-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathfflib.fs
347 lines (296 loc) · 11 KB
/
fflib.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
\ lib.fs shared library support package 16aug03py
\ Copyright (C) 1995,1996,1997,1998,2000,2003,2005,2006,2007,2008 Free Software Foundation, Inc.
\ This file is part of Gforth.
\ Gforth is free software; you can redistribute it and/or
\ modify it under the terms of the GNU General Public License
\ as published by the Free Software Foundation, either version 3
\ of the License, or (at your option) any later version.
\ This program is distributed in the hope that it will be useful,
\ but WITHOUT ANY WARRANTY; without even the implied warranty of
\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\ GNU General Public License for more details.
\ You should have received a copy of the GNU General Public License
\ along with this program. If not, see http://www.gnu.org/licenses/.
\ replacements for former primitives
c-library fflib
s" avcall" add-lib
s" callback" add-lib
\c #include <avcall.h>
\c #include <callback.h>
\c static av_alist alist;
\c static va_alist gforth_clist;
\c #ifndef HAS_BACKLINK
\c static void **saved_gforth_pointers;
\c #endif
\c static float frv;
\c static int irv;
\c static double drv;
\c static long long llrv;
\c static void * prv;
\c typedef void *Label;
\c typedef Label *Xt;
\c
\c void gforth_callback_ffcall(Xt* fcall, void * alist)
\c {
\c #ifndef HAS_BACKLINK
\c void **gforth_pointers = saved_gforth_pointers;
\c #endif
\c {
\c /* save global valiables */
\c Cell *rp = gforth_RP;
\c Cell *sp = gforth_SP;
\c Float *fp = gforth_FP;
\c char *lp = gforth_LP;
\c va_alist clist = gforth_clist;
\c
\c gforth_clist = (va_alist)alist;
\c
\c gforth_engine(fcall, sp, rp, fp, lp, gforth_UP);
\c
\c /* restore global variables */
\c gforth_RP = rp;
\c gforth_SP = sp;
\c gforth_FP = fp;
\c gforth_LP = lp;
\c gforth_clist = clist;
\c }
\c }
\c #define av_start_void1(c_addr) av_start_void(alist, c_addr)
c-function av-start-void av_start_void1 a -- void
\c #define av_start_int1(c_addr) av_start_int(alist, c_addr, &irv)
c-function av-start-int av_start_int1 a -- void
\c #define av_start_float1(c_addr) av_start_float(alist, c_addr, &frv)
c-function av-start-float av_start_float1 a -- void
\c #define av_start_double1(c_addr) av_start_double(alist, c_addr, &drv)
c-function av-start-double av_start_double1 a -- void
\c #define av_start_longlong1(c_addr) av_start_longlong(alist, c_addr, &llrv)
c-function av-start-longlong av_start_longlong1 a -- void
\c #define av_start_ptr1(c_addr) av_start_ptr(alist, c_addr, void *, &prv)
c-function av-start-ptr av_start_ptr1 a -- void
\c #define av_int1(w) av_int(alist,w)
c-function av-int av_int1 n -- void
\c #define av_float1(r) av_float(alist,r)
c-function av-float av_float1 r -- void
\c #define av_double1(r) av_double(alist,r)
c-function av-double av_double1 r -- void
\c #define av_longlong1(d) av_longlong(alist,d)
c-function av-longlong av_longlong1 d -- void
\c #define av_ptr1(a) av_ptr(alist, void *, a)
c-function av-ptr av_ptr1 a -- void
\c #define av_call_void() av_call(alist)
c-function av-call-void av_call_void -- void
\c #define av_call_int() (av_call(alist), irv)
c-function av-call-int av_call_int -- n
\c #define av_call_float() (av_call(alist), frv)
c-function av-call-float av_call_float -- r
\c #define av_call_double() (av_call(alist), drv)
c-function av-call-double av_call_double -- r
\c #define av_call_longlong() (av_call(alist), llrv)
c-function av-call-longlong av_call_longlong -- d
\c #define av_call_ptr() (av_call(alist), prv)
c-function av-call-ptr av_call_ptr -- a
\c #define alloc_callback1(a_ip) alloc_callback(gforth_callback_ffcall, (Xt *)a_ip)
c-function alloc-callback alloc_callback1 a -- a
\c #define va_start_void1() va_start_void(gforth_clist)
c-function va-start-void va_start_void1 -- void
\c #define va_start_int1() va_start_int(gforth_clist)
c-function va-start-int va_start_int1 -- void
\c #define va_start_longlong1() va_start_longlong(gforth_clist)
c-function va-start-longlong va_start_longlong1 -- void
\c #define va_start_ptr1() va_start_ptr(gforth_clist, (char *))
c-function va-start-ptr va_start_ptr1 -- void
\c #define va_start_float1() va_start_float(gforth_clist)
c-function va-start-float va_start_float1 -- void
\c #define va_start_double1() va_start_double(gforth_clist)
c-function va-start-double va_start_double1 -- void
\c #define va_arg_int1() va_arg_int(gforth_clist)
c-function va-arg-int va_arg_int1 -- n
\c #define va_arg_longlong1() va_arg_longlong(gforth_clist)
c-function va-arg-longlong va_arg_longlong1 -- d
\c #define va_arg_ptr1() va_arg_ptr(gforth_clist, char *)
c-function va-arg-ptr va_arg_ptr1 -- a
\c #define va_arg_float1() va_arg_float(gforth_clist)
c-function va-arg-float va_arg_float1 -- r
\c #define va_arg_double1() va_arg_double(gforth_clist)
c-function va-arg-double va_arg_double1 -- r
\c #define va_return_void1() va_return_void(gforth_clist)
c-function va-return-void1 va_return_void1 -- void
\c #define va_return_int1(w) va_return_int(gforth_clist,w)
c-function va-return-int1 va_return_int1 n -- void
\c #define va_return_ptr1(w) va_return_ptr(gforth_clist, void *, w)
c-function va-return-ptr1 va_return_ptr1 a -- void
\c #define va_return_longlong1(d) va_return_longlong(gforth_clist,d)
c-function va-return-longlong1 va_return_longlong1 d -- void
\c #define va_return_float1(r) va_return_float(gforth_clist,r)
c-function va-return-float1 va_return_float1 r -- void
\c #define va_return_double1(r) va_return_double(gforth_clist,r)
c-function va-return-double1 va_return_double1 r -- void
end-c-library
: av-int-r 2r> >r av-int ;
: av-float-r f@local0 lp+ av-float ;
: av-double-r f@local0 lp+ av-double ;
: av-longlong-r r> 2r> rot >r av-longlong ;
: av-ptr-r 2r> >r av-ptr ;
: va-return-void va-return-void1 0 (bye) ;
: va-return-int va-return-int1 0 (bye) ;
: va-return-ptr va-return-ptr1 0 (bye) ;
: va-return-longlong va-return-longlong1 0 (bye) ;
: va-return-float va-return-float1 0 (bye) ;
: va-return-double va-return-double1 0 (bye) ;
\ start of fflib proper
Variable libs 0 libs !
\ links between libraries
Variable thisproc
Variable thislib
Variable revdec revdec off
\ turn revdec on to compile bigFORTH libraries
Variable revarg revarg off
\ turn revarg on to compile declarations with reverse arguments
Variable legacy legacy off
\ turn legacy on to compile bigFORTH legacy libraries
Vocabulary c-decl
Vocabulary cb-decl
: @lib ( lib -- )
\G obtains library handle
cell+ dup 2 cells + count open-lib
dup 0= abort" Library not found" swap ! ;
: @proc ( lib addr -- )
\G obtains symbol address
cell+ tuck cell+ @ count rot cell+ @
lib-sym dup 0= abort" Proc not found!" swap ! ;
: proc, ( lib -- )
\G allocates and initializes proc stub
\G stub format:
\G linked list in library
\G address of proc
\G ptr to OS name of symbol as counted string
\G threaded code for invocation
here dup thisproc !
swap 2 cells + dup @ A, !
0 , 0 A, ;
Defer legacy-proc ' noop IS legacy-proc
: proc: ( lib "name" -- )
\G Creates a named proc stub
Create proc, 0 also c-decl
legacy @ IF legacy-proc THEN
DOES> ( x1 .. xn -- r )
dup cell+ @ swap 3 cells + >r ;
Variable ind-call ind-call off
: fptr ( "name" -- )
Create here thisproc ! 0 , 0 , 0 , 0 also c-decl ind-call on
DOES> 3 cells + >r ;
: library ( "name" "file" -- )
\G loads library "file" and creates a proc defining word "name"
\G library format:
\G linked list of libraries
\G library handle
\G linked list of library's procs
\G OS name of library as counted string
Create here libs @ A, dup libs !
0 , 0 A, parse-name string, @lib
DOES> ( -- ) dup thislib ! proc: ;
: init-shared-libs ( -- )
defers 'cold
0 libs BEGIN
@ dup WHILE
dup REPEAT
drop BEGIN
dup WHILE
>r
r@ @lib
r@ 2 cells + BEGIN
@ dup WHILE
r@ over @proc REPEAT
drop rdrop
REPEAT
drop ;
' init-shared-libs IS 'cold
: argtype ( revxt pushxt fwxt "name" -- )
Create , , , ;
: arg@ ( arg -- argxt pushxt )
revarg @ IF 2 cells + @ ['] noop swap ELSE 2@ THEN ;
: arg, ( xt -- )
dup ['] noop = IF drop EXIT THEN compile, ;
: decl, ( 0 arg1 .. argn call start -- )
2@ compile, >r
revdec @ IF 0 >r
BEGIN dup WHILE >r REPEAT
BEGIN r> dup WHILE arg@ arg, REPEAT drop
BEGIN dup WHILE arg, REPEAT drop
ELSE 0 >r
BEGIN dup WHILE arg@ arg, >r REPEAT drop
BEGIN r> dup WHILE arg, REPEAT drop
THEN
r> compile, postpone EXIT ;
: symbol, ( "c-symbol" -- )
here thisproc @ 2 cells + ! parse-name s,
thislib @ thisproc @ @proc ;
: rettype ( endxt startxt "name" -- )
Create 2,
DOES> decl, ind-call @ 0= IF symbol, THEN
previous revarg off ind-call off ;
also c-decl definitions
: <rev> revarg on ;
' av-int ' av-int-r ' >r argtype int
' av-float ' av-float-r ' f>l argtype sf
' av-double ' av-double-r ' f>l argtype df
' av-longlong ' av-longlong-r ' 2>r argtype dlong
' av-ptr ' av-ptr-r ' >r argtype ptr
' av-call-void ' av-start-void rettype (void)
' av-call-int ' av-start-int rettype (int)
' av-call-float ' av-start-float rettype (sf)
' av-call-double ' av-start-double rettype (fp)
' av-call-longlong ' av-start-longlong rettype (dlong)
' av-call-ptr ' av-start-ptr rettype (ptr)
: (addr) postpone EXIT drop symbol, previous revarg off ;
previous definitions
\ legacy support for old library interfaces
\ interface to old vararg stuff not implemented yet
also c-decl
:noname ( n 0 -- 0 int1 .. intn )
legacy @ 0< revarg !
swap 0 ?DO int LOOP (int)
; IS legacy-proc
: (int) ( n -- )
>r ' execute r> 0 ?DO int LOOP (int) ;
: (void) ( n -- )
>r ' execute r> 0 ?DO int LOOP (void) ;
: (float) ( n -- )
>r ' execute r> 0 ?DO df LOOP (fp) ;
previous
\ callback stuff
Variable callbacks
\G link between callbacks
: callback ( -- )
Create 0 ] postpone >r also cb-decl
DOES>
Create here >r 0 , callbacks @ A, r@ callbacks !
swap postpone Literal postpone call , postpone EXIT
r> dup cell+ cell+ alloc-callback swap !
DOES> @ ;
: callback; ( 0 xt1 .. xtn -- )
BEGIN over WHILE compile, REPEAT
postpone r> postpone execute compile, drop
postpone EXIT postpone [ previous ; immediate
: va-ret ( xt xt -- )
Create A, A, immediate
DOES> 2@ compile, ;
: init-callbacks ( -- )
defers 'cold callbacks 1 cells -
BEGIN cell+ @ dup WHILE dup cell+ cell+ alloc-callback over !
REPEAT drop ;
' init-callbacks IS 'cold
also cb-decl definitions
\ arguments
' va-arg-int Alias int
' va-arg-float Alias sf
' va-arg-double Alias df
' va-arg-longlong Alias dlong
' va-arg-ptr Alias ptr
' va-return-void ' va-start-void va-ret (void)
' va-return-int ' va-start-int va-ret (int)
' va-return-float ' va-start-float va-ret (sf)
' va-return-double ' va-start-double va-ret (fp)
' va-return-longlong ' va-start-longlong va-ret (dlong)
' va-return-ptr ' va-start-ptr va-ret (ptr)
previous definitions