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