Merge from vendor branch BINUTILS:
[dragonfly.git] / sys / boot / ficl / ficl.h
1 /*******************************************************************
2 ** f i c l . h
3 ** Forth Inspired Command Language
4 ** Author: John Sadler (john_sadler@alum.mit.edu)
5 ** Created: 19 July 1997
6 ** Dedicated to RHS, in loving memory
7 ** $Id: ficl.h,v 1.18 2001/12/05 07:21:34 jsadler Exp $
8 *******************************************************************/
9 /*
10 ** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
11 ** All rights reserved.
12 **
13 ** Get the latest Ficl release at http://ficl.sourceforge.net
14 **
15 ** I am interested in hearing from anyone who uses ficl. If you have
16 ** a problem, a success story, a defect, an enhancement request, or
17 ** if you would like to contribute to the ficl release, please
18 ** contact me by email at the address above.
19 **
20 ** L I C E N S E  and  D I S C L A I M E R
21 ** 
22 ** Redistribution and use in source and binary forms, with or without
23 ** modification, are permitted provided that the following conditions
24 ** are met:
25 ** 1. Redistributions of source code must retain the above copyright
26 **    notice, this list of conditions and the following disclaimer.
27 ** 2. Redistributions in binary form must reproduce the above copyright
28 **    notice, this list of conditions and the following disclaimer in the
29 **    documentation and/or other materials provided with the distribution.
30 **
31 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
32 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 ** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
35 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 ** SUCH DAMAGE.
42 */
43
44 /*
45  * $FreeBSD: src/sys/boot/ficl/ficl.h,v 1.20 2002/04/09 17:45:11 dcs Exp $
46  * $DragonFly: src/sys/boot/ficl/ficl.h,v 1.3 2003/11/10 06:08:33 dillon Exp $
47  */
48
49 #if !defined (__FICL_H__)
50 #define __FICL_H__
51 /*
52 ** Ficl (Forth-inspired command language) is an ANS Forth
53 ** interpreter written in C. Unlike traditional Forths, this
54 ** interpreter is designed to be embedded into other systems
55 ** as a command/macro/development prototype language. 
56 **
57 ** Where Forths usually view themselves as the center of the system
58 ** and expect the rest of the system to be coded in Forth, Ficl
59 ** acts as a component of the system. It is easy to export 
60 ** code written in C or ASM to Ficl in the style of TCL, or to invoke
61 ** Ficl code from a compiled module. This allows you to do incremental
62 ** development in a way that combines the best features of threaded 
63 ** languages (rapid development, quick code/test/debug cycle,
64 ** reasonably fast) with the best features of C (everyone knows it,
65 ** easier to support large blocks of code, efficient, type checking).
66 **
67 ** Ficl provides facilities for interoperating
68 ** with programs written in C: C functions can be exported to Ficl,
69 ** and Ficl commands can be executed via a C calling interface. The
70 ** interpreter is re-entrant, so it can be used in multiple instances
71 ** in a multitasking system. Unlike Forth, Ficl's outer interpreter
72 ** expects a text block as input, and returns to the caller after each
73 ** text block, so the "data pump" is somewhere in external code. This
74 ** is more like TCL than Forth, which usually expcets to be at the center
75 ** of the system, requesting input at its convenience. Each Ficl virtual 
76 ** machine can be bound to a different I/O channel, and is independent
77 ** of all others in in the same address space except that all virtual
78 ** machines share a common dictionary (a sort or open symbol table that
79 ** defines all of the elements of the language).
80 **
81 ** Code is written in ANSI C for portability. 
82 **
83 ** Summary of Ficl features and constraints:
84 ** - Standard: Implements the ANSI Forth CORE word set and part 
85 **   of the CORE EXT word-set, SEARCH and SEARCH EXT, TOOLS and
86 **   TOOLS EXT, LOCAL and LOCAL ext and various extras.
87 ** - Extensible: you can export code written in Forth, C, 
88 **   or asm in a straightforward way. Ficl provides open
89 **   facilities for extending the language in an application
90 **   specific way. You can even add new control structures!
91 ** - Ficl and C can interact in two ways: Ficl can encapsulate
92 **   C code, or C code can invoke Ficl code.
93 ** - Thread-safe, re-entrant: The shared system dictionary 
94 **   uses a locking mechanism that you can either supply
95 **   or stub out to provide exclusive access. Each Ficl
96 **   virtual machine has an otherwise complete state, and
97 **   each can be bound to a separate I/O channel (or none at all).
98 ** - Simple encapsulation into existing systems: a basic implementation
99 **   requires three function calls (see the example program in testmain.c).
100 ** - ROMable: Ficl is designed to work in RAM-based and ROM code / RAM data
101 **   environments. It does require somewhat more memory than a pure
102 **   ROM implementation because it builds its system dictionary in 
103 **   RAM at startup time.
104 ** - Written an ANSI C to be as simple as I can make it to understand,
105 **   support, debug, and port. Compiles without complaint at /Az /W4 
106 **   (require ANSI C, max warnings) under Microsoft VC++ 5.
107 ** - Does full 32 bit math (but you need to implement
108 **   two mixed precision math primitives (see sysdep.c))
109 ** - Indirect threaded interpreter is not the fastest kind of
110 **   Forth there is (see pForth 68K for a really fast subroutine
111 **   threaded interpreter), but it's the cleanest match to a
112 **   pure C implementation.
113 **
114 ** P O R T I N G   F i c l
115 **
116 ** To install Ficl on your target system, you need an ANSI C compiler
117 ** and its runtime library. Inspect the system dependent macros and
118 ** functions in sysdep.h and sysdep.c and edit them to suit your
119 ** system. For example, INT16 is a short on some compilers and an
120 ** int on others. Check the default CELL alignment controlled by
121 ** FICL_ALIGN. If necessary, add new definitions of ficlMalloc, ficlFree,
122 ** ficlLockDictionary, and ficlTextOut to work with your operating system.
123 ** Finally, use testmain.c as a guide to installing the Ficl system and 
124 ** one or more virtual machines into your code. You do not need to include
125 ** testmain.c in your build.
126 **
127 ** T o   D o   L i s t
128 **
129 ** 1. Unimplemented system dependent CORE word: key
130 ** 2. Ficl uses the PAD in some CORE words - this violates the standard,
131 **    but it's cleaner for a multithreaded system. I'll have to make a
132 **    second pad for reference by the word PAD to fix this.
133 **
134 ** F o r   M o r e   I n f o r m a t i o n
135 **
136 ** Web home of ficl
137 **   http://ficl.sourceforge.net
138 ** Check this website for Forth literature (including the ANSI standard)
139 **   http://www.taygeta.com/forthlit.html
140 ** and here for software and more links
141 **   http://www.taygeta.com/forth.html
142 **
143 ** Obvious Performance enhancement opportunities
144 ** Compile speed
145 ** - work on interpret speed
146 ** - turn off locals (FICL_WANT_LOCALS)
147 ** Interpret speed 
148 ** - Change inner interpreter (and everything else)
149 **   so that a definition is a list of pointers to functions
150 **   and inline data rather than pointers to words. This gets
151 **   rid of vm->runningWord and a level of indirection in the
152 **   inner loop. I'll look at it for ficl 3.0
153 ** - Make the main hash table a bigger prime (HASHSIZE)
154 ** - FORGET about twiddling the hash function - my experience is
155 **   that that is a waste of time.
156 ** - Eliminate the need to pass the pVM parameter on the stack
157 **   by dedicating a register to it. Most words need access to the
158 **   vm, but the parameter passing overhead can be reduced. One way
159 **   requires that the host OS have a task switch callout. Create
160 **   a global variable for the running VM and refer to it in words
161 **   that need VM access. Alternative: use thread local storage. 
162 **   For single threaded implementations, you can just use a global.
163 **   The first two solutions create portability problems, so I
164 **   haven't considered doing them. Another possibility is to
165 **   declare the pVm parameter to be "register", and hope the compiler
166 **   pays attention.
167 **
168 */
169
170 /*
171 ** Revision History:
172 ** 
173 ** 15 Apr 1999 (sadler) Merged FreeBSD changes for exception wordset and
174 ** counted strings in ficlExec. 
175 ** 12 Jan 1999 (sobral) Corrected EVALUATE behavior. Now TIB has an
176 ** "end" field, and all words respect this. ficlExec is passed a "size"
177 ** of TIB, as well as vmPushTib. This size is used to calculate the "end"
178 ** of the string, ie, base+size. If the size is not known, pass -1.
179 **
180 ** 10 Jan 1999 (sobral) EXCEPTION word set has been added, and existing
181 ** words has been modified to conform to EXCEPTION EXT word set. 
182 **
183 ** 27 Aug 1998 (sadler) testing and corrections for LOCALS, LOCALS EXT,
184 **  SEARCH / SEARCH EXT, TOOLS / TOOLS EXT. 
185 **  Added .X to display in hex, PARSE and PARSE-WORD to supplement WORD,
186 **  EMPTY to clear stack.
187 **
188 ** 29 jun 1998 (sadler) added variable sized hash table support
189 **  and ANS Forth optional SEARCH & SEARCH EXT word set.
190 ** 26 May 1998 (sadler) 
191 **  FICL_PROMPT macro
192 ** 14 April 1998 (sadler) V1.04
193 **  Ficlwin: Windows version, Skip Carter's Linux port
194 ** 5 March 1998 (sadler) V1.03
195 **  Bug fixes -- passes John Ryan's ANS test suite "core.fr"
196 **
197 ** 24 February 1998 (sadler) V1.02
198 ** -Fixed bugs in <# # #>
199 ** -Changed FICL_WORD so that storage for the name characters
200 **  can be allocated from the dictionary as needed rather than 
201 **  reserving 32 bytes in each word whether needed or not - 
202 **  this saved 50% of the dictionary storage requirement.
203 ** -Added words in testmain for Win32 functions system,chdir,cwd,
204 **  also added a word that loads and evaluates a file.
205 **
206 ** December 1997 (sadler)
207 ** -Added VM_RESTART exception handling in ficlExec -- this lets words
208 **  that require additional text to succeed (like :, create, variable...)
209 **  recover gracefully from an empty input buffer rather than emitting
210 **  an error message. Definitions can span multiple input blocks with
211 **  no restrictions.
212 ** -Changed #include order so that <assert.h> is included in sysdep.h,
213 **  and sysdep is included in all other files. This lets you define
214 **  NDEBUG in sysdep.h to disable assertions if you want to.
215 ** -Make PC specific system dependent code conditional on _M_IX86
216 **  defined so that ports can coexist in sysdep.h/sysdep.c
217 */
218
219 #ifdef __cplusplus
220 extern "C" {
221 #endif
222
223 #include "sysdep.h"
224 #include <limits.h> /* UCHAR_MAX */
225
226 /*
227 ** Forward declarations... read on.
228 */
229 struct ficl_word;
230 typedef struct ficl_word FICL_WORD;
231 struct vm;
232 typedef struct vm FICL_VM;
233 struct ficl_dict;
234 typedef struct ficl_dict FICL_DICT;
235 struct ficl_system;
236 typedef struct ficl_system FICL_SYSTEM;
237 struct ficl_system_info;
238 typedef struct ficl_system_info FICL_SYSTEM_INFO;
239
240 /* 
241 ** the Good Stuff starts here...
242 */
243 #define FICL_VER        "3.02"
244 #define FICL_VER_MAJOR  3
245 #define FICL_VER_MINOR  2
246 #if !defined (FICL_PROMPT)
247 #define FICL_PROMPT "ok> "
248 #endif
249
250 /*
251 ** ANS Forth requires false to be zero, and true to be the ones
252 ** complement of false... that unifies logical and bitwise operations
253 ** nicely.
254 */
255 #define FICL_TRUE  ((unsigned long)~(0L))
256 #define FICL_FALSE (0)
257 #define FICL_BOOL(x) ((x) ? FICL_TRUE : FICL_FALSE)
258
259
260 /*
261 ** A CELL is the main storage type. It must be large enough
262 ** to contain a pointer or a scalar. In order to accommodate 
263 ** 32 bit and 64 bit processors, use abstract types for int, 
264 ** unsigned, and float.
265 */
266 typedef union _cell
267 {
268     FICL_INT i;
269     FICL_UNS u;
270 #if (FICL_WANT_FLOAT)
271     FICL_FLOAT f;
272 #endif
273     void *p;
274     void (*fn)(void);
275 } CELL;
276
277 /*
278 ** LVALUEtoCELL does a little pointer trickery to cast any CELL sized
279 ** lvalue (informal definition: an expression whose result has an
280 ** address) to CELL. Remember that constants and casts are NOT
281 ** themselves lvalues!
282 */
283 #define LVALUEtoCELL(v) (*(CELL *)&v)
284
285 /*
286 ** PTRtoCELL is a cast through void * intended to satisfy the
287 ** most outrageously pedantic compiler... (I won't mention 
288 ** its name)
289 */
290 #define PTRtoCELL (CELL *)(void *)
291 #define PTRtoSTRING (FICL_STRING *)(void *)
292
293 /*
294 ** Strings in FICL are stored in Pascal style - with a count
295 ** preceding the text. We'll also NULL-terminate them so that 
296 ** they work with the usual C lib string functions. (Belt &
297 ** suspenders? You decide.)
298 ** STRINGINFO hides the implementation with a couple of
299 ** macros for use in internal routines.
300 */
301
302 typedef unsigned char FICL_COUNT;
303 #define FICL_STRING_MAX UCHAR_MAX
304 typedef struct _ficl_string
305 {
306     FICL_COUNT count;
307     char text[1];
308 } FICL_STRING;
309
310 typedef struct 
311 {
312     FICL_UNS count;
313     char *cp;
314 } STRINGINFO;
315
316 #define SI_COUNT(si) (si.count)
317 #define SI_PTR(si)   (si.cp)
318 #define SI_SETLEN(si, len) (si.count = (FICL_UNS)(len))
319 #define SI_SETPTR(si, ptr) (si.cp = (char *)(ptr))
320 /* 
321 ** Init a STRINGINFO from a pointer to NULL-terminated string
322 */
323 #define SI_PSZ(si, psz) \
324             {si.cp = psz; si.count = (FICL_COUNT)strlen(psz);}
325 /* 
326 ** Init a STRINGINFO from a pointer to FICL_STRING
327 */
328 #define SI_PFS(si, pfs) \
329             {si.cp = pfs->text; si.count = pfs->count;}
330
331 /*
332 ** Ficl uses this little structure to hold the address of 
333 ** the block of text it's working on and an index to the next
334 ** unconsumed character in the string. Traditionally, this is
335 ** done by a Text Input Buffer, so I've called this struct TIB.
336 **
337 ** Since this structure also holds the size of the input buffer,
338 ** and since evaluate requires that, let's put the size here.
339 ** The size is stored as an end-pointer because that is what the
340 ** null-terminated string aware functions find most easy to deal
341 ** with.
342 ** Notice, though, that nobody really uses this except evaluate,
343 ** so it might just be moved to FICL_VM instead. (sobral)
344 */
345 typedef struct
346 {
347     FICL_INT index;
348     char *end;
349     char *cp;
350 } TIB;
351
352
353 /*
354 ** Stacks get heavy use in Ficl and Forth...
355 ** Each virtual machine implements two of them:
356 ** one holds parameters (data), and the other holds return
357 ** addresses and control flow information for the virtual
358 ** machine. (Note: C's automatic stack is implicitly used,
359 ** but not modeled because it doesn't need to be...)
360 ** Here's an abstract type for a stack
361 */
362 typedef struct _ficlStack
363 {
364     FICL_UNS nCells;    /* size of the stack */
365     CELL *pFrame;       /* link reg for stack frame */
366     CELL *sp;           /* stack pointer */
367     CELL base[1];       /* Top of stack */
368 } FICL_STACK;
369
370 /*
371 ** Stack methods... many map closely to required Forth words.
372 */
373 FICL_STACK *stackCreate   (unsigned nCells);
374 void        stackDelete   (FICL_STACK *pStack);
375 int         stackDepth    (FICL_STACK *pStack);
376 void        stackDrop     (FICL_STACK *pStack, int n);
377 CELL        stackFetch    (FICL_STACK *pStack, int n);
378 CELL        stackGetTop   (FICL_STACK *pStack);
379 void        stackLink     (FICL_STACK *pStack, int nCells);
380 void        stackPick     (FICL_STACK *pStack, int n);
381 CELL        stackPop      (FICL_STACK *pStack);
382 void       *stackPopPtr   (FICL_STACK *pStack);
383 FICL_UNS    stackPopUNS   (FICL_STACK *pStack);
384 FICL_INT    stackPopINT   (FICL_STACK *pStack);
385 void        stackPush     (FICL_STACK *pStack, CELL c);
386 void        stackPushPtr  (FICL_STACK *pStack, void *ptr);
387 void        stackPushUNS  (FICL_STACK *pStack, FICL_UNS u);
388 void        stackPushINT  (FICL_STACK *pStack, FICL_INT i);
389 void        stackReset    (FICL_STACK *pStack);
390 void        stackRoll     (FICL_STACK *pStack, int n);
391 void        stackSetTop   (FICL_STACK *pStack, CELL c);
392 void        stackStore    (FICL_STACK *pStack, int n, CELL c);
393 void        stackUnlink   (FICL_STACK *pStack);
394
395 #if (FICL_WANT_FLOAT)
396 float       stackPopFloat (FICL_STACK *pStack);
397 void        stackPushFloat(FICL_STACK *pStack, FICL_FLOAT f);
398 #endif
399
400 /*
401 ** Shortcuts (Guy Carver)
402 */
403 #define PUSHPTR(p)   stackPushPtr(pVM->pStack,p)
404 #define PUSHUNS(u)   stackPushUNS(pVM->pStack,u)
405 #define PUSHINT(i)   stackPushINT(pVM->pStack,i)
406 #define PUSHFLOAT(f) stackPushFloat(pVM->fStack,f)
407 #define PUSH(c)      stackPush(pVM->pStack,c)
408 #define POPPTR()     stackPopPtr(pVM->pStack)
409 #define POPUNS()     stackPopUNS(pVM->pStack)
410 #define POPINT()     stackPopINT(pVM->pStack)
411 #define POPFLOAT()   stackPopFloat(pVM->fStack)
412 #define POP()        stackPop(pVM->pStack)
413 #define GETTOP()     stackGetTop(pVM->pStack)
414 #define SETTOP(c)    stackSetTop(pVM->pStack,LVALUEtoCELL(c))
415 #define GETTOPF()    stackGetTop(pVM->fStack)
416 #define SETTOPF(c)   stackSetTop(pVM->fStack,LVALUEtoCELL(c))
417 #define STORE(n,c)   stackStore(pVM->pStack,n,LVALUEtoCELL(c))
418 #define DEPTH()      stackDepth(pVM->pStack)
419 #define DROP(n)      stackDrop(pVM->pStack,n)
420 #define DROPF(n)     stackDrop(pVM->fStack,n)
421 #define FETCH(n)     stackFetch(pVM->pStack,n)
422 #define PICK(n)      stackPick(pVM->pStack,n)
423 #define PICKF(n)     stackPick(pVM->fStack,n)
424 #define ROLL(n)      stackRoll(pVM->pStack,n)
425 #define ROLLF(n)     stackRoll(pVM->fStack,n)
426
427 /* 
428 ** The virtual machine (VM) contains the state for one interpreter.
429 ** Defined operations include:
430 ** Create & initialize
431 ** Delete
432 ** Execute a block of text
433 ** Parse a word out of the input stream
434 ** Call return, and branch 
435 ** Text output
436 ** Throw an exception
437 */
438
439 typedef FICL_WORD ** IPTYPE; /* the VM's instruction pointer */
440
441 /*
442 ** Each VM has a placeholder for an output function -
443 ** this makes it possible to have each VM do I/O
444 ** through a different device. If you specify no
445 ** OUTFUNC, it defaults to ficlTextOut.
446 */
447 typedef void (*OUTFUNC)(FICL_VM *pVM, char *text, int fNewline);
448
449 /*
450 ** Each VM operates in one of two non-error states: interpreting
451 ** or compiling. When interpreting, words are simply executed.
452 ** When compiling, most words in the input stream have their
453 ** addresses inserted into the word under construction. Some words
454 ** (known as IMMEDIATE) are executed in the compile state, too.
455 */
456 /* values of STATE */
457 #define INTERPRET 0
458 #define COMPILE   1
459
460 /*
461 ** The pad is a small scratch area for text manipulation. ANS Forth
462 ** requires it to hold at least 84 characters.
463 */
464 #if !defined nPAD
465 #define nPAD 256
466 #endif
467
468 /* 
469 ** ANS Forth requires that a word's name contain {1..31} characters.
470 */
471 #if !defined nFICLNAME
472 #define nFICLNAME       31
473 #endif
474
475 /*
476 ** OK - now we can really define the VM...
477 */
478 struct vm
479 {
480     FICL_SYSTEM    *pSys;       /* Which system this VM belongs to  */
481     FICL_VM        *link;       /* Ficl keeps a VM list for simple teardown */
482     jmp_buf        *pState;     /* crude exception mechanism...     */
483     OUTFUNC         textOut;    /* Output callback - see sysdep.c   */
484     void *          pExtend;    /* vm extension pointer for app use - initialized from FICL_SYSTEM */
485     short           fRestart;   /* Set TRUE to restart runningWord  */
486     IPTYPE          ip;         /* instruction pointer              */
487     FICL_WORD      *runningWord;/* address of currently running word (often just *(ip-1) ) */
488     FICL_UNS        state;      /* compiling or interpreting        */
489     FICL_UNS        base;       /* number conversion base           */
490     FICL_STACK     *pStack;     /* param stack                      */
491     FICL_STACK     *rStack;     /* return stack                     */
492 #if FICL_WANT_FLOAT
493     FICL_STACK     *fStack;     /* float stack (optional)           */
494 #endif
495     CELL            sourceID;   /* -1 if EVALUATE, 0 if normal input */
496     TIB             tib;        /* address of incoming text string  */
497 #if FICL_WANT_USER
498     CELL            user[FICL_USER_CELLS];
499 #endif
500     char            pad[nPAD];  /* the scratch area (see above)     */
501 };
502
503 /*
504 ** A FICL_CODE points to a function that gets called to help execute
505 ** a word in the dictionary. It always gets passed a pointer to the
506 ** running virtual machine, and from there it can get the address
507 ** of the parameter area of the word it's supposed to operate on.
508 ** For precompiled words, the code is all there is. For user defined
509 ** words, the code assumes that the word's parameter area is a list
510 ** of pointers to the code fields of other words to execute, and
511 ** may also contain inline data. The first parameter is always
512 ** a pointer to a code field.
513 */
514 typedef void (*FICL_CODE)(FICL_VM *pVm);
515
516 #if 0
517 #define VM_ASSERT(pVM) assert((*(pVM->ip - 1)) == pVM->runningWord)
518 #else
519 #define VM_ASSERT(pVM) 
520 #endif
521
522 /* 
523 ** Ficl models memory as a contiguous space divided into
524 ** words in a linked list called the dictionary.
525 ** A FICL_WORD starts each entry in the list.
526 ** Version 1.02: space for the name characters is allotted from
527 ** the dictionary ahead of the word struct, rather than using
528 ** a fixed size array for each name.
529 */
530 struct ficl_word
531 {
532     struct ficl_word *link;     /* Previous word in the dictionary      */
533     UNS16 hash;
534     UNS8 flags;                 /* Immediate, Smudge, Compile-only      */
535     FICL_COUNT nName;           /* Number of chars in word name         */
536     char *name;                 /* First nFICLNAME chars of word name   */
537     FICL_CODE code;             /* Native code to execute the word      */
538     CELL param[1];              /* First data cell of the word          */
539 };
540
541 /*
542 ** Worst-case size of a word header: nFICLNAME chars in name
543 */
544 #define CELLS_PER_WORD  \
545     ( (sizeof (FICL_WORD) + nFICLNAME + sizeof (CELL)) \
546                           / (sizeof (CELL)) )
547
548 int wordIsImmediate(FICL_WORD *pFW);
549 int wordIsCompileOnly(FICL_WORD *pFW);
550
551 /* flag values for word header */
552 #define FW_IMMEDIATE    1   /* execute me even if compiling */
553 #define FW_COMPILE      2   /* error if executed when not compiling */
554 #define FW_SMUDGE       4   /* definition in progress - hide me */
555 #define FW_ISOBJECT     8   /* word is an object or object member variable */
556
557 #define FW_COMPIMMED    (FW_IMMEDIATE | FW_COMPILE)
558 #define FW_DEFAULT      0
559
560
561 /*
562 ** Exit codes for vmThrow
563 */
564 #define VM_INNEREXIT -256   /* tell ficlExecXT to exit inner loop */
565 #define VM_OUTOFTEXT -257   /* hungry - normal exit */
566 #define VM_RESTART   -258   /* word needs more text to succeed - re-run it */
567 #define VM_USEREXIT  -259   /* user wants to quit */
568 #define VM_ERREXIT   -260   /* interp found an error */
569 #define VM_BREAK     -261   /* debugger breakpoint */
570 #define VM_ABORT       -1   /* like errexit -- abort */
571 #define VM_ABORTQ      -2   /* like errexit -- abort" */
572 #define VM_QUIT       -56   /* like errexit, but leave pStack & base alone */
573
574
575 void        vmBranchRelative(FICL_VM *pVM, int offset);
576 FICL_VM *   vmCreate       (FICL_VM *pVM, unsigned nPStack, unsigned nRStack);
577 void        vmDelete       (FICL_VM *pVM);
578 void        vmExecute      (FICL_VM *pVM, FICL_WORD *pWord);
579 FICL_DICT  *vmGetDict      (FICL_VM *pVM);
580 char *      vmGetString    (FICL_VM *pVM, FICL_STRING *spDest, char delimiter);
581 STRINGINFO  vmGetWord      (FICL_VM *pVM);
582 STRINGINFO  vmGetWord0     (FICL_VM *pVM);
583 int         vmGetWordToPad (FICL_VM *pVM);
584 STRINGINFO  vmParseString  (FICL_VM *pVM, char delimiter);
585 STRINGINFO  vmParseStringEx(FICL_VM *pVM, char delimiter, char fSkipLeading);
586 CELL        vmPop          (FICL_VM *pVM);
587 void        vmPush         (FICL_VM *pVM, CELL c);
588 void        vmPopIP        (FICL_VM *pVM);
589 void        vmPushIP       (FICL_VM *pVM, IPTYPE newIP);
590 void        vmQuit         (FICL_VM *pVM);
591 void        vmReset        (FICL_VM *pVM);
592 void        vmSetTextOut   (FICL_VM *pVM, OUTFUNC textOut);
593 void        vmTextOut      (FICL_VM *pVM, char *text, int fNewline);
594 void        vmTextOut      (FICL_VM *pVM, char *text, int fNewline);
595 void        vmThrow        (FICL_VM *pVM, int except);
596 void        vmThrowErr     (FICL_VM *pVM, char *fmt, ...);
597
598 #define vmGetRunningWord(pVM) ((pVM)->runningWord)
599
600
601 /*
602 ** The inner interpreter - coded as a macro (see note for 
603 ** INLINE_INNER_LOOP in sysdep.h for complaints about VC++ 5
604 */
605 #define M_VM_STEP(pVM) \
606         FICL_WORD *tempFW = *(pVM)->ip++; \
607         (pVM)->runningWord = tempFW; \
608         tempFW->code(pVM); 
609
610 #define M_INNER_LOOP(pVM) \
611     for (;;)  { M_VM_STEP(pVM) }
612
613
614 #if INLINE_INNER_LOOP != 0
615 #define     vmInnerLoop(pVM) M_INNER_LOOP(pVM)
616 #else
617 void        vmInnerLoop(FICL_VM *pVM);
618 #endif
619
620 /*
621 ** vmCheckStack needs a vm pointer because it might have to say
622 ** something if it finds a problem. Parms popCells and pushCells
623 ** correspond to the number of parameters on the left and right of 
624 ** a word's stack effect comment.
625 */
626 void        vmCheckStack(FICL_VM *pVM, int popCells, int pushCells);
627 #if FICL_WANT_FLOAT
628 void        vmCheckFStack(FICL_VM *pVM, int popCells, int pushCells);
629 #endif
630
631 /*
632 ** TIB access routines...
633 ** ANS forth seems to require the input buffer to be represented 
634 ** as a pointer to the start of the buffer, and an index to the
635 ** next character to read.
636 ** PushTib points the VM to a new input string and optionally
637 **  returns a copy of the current state
638 ** PopTib restores the TIB state given a saved TIB from PushTib
639 ** GetInBuf returns a pointer to the next unused char of the TIB
640 */
641 void        vmPushTib  (FICL_VM *pVM, char *text, FICL_INT nChars, TIB *pSaveTib);
642 void        vmPopTib   (FICL_VM *pVM, TIB *pTib);
643 #define     vmGetInBuf(pVM)      ((pVM)->tib.cp + (pVM)->tib.index)
644 #define     vmGetInBufLen(pVM)   ((pVM)->tib.end - (pVM)->tib.cp)
645 #define     vmGetInBufEnd(pVM)   ((pVM)->tib.end)
646 #define     vmGetTibIndex(pVM)    (pVM)->tib.index
647 #define     vmSetTibIndex(pVM, i) (pVM)->tib.index = i
648 #define     vmUpdateTib(pVM, str) (pVM)->tib.index = (str) - (pVM)->tib.cp
649
650 /*
651 ** Generally useful string manipulators omitted by ANSI C...
652 ** ltoa complements strtol
653 */
654 #if defined(_WIN32) && !FICL_MAIN
655 /* #SHEESH
656 ** Why do Microsoft Meatballs insist on contaminating
657 ** my namespace with their string functions???
658 */
659 #pragma warning(disable: 4273)
660 #endif
661
662 int        isPowerOfTwo(FICL_UNS u);
663
664 char       *ltoa( FICL_INT value, char *string, int radix );
665 char       *ultoa(FICL_UNS value, char *string, int radix );
666 char        digit_to_char(int value);
667 char       *strrev( char *string );
668 char       *skipSpace(char *cp, char *end);
669 char       *caseFold(char *cp);
670 int         strincmp(char *cp1, char *cp2, FICL_UNS count);
671
672 #if defined(_WIN32) && !FICL_MAIN
673 #pragma warning(default: 4273)
674 #endif
675
676 /*
677 ** Ficl hash table - variable size.
678 ** assert(size > 0)
679 ** If size is 1, the table degenerates into a linked list.
680 ** A WORDLIST (see the search order word set in DPANS) is
681 ** just a pointer to a FICL_HASH in this implementation.
682 */
683 #if !defined HASHSIZE /* Default size of hash table. For most uniform */
684 #define HASHSIZE 241  /*   performance, use a prime number!   */
685 #endif
686
687 typedef struct ficl_hash 
688 {
689     struct ficl_hash *link;  /* link to parent class wordlist for OO */
690     char      *name;         /* optional pointer to \0 terminated wordlist name */
691     unsigned   size;         /* number of buckets in the hash */
692     FICL_WORD *table[1];
693 } FICL_HASH;
694
695 void        hashForget    (FICL_HASH *pHash, void *where);
696 UNS16       hashHashCode  (STRINGINFO si);
697 void        hashInsertWord(FICL_HASH *pHash, FICL_WORD *pFW);
698 FICL_WORD  *hashLookup    (FICL_HASH *pHash, STRINGINFO si, UNS16 hashCode);
699 void        hashReset     (FICL_HASH *pHash);
700
701 /*
702 ** A Dictionary is a linked list of FICL_WORDs. It is also Ficl's
703 ** memory model. Description of fields:
704 **
705 ** here -- points to the next free byte in the dictionary. This
706 **      pointer is forced to be CELL-aligned before a definition is added.
707 **      Do not assume any specific alignment otherwise - Use dictAlign().
708 **
709 ** smudge -- pointer to word currently being defined (or last defined word)
710 **      If the definition completes successfully, the word will be
711 **      linked into the hash table. If unsuccessful, dictUnsmudge
712 **      uses this pointer to restore the previous state of the dictionary.
713 **      Smudge prevents unintentional recursion as a side-effect: the
714 **      dictionary search algo examines only completed definitions, so a 
715 **      word cannot invoke itself by name. See the ficl word "recurse".
716 **      NOTE: smudge always points to the last word defined. IMMEDIATE
717 **      makes use of this fact. Smudge is initially NULL.
718 **
719 ** pForthWords -- pointer to the default wordlist (FICL_HASH).
720 **      This is the initial compilation list, and contains all
721 **      ficl's precompiled words.
722 **
723 ** pCompile -- compilation wordlist - initially equal to pForthWords
724 ** pSearch  -- array of pointers to wordlists. Managed as a stack.
725 **      Highest index is the first list in the search order.
726 ** nLists   -- number of lists in pSearch. nLists-1 is the highest 
727 **      filled slot in pSearch, and points to the first wordlist
728 **      in the search order
729 ** size -- number of cells in the dictionary (total)
730 ** dict -- start of data area. Must be at the end of the struct.
731 */
732 struct ficl_dict
733 {
734     CELL *here;
735     FICL_WORD *smudge;
736     FICL_HASH *pForthWords;
737     FICL_HASH *pCompile;
738     FICL_HASH *pSearch[FICL_DEFAULT_VOCS];
739     int        nLists;
740     unsigned   size;    /* Number of cells in dict (total)*/
741     CELL       *dict;   /* Base of dictionary memory      */
742 };
743
744 void       *alignPtr(void *ptr);
745 void        dictAbortDefinition(FICL_DICT *pDict);
746 void        dictAlign      (FICL_DICT *pDict);
747 int         dictAllot      (FICL_DICT *pDict, int n);
748 int         dictAllotCells (FICL_DICT *pDict, int nCells);
749 void        dictAppendCell (FICL_DICT *pDict, CELL c);
750 void        dictAppendChar (FICL_DICT *pDict, char c);
751 FICL_WORD  *dictAppendWord (FICL_DICT *pDict, 
752                            char *name, 
753                            FICL_CODE pCode, 
754                            UNS8 flags);
755 FICL_WORD  *dictAppendWord2(FICL_DICT *pDict, 
756                            STRINGINFO si, 
757                            FICL_CODE pCode, 
758                            UNS8 flags);
759 void        dictAppendUNS  (FICL_DICT *pDict, FICL_UNS u);
760 int         dictCellsAvail (FICL_DICT *pDict);
761 int         dictCellsUsed  (FICL_DICT *pDict);
762 void        dictCheck      (FICL_DICT *pDict, FICL_VM *pVM, int n);
763 FICL_DICT  *dictCreate(unsigned nCELLS);
764 FICL_DICT  *dictCreateHashed(unsigned nCells, unsigned nHash);
765 FICL_HASH  *dictCreateWordlist(FICL_DICT *dp, int nBuckets);
766 void        dictDelete     (FICL_DICT *pDict);
767 void        dictEmpty      (FICL_DICT *pDict, unsigned nHash);
768 #if FICL_WANT_FLOAT
769 void        dictHashSummary(FICL_VM *pVM);
770 #endif
771 int         dictIncludes   (FICL_DICT *pDict, void *p);
772 FICL_WORD  *dictLookup     (FICL_DICT *pDict, STRINGINFO si);
773 #if FICL_WANT_LOCALS
774 FICL_WORD  *ficlLookupLoc  (FICL_SYSTEM *pSys, STRINGINFO si);
775 #endif
776 void        dictResetSearchOrder(FICL_DICT *pDict);
777 void        dictSetFlags   (FICL_DICT *pDict, UNS8 set, UNS8 clr);
778 void        dictSetImmediate(FICL_DICT *pDict);
779 void        dictUnsmudge   (FICL_DICT *pDict);
780 CELL       *dictWhere      (FICL_DICT *pDict);
781
782
783 /* 
784 ** P A R S E   S T E P
785 ** (New for 2.05)
786 ** See words.c: interpWord
787 ** By default, ficl goes through two attempts to parse each token from its input
788 ** stream: it first attempts to match it with a word in the dictionary, and
789 ** if that fails, it attempts to convert it into a number. This mechanism is now
790 ** extensible by additional steps. This allows extensions like floating point and 
791 ** double number support to be factored cleanly.
792 **
793 ** Each parse step is a function that receives the next input token as a STRINGINFO.
794 ** If the parse step matches the token, it must apply semantics to the token appropriate
795 ** to the present value of VM.state (compiling or interpreting), and return FICL_TRUE.
796 ** Otherwise it returns FICL_FALSE. See words.c: isNumber for an example
797 **
798 ** Note: for the sake of efficiency, it's a good idea both to limit the number
799 ** of parse steps and to code each parse step so that it rejects tokens that
800 ** do not match as quickly as possible.
801 */
802
803 typedef int (*FICL_PARSE_STEP)(FICL_VM *pVM, STRINGINFO si);
804
805 /*
806 ** Appends a parse step function to the end of the parse list (see 
807 ** FICL_PARSE_STEP notes in ficl.h for details). Returns 0 if successful,
808 ** nonzero if there's no more room in the list. Each parse step is a word in 
809 ** the dictionary. Precompiled parse steps can use (PARSE-STEP) as their 
810 ** CFA - see parenParseStep in words.c.
811 */
812 int  ficlAddParseStep(FICL_SYSTEM *pSys, FICL_WORD *pFW); /* ficl.c */
813 void ficlAddPrecompiledParseStep(FICL_SYSTEM *pSys, char *name, FICL_PARSE_STEP pStep);
814 void ficlListParseSteps(FICL_VM *pVM);
815
816 /*
817 ** FICL_BREAKPOINT record.
818 ** origXT - if NULL, this breakpoint is unused. Otherwise it stores the xt 
819 ** that the breakpoint overwrote. This is restored to the dictionary when the
820 ** BP executes or gets cleared
821 ** address - the location of the breakpoint (address of the instruction that
822 **           has been replaced with the breakpoint trap
823 ** origXT  - The original contents of the location with the breakpoint
824 ** Note: address is NULL when this breakpoint is empty
825 */
826 typedef struct FICL_BREAKPOINT
827 {
828     void      *address;
829     FICL_WORD *origXT;
830 } FICL_BREAKPOINT;
831
832
833 /*
834 ** F I C L _ S Y S T E M
835 ** The top level data structure of the system - ficl_system ties a list of
836 ** virtual machines with their corresponding dictionaries. Ficl 3.0 will
837 ** support multiple Ficl systems, allowing multiple concurrent sessions 
838 ** to separate dictionaries with some constraints. 
839 ** The present model allows multiple sessions to one dictionary provided
840 ** you implement ficlLockDictionary() as specified in sysdep.h
841 ** Note: the pExtend pointer is there to provide context for applications. It is copied
842 ** to each VM's pExtend field as that VM is created.
843 */
844 struct ficl_system 
845 {
846     FICL_SYSTEM *link;
847     void *pExtend;      /* Initializes VM's pExtend pointer (for application use) */
848     FICL_VM *vmList;
849     FICL_DICT *dp;
850     FICL_DICT *envp;
851 #ifdef FICL_WANT_LOCALS
852     FICL_DICT *localp;
853 #endif
854     FICL_WORD *pInterp[3];
855     FICL_WORD *parseList[FICL_MAX_PARSE_STEPS];
856         OUTFUNC    textOut;
857
858         FICL_WORD *pBranchParen;
859         FICL_WORD *pDoParen;
860         FICL_WORD *pDoesParen;
861         FICL_WORD *pExitInner;
862         FICL_WORD *pExitParen;
863         FICL_WORD *pIfParen;
864         FICL_WORD *pInterpret;
865         FICL_WORD *pLitParen;
866         FICL_WORD *pTwoLitParen;
867         FICL_WORD *pLoopParen;
868         FICL_WORD *pPLoopParen;
869         FICL_WORD *pQDoParen;
870         FICL_WORD *pSemiParen;
871         FICL_WORD *pStore;
872         FICL_WORD *pCStringLit;
873         FICL_WORD *pStringLit;
874
875 #if FICL_WANT_LOCALS
876         FICL_WORD *pGetLocalParen;
877         FICL_WORD *pGet2LocalParen;
878         FICL_WORD *pGetLocal0;
879         FICL_WORD *pGetLocal1;
880         FICL_WORD *pToLocalParen;
881         FICL_WORD *pTo2LocalParen;
882         FICL_WORD *pToLocal0;
883         FICL_WORD *pToLocal1;
884         FICL_WORD *pLinkParen;
885         FICL_WORD *pUnLinkParen;
886         FICL_INT   nLocals;
887         CELL *pMarkLocals;
888 #endif
889
890         FICL_BREAKPOINT bpStep;
891 };
892
893 struct ficl_system_info
894 {
895         int size;           /* structure size tag for versioning */
896         int nDictCells;     /* Size of system's Dictionary */
897         OUTFUNC textOut;    /* default textOut function */
898         void *pExtend;      /* Initializes VM's pExtend pointer - for application use */
899     int nEnvCells;      /* Size of Environment dictionary */
900 };
901
902
903 #define ficlInitInfo(x) { memset((x), 0, sizeof(FICL_SYSTEM_INFO)); \
904          (x)->size = sizeof(FICL_SYSTEM_INFO); }
905
906 /*
907 ** External interface to FICL...
908 */
909 /* 
910 ** f i c l I n i t S y s t e m
911 ** Binds a global dictionary to the interpreter system and initializes
912 ** the dict to contain the ANSI CORE wordset. 
913 ** You can specify the address and size of the allocated area.
914 ** Using ficlInitSystemEx you can also specify the text output function.
915 ** After that, ficl manages it.
916 ** First step is to set up the static pointers to the area.
917 ** Then write the "precompiled" portion of the dictionary in.
918 ** The dictionary needs to be at least large enough to hold the
919 ** precompiled part. Try 1K cells minimum. Use "words" to find
920 ** out how much of the dictionary is used at any time.
921 */
922 FICL_SYSTEM *ficlInitSystemEx(FICL_SYSTEM_INFO *fsi);
923
924 /* Deprecated call */
925 FICL_SYSTEM *ficlInitSystem(int nDictCells);
926
927 /*
928 ** f i c l T e r m S y s t e m
929 ** Deletes the system dictionary and all virtual machines that
930 ** were created with ficlNewVM (see below). Call this function to
931 ** reclaim all memory used by the dictionary and VMs.
932 */
933 void       ficlTermSystem(FICL_SYSTEM *pSys);
934
935 /*
936 ** f i c l E v a l u a t e
937 ** Evaluates a block of input text in the context of the
938 ** specified interpreter. Also sets SOURCE-ID properly.
939 **
940 ** PLEASE USE THIS FUNCTION when throwing a hard-coded
941 ** string to the FICL interpreter.
942 */
943 int        ficlEvaluate(FICL_VM *pVM, char *pText);
944
945 /*
946 ** f i c l E x e c
947 ** Evaluates a block of input text in the context of the
948 ** specified interpreter. Emits any requested output to the
949 ** interpreter's output function. If the input string is NULL
950 ** terminated, you can pass -1 as nChars rather than count it.
951 ** Execution returns when the text block has been executed,
952 ** or an error occurs.
953 ** Returns one of the VM_XXXX codes defined in ficl.h:
954 ** VM_OUTOFTEXT is the normal exit condition
955 ** VM_ERREXIT means that the interp encountered a syntax error
956 **      and the vm has been reset to recover (some or all
957 **      of the text block got ignored
958 ** VM_USEREXIT means that the user executed the "bye" command
959 **      to shut down the interpreter. This would be a good
960 **      time to delete the vm, etc -- or you can ignore this
961 **      signal.
962 ** VM_ABORT and VM_ABORTQ are generated by 'abort' and 'abort"'
963 **      commands.
964 ** Preconditions: successful execution of ficlInitSystem,
965 **      Successful creation and init of the VM by ficlNewVM (or equiv)
966 **
967 ** If you call ficlExec() or one of its brothers, you MUST
968 ** ensure pVM->sourceID was set to a sensible value.
969 ** ficlExec() explicitly DOES NOT manage SOURCE-ID for you.
970 */
971 int        ficlExec (FICL_VM *pVM, char *pText);
972 int        ficlExecC(FICL_VM *pVM, char *pText, FICL_INT nChars);
973 int        ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord);
974
975 /*
976 ** ficlExecFD(FICL_VM *pVM, int fd);
977  * Evaluates text from file passed in via fd.
978  * Execution returns when all of file has been executed or an
979  * error occurs.
980  */
981 int        ficlExecFD(FICL_VM *pVM, int fd);
982
983 /*
984 ** Create a new VM from the heap, and link it into the system VM list.
985 ** Initializes the VM and binds default sized stacks to it. Returns the
986 ** address of the VM, or NULL if an error occurs.
987 ** Precondition: successful execution of ficlInitSystem
988 */
989 FICL_VM   *ficlNewVM(FICL_SYSTEM *pSys);
990
991 /*
992 ** Force deletion of a VM. You do not need to do this 
993 ** unless you're creating and discarding a lot of VMs.
994 ** For systems that use a constant pool of VMs for the life
995 ** of the system, ficltermSystem takes care of VM cleanup
996 ** automatically.
997 */
998 void ficlFreeVM(FICL_VM *pVM);
999
1000
1001 /*
1002 ** Set the stack sizes (return and parameter) to be used for all
1003 ** subsequently created VMs. Returns actual stack size to be used.
1004 */
1005 int ficlSetStackSize(int nStackCells);
1006
1007 /*
1008 ** Returns the address of the most recently defined word in the system
1009 ** dictionary with the given name, or NULL if no match.
1010 ** Precondition: successful execution of ficlInitSystem
1011 */
1012 FICL_WORD *ficlLookup(FICL_SYSTEM *pSys, char *name);
1013
1014 /*
1015 ** f i c l G e t D i c t
1016 ** Utility function - returns the address of the system dictionary.
1017 ** Precondition: successful execution of ficlInitSystem
1018 */
1019 FICL_DICT *ficlGetDict(FICL_SYSTEM *pSys);
1020 FICL_DICT *ficlGetEnv (FICL_SYSTEM *pSys);
1021 void       ficlSetEnv (FICL_SYSTEM *pSys, char *name, FICL_UNS value);
1022 void       ficlSetEnvD(FICL_SYSTEM *pSys, char *name, FICL_UNS hi, FICL_UNS lo);
1023 #if FICL_WANT_LOCALS
1024 FICL_DICT *ficlGetLoc (FICL_SYSTEM *pSys);
1025 #endif
1026 /* 
1027 ** f i c l B u i l d
1028 ** Builds a word into the system default dictionary in a thread-safe way.
1029 ** Preconditions: system must be initialized, and there must
1030 ** be enough space for the new word's header! Operation is
1031 ** controlled by ficlLockDictionary, so any initialization
1032 ** required by your version of the function (if you "overrode"
1033 ** it) must be complete at this point.
1034 ** Parameters:
1035 ** name  -- the name of the word to be built
1036 ** code  -- code to execute when the word is invoked - must take a single param
1037 **          pointer to a FICL_VM
1038 ** flags -- 0 or more of FW_IMMEDIATE, FW_COMPILE, use bitwise OR! 
1039 **          Most words can use FW_DEFAULT.
1040 ** nAllot - number of extra cells to allocate in the parameter area (usually zero)
1041 */
1042 int        ficlBuild(FICL_SYSTEM *pSys, char *name, FICL_CODE code, char flags);
1043
1044 /* 
1045 ** f i c l C o m p i l e C o r e
1046 ** Builds the ANS CORE wordset into the dictionary - called by
1047 ** ficlInitSystem - no need to waste dict space by doing it again.
1048 */
1049 void       ficlCompileCore(FICL_SYSTEM *pSys);
1050 void       ficlCompilePrefix(FICL_SYSTEM *pSys);
1051 void       ficlCompileSearch(FICL_SYSTEM *pSys);
1052 void       ficlCompileSoftCore(FICL_SYSTEM *pSys);
1053 void       ficlCompileTools(FICL_SYSTEM *pSys);
1054 void       ficlCompileFile(FICL_SYSTEM *pSys);
1055 #if FICL_WANT_FLOAT
1056 void       ficlCompileFloat(FICL_SYSTEM *pSys);
1057 int        ficlParseFloatNumber( FICL_VM *pVM, STRINGINFO si ); /* float.c */
1058 #endif
1059 #if FICL_PLATFORM_EXTEND
1060 void       ficlCompilePlatform(FICL_SYSTEM *pSys);
1061 #endif
1062 int        ficlParsePrefix(FICL_VM *pVM, STRINGINFO si);
1063
1064 /*
1065 ** from words.c...
1066 */
1067 void       constantParen(FICL_VM *pVM);
1068 void       twoConstParen(FICL_VM *pVM);
1069 int        ficlParseNumber(FICL_VM *pVM, STRINGINFO si);
1070 void       ficlTick(FICL_VM *pVM);
1071 void       parseStepParen(FICL_VM *pVM);
1072
1073 /*
1074 ** From tools.c
1075 */
1076 int        isAFiclWord(FICL_DICT *pd, FICL_WORD *pFW);
1077
1078 /* 
1079 ** The following supports SEE and the debugger.
1080 */
1081 typedef enum  
1082 {
1083     BRANCH,
1084     COLON, 
1085     CONSTANT, 
1086     CREATE,
1087     DO,
1088     DOES, 
1089     IF,
1090     LITERAL,
1091     LOOP,
1092     PLOOP,
1093     PRIMITIVE,
1094     QDO,
1095     STRINGLIT,
1096     CSTRINGLIT,
1097 #if FICL_WANT_USER
1098     USER, 
1099 #endif
1100     VARIABLE, 
1101 } WORDKIND;
1102
1103 WORDKIND   ficlWordClassify(FICL_WORD *pFW);
1104
1105 /*
1106 ** Dictionary on-demand resizing
1107 */
1108 extern CELL dictThreshold;
1109 extern CELL dictIncrease;
1110
1111 /*
1112 ** Various FreeBSD goodies
1113 */
1114
1115 #if defined(__i386__) && !defined(TESTMAIN)
1116 extern void ficlOutb(FICL_VM *pVM);
1117 extern void ficlInb(FICL_VM *pVM);
1118 #endif
1119
1120 #if !defined(TESTMAIN)
1121 extern void ficlSetenv(FICL_VM *pVM);
1122 extern void ficlSetenvq(FICL_VM *pVM);
1123 extern void ficlGetenv(FICL_VM *pVM);
1124 extern void ficlUnsetenv(FICL_VM *pVM);
1125 extern void ficlCopyin(FICL_VM *pVM);
1126 extern void ficlCopyout(FICL_VM *pVM);
1127 extern void ficlFindfile(FICL_VM *pVM);
1128 extern void ficlPnpdevices(FICL_VM *pVM);
1129 extern void ficlPnphandlers(FICL_VM *pVM);
1130 extern void ficlCcall(FICL_VM *pVM);
1131 #endif
1132
1133 /*
1134 ** Used with File-Access wordset.
1135 */
1136 #define FICL_FAM_READ   1
1137 #define FICL_FAM_WRITE  2
1138 #define FICL_FAM_APPEND 4
1139 #define FICL_FAM_BINARY 8
1140
1141 #define FICL_FAM_OPEN_MODE(fam) ((fam) & (FICL_FAM_READ | FICL_FAM_WRITE | FICL_FAM_APPEND))
1142
1143
1144 #if (FICL_WANT_FILE)
1145 typedef struct ficlFILE
1146 {
1147         FILE *f;
1148         char filename[256];
1149 } ficlFILE;
1150 #endif
1151
1152 #ifdef __cplusplus
1153 }
1154 #endif
1155
1156 #endif /* __FICL_H__ */