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