ficl.h revision 60959
140843Smsmith/*******************************************************************
240843Smsmith** f i c l . h
340843Smsmith** Forth Inspired Command Language
440843Smsmith** Author: John Sadler (john_sadler@alum.mit.edu)
540843Smsmith** Created: 19 July 1997
640843Smsmith**
740843Smsmith*******************************************************************/
840843Smsmith/*
940843Smsmith** N O T I C E -- DISCLAIMER OF WARRANTY
1040843Smsmith**
1140843Smsmith** Ficl is freeware. Use it in any way that you like, with
1240843Smsmith** the understanding that the code is supported on a "best effort"
1340843Smsmith** basis only.
1440843Smsmith**
1540843Smsmith** Any third party may reproduce, distribute, or modify the ficl
1640843Smsmith** software code or any derivative  works thereof without any
1740843Smsmith** compensation or license, provided that the author information
1840843Smsmith** and this disclaimer text are retained in the source code files.
1940843Smsmith** The ficl software code is provided on an "as is"  basis without
2040843Smsmith** warranty of any kind, including, without limitation, the implied
2140843Smsmith** warranties of merchantability and fitness for a particular purpose
2240843Smsmith** and their equivalents under the laws of any jurisdiction.
2340843Smsmith**
2440843Smsmith** I am interested in hearing from anyone who uses ficl. If you have
2540843Smsmith** a problem, a success story, a defect, an enhancement request, or
2640843Smsmith** if you would like to contribute to the ficl release (yay!), please
2740843Smsmith** send me email at the address above.
2840843Smsmith*/
2940843Smsmith
3051786Sdcs/* $FreeBSD: head/sys/boot/ficl/ficl.h 60959 2000-05-26 21:35:08Z dcs $ */
3151786Sdcs
3240843Smsmith#if !defined (__FICL_H__)
3340843Smsmith#define __FICL_H__
3440843Smsmith/*
3540843Smsmith** Ficl (Forth-inspired command language) is an ANS Forth
3640843Smsmith** interpreter written in C. Unlike traditional Forths, this
3740843Smsmith** interpreter is designed to be embedded into other systems
3840843Smsmith** as a command/macro/development prototype language.
3940843Smsmith**
4040843Smsmith** Where Forths usually view themselves as the center of the system
4140843Smsmith** and expect the rest of the system to be coded in Forth, Ficl
4240843Smsmith** acts as a component of the system. It is easy to export
4340843Smsmith** code written in C or ASM to Ficl in the style of TCL, or to invoke
4440843Smsmith** Ficl code from a compiled module. This allows you to do incremental
4540843Smsmith** development in a way that combines the best features of threaded
4640843Smsmith** languages (rapid development, quick code/test/debug cycle,
4740843Smsmith** reasonably fast) with the best features of C (everyone knows it,
4840843Smsmith** easier to support large blocks of code, efficient, type checking).
4940843Smsmith**
5040843Smsmith** Ficl provides facilities for interoperating
5140843Smsmith** with programs written in C: C functions can be exported to Ficl,
5240843Smsmith** and Ficl commands can be executed via a C calling interface. The
5340843Smsmith** interpreter is re-entrant, so it can be used in multiple instances
5440843Smsmith** in a multitasking system. Unlike Forth, Ficl's outer interpreter
5540843Smsmith** expects a text block as input, and returns to the caller after each
5640843Smsmith** text block, so the "data pump" is somewhere in external code. This
5740843Smsmith** is more like TCL than Forth, which usually expcets to be at the center
5840843Smsmith** of the system, requesting input at its convenience. Each Ficl virtual
5940843Smsmith** machine can be bound to a different I/O channel, and is independent
6040843Smsmith** of all others in in the same address space except that all virtual
6140843Smsmith** machines share a common dictionary (a sort or open symbol table that
6240843Smsmith** defines all of the elements of the language).
6340843Smsmith**
6440843Smsmith** Code is written in ANSI C for portability.
6540843Smsmith**
6640843Smsmith** Summary of Ficl features and constraints:
6740843Smsmith** - Standard: Implements the ANSI Forth CORE word set and part
6840843Smsmith**   of the CORE EXT word-set, SEARCH and SEARCH EXT, TOOLS and
6940843Smsmith**   TOOLS EXT, LOCAL and LOCAL ext and various extras.
7040843Smsmith** - Extensible: you can export code written in Forth, C,
7140843Smsmith**   or asm in a straightforward way. Ficl provides open
7240843Smsmith**   facilities for extending the language in an application
7340843Smsmith**   specific way. You can even add new control structures!
7440843Smsmith** - Ficl and C can interact in two ways: Ficl can encapsulate
7540843Smsmith**   C code, or C code can invoke Ficl code.
7640843Smsmith** - Thread-safe, re-entrant: The shared system dictionary
7740843Smsmith**   uses a locking mechanism that you can either supply
7840843Smsmith**   or stub out to provide exclusive access. Each Ficl
7940843Smsmith**   virtual machine has an otherwise complete state, and
8040843Smsmith**   each can be bound to a separate I/O channel (or none at all).
8140843Smsmith** - Simple encapsulation into existing systems: a basic implementation
8240843Smsmith**   requires three function calls (see the example program in testmain.c).
8340843Smsmith** - ROMable: Ficl is designed to work in RAM-based and ROM code / RAM data
8440843Smsmith**   environments. It does require somewhat more memory than a pure
8540843Smsmith**   ROM implementation because it builds its system dictionary in
8640843Smsmith**   RAM at startup time.
8740843Smsmith** - Written an ANSI C to be as simple as I can make it to understand,
8840843Smsmith**   support, debug, and port. Compiles without complaint at /Az /W4
8940843Smsmith**   (require ANSI C, max warnings) under Microsoft VC++ 5.
9040843Smsmith** - Does full 32 bit math (but you need to implement
9140843Smsmith**   two mixed precision math primitives (see sysdep.c))
9240843Smsmith** - Indirect threaded interpreter is not the fastest kind of
9340843Smsmith**   Forth there is (see pForth 68K for a really fast subroutine
9440843Smsmith**   threaded interpreter), but it's the cleanest match to a
9540843Smsmith**   pure C implementation.
9640843Smsmith**
9740843Smsmith** P O R T I N G   F i c l
9840843Smsmith**
9940843Smsmith** To install Ficl on your target system, you need an ANSI C compiler
10040843Smsmith** and its runtime library. Inspect the system dependent macros and
10140843Smsmith** functions in sysdep.h and sysdep.c and edit them to suit your
10240843Smsmith** system. For example, INT16 is a short on some compilers and an
10340843Smsmith** int on others. Check the default CELL alignment controlled by
10440843Smsmith** FICL_ALIGN. If necessary, add new definitions of ficlMalloc, ficlFree,
10540843Smsmith** ficlLockDictionary, and ficlTextOut to work with your operating system.
10640843Smsmith** Finally, use testmain.c as a guide to installing the Ficl system and
10740843Smsmith** one or more virtual machines into your code. You do not need to include
10840843Smsmith** testmain.c in your build.
10940843Smsmith**
11040843Smsmith** T o   D o   L i s t
11140843Smsmith**
11240843Smsmith** 1. Unimplemented system dependent CORE word: key
11340843Smsmith** 2. Kludged CORE word: ACCEPT
11440843Smsmith** 3. Dictionary locking is full of holes - only one vm at a time
11540843Smsmith**    can alter the dict.
11640843Smsmith** 4. Ficl uses the pad in CORE words - this violates the standard,
11740843Smsmith**    but it's cleaner for a multithreaded system. I'll have to make a
11840843Smsmith**    second pad for reference by the word PAD to fix this.
11940843Smsmith**
12040843Smsmith** F o r   M o r e   I n f o r m a t i o n
12140843Smsmith**
12240843Smsmith** Web home of ficl
12340843Smsmith**   http://www.taygeta.com/forth/compilers
12440843Smsmith** Check this website for Forth literature (including the ANSI standard)
12540843Smsmith**   http://www.taygeta.com/forthlit.html
12640843Smsmith** and here for software and more links
12740843Smsmith**   http://www.taygeta.com/forth.html
12840843Smsmith**
12940843Smsmith** Obvious Performance enhancement opportunities
13040843Smsmith** Compile speed
13140843Smsmith** - work on interpret speed
13240843Smsmith** - turn off locals (FICL_WANT_LOCALS)
13340843Smsmith** Interpret speed
13440843Smsmith** - Change inner interpreter (and everything else)
13540843Smsmith**   so that a definition is a list of pointers to functions
13640843Smsmith**   and inline data rather than pointers to words. This gets
13740843Smsmith**   rid of vm->runningWord and a level of indirection in the
13840843Smsmith**   inner loop. I'll look at it for ficl 3.0
13940843Smsmith** - Make the main hash table a bigger prime (HASHSIZE)
14040843Smsmith** - FORGET about twiddling the hash function - my experience is
14140843Smsmith**   that that is a waste of time.
14240843Smsmith** - eliminate the need to pass the pVM parameter on the stack
14340843Smsmith**   by dedicating a register to it. Most words need access to the
14440843Smsmith**   vm, but the parameter passing overhead can be reduced. One way
14540843Smsmith**   requires that the host OS have a task switch callout. Create
14640843Smsmith**   a global variable for the running VM and refer to it in words
14740843Smsmith**   that need VM access. Alternative: use thread local storage.
14840843Smsmith**   For single threaded implementations, you can just use a global.
14940843Smsmith**   The first two solutions create portability problems, so I
15040843Smsmith**   haven't considered doing them. Another possibility is to
15140843Smsmith**   declare the pVm parameter to be "register", and hope the compiler
15240843Smsmith**   pays attention.
15340843Smsmith**
15440843Smsmith*/
15540843Smsmith
15640843Smsmith/*
15740843Smsmith** Revision History:
15851786Sdcs**
15951786Sdcs** 15 Apr 1999 (sadler) Merged FreeBSD changes for exception wordset and
16051786Sdcs** counted strings in ficlExec.
16143078Smsmith** 12 Jan 1999 (sobral) Corrected EVALUATE behavior. Now TIB has an
16243078Smsmith** "end" field, and all words respect this. ficlExec is passed a "size"
16343078Smsmith** of TIB, as well as vmPushTib. This size is used to calculate the "end"
16443078Smsmith** of the string, ie, base+size. If the size is not known, pass -1.
16543078Smsmith**
16643078Smsmith** 10 Jan 1999 (sobral) EXCEPTION word set has been added, and existing
16743078Smsmith** words has been modified to conform to EXCEPTION EXT word set.
16843078Smsmith**
16940843Smsmith** 27 Aug 1998 (sadler) testing and corrections for LOCALS, LOCALS EXT,
17040843Smsmith**  SEARCH / SEARCH EXT, TOOLS / TOOLS EXT.
17140843Smsmith**  Added .X to display in hex, PARSE and PARSE-WORD to supplement WORD,
17240843Smsmith**  EMPTY to clear stack.
17340843Smsmith**
17440843Smsmith** 29 jun 1998 (sadler) added variable sized hash table support
17540843Smsmith**  and ANS Forth optional SEARCH & SEARCH EXT word set.
17640843Smsmith** 26 May 1998 (sadler)
17740843Smsmith**  FICL_PROMPT macro
17840843Smsmith** 14 April 1998 (sadler) V1.04
17940843Smsmith**  Ficlwin: Windows version, Skip Carter's Linux port
18040843Smsmith** 5 March 1998 (sadler) V1.03
18140843Smsmith**  Bug fixes -- passes John Ryan's ANS test suite "core.fr"
18240843Smsmith**
18340843Smsmith** 24 February 1998 (sadler) V1.02
18440843Smsmith** -Fixed bugs in <# # #>
18540843Smsmith** -Changed FICL_WORD so that storage for the name characters
18640843Smsmith**  can be allocated from the dictionary as needed rather than
18740843Smsmith**  reserving 32 bytes in each word whether needed or not -
18840843Smsmith**  this saved 50% of the dictionary storage requirement.
18940843Smsmith** -Added words in testmain for Win32 functions system,chdir,cwd,
19040843Smsmith**  also added a word that loads and evaluates a file.
19140843Smsmith**
19240843Smsmith** December 1997 (sadler)
19340843Smsmith** -Added VM_RESTART exception handling in ficlExec -- this lets words
19440843Smsmith**  that require additional text to succeed (like :, create, variable...)
19540843Smsmith**  recover gracefully from an empty input buffer rather than emitting
19640843Smsmith**  an error message. Definitions can span multiple input blocks with
19740843Smsmith**  no restrictions.
19840843Smsmith** -Changed #include order so that <assert.h> is included in sysdep.h,
19940843Smsmith**  and sysdep is included in all other files. This lets you define
20040843Smsmith**  NDEBUG in sysdep.h to disable assertions if you want to.
20140843Smsmith** -Make PC specific system dependent code conditional on _M_IX86
20240843Smsmith**  defined so that ports can coexist in sysdep.h/sysdep.c
20340843Smsmith*/
20440843Smsmith
20540843Smsmith#ifdef __cplusplus
20640843Smsmithextern "C" {
20740843Smsmith#endif
20840843Smsmith
20940843Smsmith#include "sysdep.h"
21040843Smsmith#include <limits.h> /* UCHAR_MAX */
21140843Smsmith
21240843Smsmith/*
21340843Smsmith** Forward declarations... read on.
21440843Smsmith*/
21540843Smsmithstruct ficl_word;
21640843Smsmithstruct vm;
21740843Smsmithstruct ficl_dict;
21840843Smsmith
21940843Smsmith/*
22040843Smsmith** the Good Stuff starts here...
22140843Smsmith*/
22251786Sdcs#define FICL_VER    "2.03"
22351786Sdcs#if !defined (FICL_PROMPT)
22451786Sdcs#define FICL_PROMPT "ok> "
22540949Smsmith#endif
22640843Smsmith
22740843Smsmith/*
22840843Smsmith** ANS Forth requires false to be zero, and true to be the ones
22940843Smsmith** complement of false... that unifies logical and bitwise operations
23040843Smsmith** nicely.
23140843Smsmith*/
23256719Sdcs#define FICL_TRUE  (~(0L))
23340843Smsmith#define FICL_FALSE (0)
23440843Smsmith#define FICL_BOOL(x) ((x) ? FICL_TRUE : FICL_FALSE)
23540843Smsmith
23640843Smsmith
23740843Smsmith/*
23840843Smsmith** A CELL is the main storage type. It must be large enough
23951786Sdcs** to contain a pointer or a scalar. In order to accommodate
24051786Sdcs** 32 bit and 64 bit processors, use abstract types for i and u.
24140843Smsmith*/
24240843Smsmithtypedef union _cell
24340843Smsmith{
24451786Sdcs	FICL_INT i;
24551786Sdcs    FICL_UNS u;
24640843Smsmith	void *p;
24740843Smsmith} CELL;
24840843Smsmith
24940843Smsmith/*
25040843Smsmith** LVALUEtoCELL does a little pointer trickery to cast any 32 bit
25140843Smsmith** lvalue (informal definition: an expression whose result has an
25240843Smsmith** address) to CELL. Remember that constants and casts are NOT
25340843Smsmith** themselves lvalues!
25440843Smsmith*/
25540843Smsmith#define LVALUEtoCELL(v) (*(CELL *)&v)
25640843Smsmith
25740843Smsmith/*
25840843Smsmith** PTRtoCELL is a cast through void * intended to satisfy the
25940843Smsmith** most outrageously pedantic compiler... (I won't mention
26040843Smsmith** its name)
26140843Smsmith*/
26240843Smsmith#define PTRtoCELL (CELL *)(void *)
26340843Smsmith#define PTRtoSTRING (FICL_STRING *)(void *)
26440843Smsmith
26540843Smsmith/*
26640843Smsmith** Strings in FICL are stored in Pascal style - with a count
26740843Smsmith** preceding the text. We'll also NULL-terminate them so that
26840843Smsmith** they work with the usual C lib string functions. (Belt &
26940843Smsmith** suspenders? You decide.)
27040843Smsmith** STRINGINFO hides the implementation with a couple of
27140843Smsmith** macros for use in internal routines.
27240843Smsmith*/
27340843Smsmith
27440843Smsmithtypedef unsigned char FICL_COUNT;
27540843Smsmith#define FICL_STRING_MAX UCHAR_MAX
27640843Smsmithtypedef struct _ficl_string
27740843Smsmith{
27840843Smsmith    FICL_COUNT count;
27940843Smsmith    char text[1];
28040843Smsmith} FICL_STRING;
28140843Smsmith
28240843Smsmithtypedef struct
28340843Smsmith{
28440843Smsmith    UNS32 count;
28540843Smsmith    char *cp;
28640843Smsmith} STRINGINFO;
28740843Smsmith
28840843Smsmith#define SI_COUNT(si) (si.count)
28940843Smsmith#define SI_PTR(si)   (si.cp)
29040843Smsmith#define SI_SETLEN(si, len) (si.count = (UNS32)(len))
29140843Smsmith#define SI_SETPTR(si, ptr) (si.cp = (char *)(ptr))
29240843Smsmith/*
29340843Smsmith** Init a STRINGINFO from a pointer to NULL-terminated string
29440843Smsmith*/
29540843Smsmith#define SI_PSZ(si, psz) \
29640843Smsmith            {si.cp = psz; si.count = (FICL_COUNT)strlen(psz);}
29740843Smsmith/*
29840843Smsmith** Init a STRINGINFO from a pointer to FICL_STRING
29940843Smsmith*/
30040843Smsmith#define SI_PFS(si, pfs) \
30140843Smsmith            {si.cp = pfs->text; si.count = pfs->count;}
30240843Smsmith
30340843Smsmith/*
30440843Smsmith** Ficl uses a this little structure to hold the address of
30540843Smsmith** the block of text it's working on and an index to the next
30640843Smsmith** unconsumed character in the string. Traditionally, this is
30740843Smsmith** done by a Text Input Buffer, so I've called this struct TIB.
30843078Smsmith**
30943078Smsmith** Since this structure also holds the size of the input buffer,
31043078Smsmith** and since evaluate requires that, let's put the size here.
31143078Smsmith** The size is stored as an end-pointer because that is what the
31243078Smsmith** null-terminated string aware functions find most easy to deal
31343078Smsmith** with.
31443078Smsmith** Notice, though, that nobody really uses this except evaluate,
31543078Smsmith** so it might just be moved to FICL_VM instead. (sobral)
31640843Smsmith*/
31740843Smsmithtypedef struct
31840843Smsmith{
31940843Smsmith    INT32 index;
32043078Smsmith    char *end;
32140843Smsmith    char *cp;
32240843Smsmith} TIB;
32340843Smsmith
32440843Smsmith
32540843Smsmith/*
32640843Smsmith** Stacks get heavy use in Ficl and Forth...
32740843Smsmith** Each virtual machine implements two of them:
32840843Smsmith** one holds parameters (data), and the other holds return
32940843Smsmith** addresses and control flow information for the virtual
33040843Smsmith** machine. (Note: C's automatic stack is implicitly used,
33140843Smsmith** but not modeled because it doesn't need to be...)
33240843Smsmith** Here's an abstract type for a stack
33340843Smsmith*/
33440843Smsmithtypedef struct _ficlStack
33540843Smsmith{
33651786Sdcs    FICL_UNS nCells;    /* size of the stack */
33740843Smsmith    CELL *pFrame;       /* link reg for stack frame */
33840843Smsmith    CELL *sp;           /* stack pointer */
33940843Smsmith    CELL base[1];       /* Bottom of the stack */
34040843Smsmith} FICL_STACK;
34140843Smsmith
34240843Smsmith/*
34340843Smsmith** Stack methods... many map closely to required Forth words.
34440843Smsmith*/
34540843SmsmithFICL_STACK *stackCreate(unsigned nCells);
34640843Smsmithvoid        stackDelete(FICL_STACK *pStack);
34740843Smsmithint         stackDepth (FICL_STACK *pStack);
34840843Smsmithvoid        stackDrop  (FICL_STACK *pStack, int n);
34940843SmsmithCELL        stackFetch (FICL_STACK *pStack, int n);
35040843SmsmithCELL        stackGetTop(FICL_STACK *pStack);
35140843Smsmithvoid        stackLink  (FICL_STACK *pStack, int nCells);
35240843Smsmithvoid        stackPick  (FICL_STACK *pStack, int n);
35340843SmsmithCELL        stackPop   (FICL_STACK *pStack);
35440843Smsmithvoid       *stackPopPtr   (FICL_STACK *pStack);
35551786SdcsFICL_UNS    stackPopUNS(FICL_STACK *pStack);
35651786SdcsFICL_INT    stackPopINT(FICL_STACK *pStack);
35740843Smsmithvoid        stackPush  (FICL_STACK *pStack, CELL c);
35840843Smsmithvoid        stackPushPtr  (FICL_STACK *pStack, void *ptr);
35951786Sdcsvoid        stackPushUNS(FICL_STACK *pStack, FICL_UNS u);
36051786Sdcsvoid        stackPushINT(FICL_STACK *pStack, FICL_INT i);
36140843Smsmithvoid        stackReset (FICL_STACK *pStack);
36240843Smsmithvoid        stackRoll  (FICL_STACK *pStack, int n);
36340843Smsmithvoid        stackSetTop(FICL_STACK *pStack, CELL c);
36440843Smsmithvoid        stackStore (FICL_STACK *pStack, int n, CELL c);
36540843Smsmithvoid        stackUnlink(FICL_STACK *pStack);
36640843Smsmith
36740843Smsmith/*
36840843Smsmith** The virtual machine (VM) contains the state for one interpreter.
36940843Smsmith** Defined operations include:
37040843Smsmith** Create & initialize
37140843Smsmith** Delete
37240843Smsmith** Execute a block of text
37340843Smsmith** Parse a word out of the input stream
37440843Smsmith** Call return, and branch
37540843Smsmith** Text output
37640843Smsmith** Throw an exception
37740843Smsmith*/
37840843Smsmith
37940843Smsmithtypedef struct ficl_word ** IPTYPE; /* the VM's instruction pointer */
38040843Smsmith
38140843Smsmith/*
38240843Smsmith** Each VM has a placeholder for an output function -
38340843Smsmith** this makes it possible to have each VM do I/O
38440843Smsmith** through a different device. If you specify no
38540843Smsmith** OUTFUNC, it defaults to ficlTextOut.
38640843Smsmith*/
38740843Smsmithtypedef void (*OUTFUNC)(struct vm *pVM, char *text, int fNewline);
38840843Smsmith
38940843Smsmith/*
39040843Smsmith** Each VM operates in one of two non-error states: interpreting
39140843Smsmith** or compiling. When interpreting, words are simply executed.
39240843Smsmith** When compiling, most words in the input stream have their
39340843Smsmith** addresses inserted into the word under construction. Some words
39440843Smsmith** (known as IMMEDIATE) are executed in the compile state, too.
39540843Smsmith*/
39640843Smsmith/* values of STATE */
39740843Smsmith#define INTERPRET 0
39840843Smsmith#define COMPILE   1
39940843Smsmith
40040843Smsmith/*
40140843Smsmith** The pad is a small scratch area for text manipulation. ANS Forth
40240843Smsmith** requires it to hold at least 84 characters.
40340843Smsmith*/
40440843Smsmith#if !defined nPAD
40540843Smsmith#define nPAD 256
40640843Smsmith#endif
40740843Smsmith
40840843Smsmith/*
40940843Smsmith** ANS Forth requires that a word's name contain {1..31} characters.
41040843Smsmith*/
41140843Smsmith#if !defined nFICLNAME
41240843Smsmith#define nFICLNAME		31
41340843Smsmith#endif
41440843Smsmith
41540843Smsmith/*
41640843Smsmith** OK - now we can really define the VM...
41740843Smsmith*/
41840843Smsmithtypedef struct vm
41940843Smsmith{
42040843Smsmith    struct vm      *link;       /* Ficl keeps a VM list for simple teardown */
42140843Smsmith    jmp_buf        *pState;     /* crude exception mechanism...     */
42240843Smsmith    OUTFUNC         textOut;    /* Output callback - see sysdep.c   */
42340843Smsmith    void *          pExtend;    /* vm extension pointer             */
42440843Smsmith    short           fRestart;   /* Set TRUE to restart runningWord  */
42540843Smsmith    IPTYPE          ip;         /* instruction pointer              */
42640843Smsmith    struct ficl_word
42740843Smsmith                   *runningWord;/* address of currently running word (often just *(ip-1) ) */
42840843Smsmith    UNS32           state;      /* compiling or interpreting        */
42940843Smsmith    UNS32           base;       /* number conversion base           */
43040843Smsmith    FICL_STACK     *pStack;     /* param stack                      */
43140843Smsmith    FICL_STACK     *rStack;     /* return stack                     */
43240843Smsmith    CELL            sourceID;   /* -1 if string, 0 if normal input  */
43340843Smsmith    TIB             tib;        /* address of incoming text string  */
43440843Smsmith#if FICL_WANT_USER
43540843Smsmith    CELL            user[FICL_USER_CELLS];
43640843Smsmith#endif
43740843Smsmith    char            pad[nPAD];  /* the scratch area (see above)     */
43840843Smsmith} FICL_VM;
43940843Smsmith
44040843Smsmith/*
44140843Smsmith** A FICL_CODE points to a function that gets called to help execute
44240843Smsmith** a word in the dictionary. It always gets passed a pointer to the
44340843Smsmith** running virtual machine, and from there it can get the address
44440843Smsmith** of the parameter area of the word it's supposed to operate on.
44540843Smsmith** For precompiled words, the code is all there is. For user defined
44640843Smsmith** words, the code assumes that the word's parameter area is a list
44740843Smsmith** of pointers to the code fields of other words to execute, and
44840843Smsmith** may also contain inline data. The first parameter is always
44940843Smsmith** a pointer to a code field.
45040843Smsmith*/
45140843Smsmithtypedef void (*FICL_CODE)(FICL_VM *pVm);
45240843Smsmith
45351786Sdcs#if 0
45451786Sdcs#define VM_ASSERT(pVM) assert((*(pVM->ip - 1)) == pVM->runningWord)
45551786Sdcs#else
45651786Sdcs#define VM_ASSERT(pVM)
45751786Sdcs#endif
45851786Sdcs
45940843Smsmith/*
46040843Smsmith** Ficl models memory as a contiguous space divided into
46140843Smsmith** words in a linked list called the dictionary.
46240843Smsmith** A FICL_WORD starts each entry in the list.
46340843Smsmith** Version 1.02: space for the name characters is allotted from
46440843Smsmith** the dictionary ahead of the word struct - this saves about half
46540843Smsmith** the storage on average with very little runtime cost.
46640843Smsmith*/
46740843Smsmithtypedef struct ficl_word
46840843Smsmith{
46940843Smsmith    struct ficl_word *link;     /* Previous word in the dictionary      */
47040843Smsmith    UNS16 hash;
47140843Smsmith    UNS8 flags;                 /* Immediate, Smudge, Compile-only      */
47240843Smsmith    FICL_COUNT nName;           /* Number of chars in word name         */
47340843Smsmith    char *name;                 /* First nFICLNAME chars of word name   */
47440843Smsmith    FICL_CODE code;             /* Native code to execute the word      */
47540843Smsmith    CELL param[1];              /* First data cell of the word          */
47640843Smsmith} FICL_WORD;
47740843Smsmith
47840843Smsmith/*
47940843Smsmith** Worst-case size of a word header: nFICLNAME chars in name
48040843Smsmith*/
48140843Smsmith#define CELLS_PER_WORD  \
48240843Smsmith    ( (sizeof (FICL_WORD) + nFICLNAME + sizeof (CELL)) \
48340843Smsmith                          / (sizeof (CELL)) )
48440843Smsmith
48540843Smsmithint wordIsImmediate(FICL_WORD *pFW);
48640843Smsmithint wordIsCompileOnly(FICL_WORD *pFW);
48740843Smsmith
48840843Smsmith/* flag values for word header */
48940843Smsmith#define FW_IMMEDIATE    1   /* execute me even if compiling */
49040843Smsmith#define FW_COMPILE      2   /* error if executed when not compiling */
49140843Smsmith#define FW_SMUDGE       4   /* definition in progress - hide me */
49240843Smsmith#define FW_CLASS        8   /* Word defines a class */
49340843Smsmith
49440843Smsmith#define FW_COMPIMMED    (FW_IMMEDIATE | FW_COMPILE)
49540843Smsmith#define FW_DEFAULT      0
49640843Smsmith
49740843Smsmith
49840843Smsmith/*
49940843Smsmith** Exit codes for vmThrow
50040843Smsmith*/
50151786Sdcs#define VM_INNEREXIT -256   /* tell ficlExecXT to exit inner loop */
50251786Sdcs#define VM_OUTOFTEXT -257   /* hungry - normal exit */
50351786Sdcs#define VM_RESTART   -258   /* word needs more text to succeed - re-run it */
50451786Sdcs#define VM_USEREXIT  -259   /* user wants to quit */
50551786Sdcs#define VM_ERREXIT   -260   /* interp found an error */
50643078Smsmith#define VM_ABORT       -1   /* like errexit -- abort */
50743078Smsmith#define VM_ABORTQ      -2   /* like errexit -- abort" */
50843078Smsmith#define VM_QUIT       -56   /* like errexit, but leave pStack & base alone */
50940843Smsmith
51040843Smsmith
51140843Smsmithvoid        vmBranchRelative(FICL_VM *pVM, int offset);
51240843SmsmithFICL_VM *   vmCreate (FICL_VM *pVM, unsigned nPStack, unsigned nRStack);
51340843Smsmithvoid        vmDelete (FICL_VM *pVM);
51440843Smsmithvoid        vmExecute(FICL_VM *pVM, FICL_WORD *pWord);
51540843Smsmithchar *      vmGetString(FICL_VM *pVM, FICL_STRING *spDest, char delimiter);
51640843SmsmithSTRINGINFO  vmGetWord(FICL_VM *pVM);
51740843SmsmithSTRINGINFO  vmGetWord0(FICL_VM *pVM);
51840843Smsmithint         vmGetWordToPad(FICL_VM *pVM);
51940843SmsmithSTRINGINFO  vmParseString(FICL_VM *pVM, char delimiter);
52060959SdcsSTRINGINFO  vmParseStringEx(FICL_VM *pVM, char delimiter, char fSkipLeading);
52160959SdcsCELL        vmPop(FICL_VM *pVM);
52260959Sdcsvoid        vmPush(FICL_VM *pVM, CELL c);
52340843Smsmithvoid        vmPopIP  (FICL_VM *pVM);
52440843Smsmithvoid        vmPushIP (FICL_VM *pVM, IPTYPE newIP);
52540843Smsmithvoid        vmQuit   (FICL_VM *pVM);
52640843Smsmithvoid        vmReset  (FICL_VM *pVM);
52740843Smsmithvoid        vmSetTextOut(FICL_VM *pVM, OUTFUNC textOut);
52860959Sdcs#if FICL_WANT_DEBUGGER
52960959Sdcsvoid        vmStep(FICL_VM *pVM);
53060959Sdcs#endif
53140843Smsmithvoid        vmTextOut(FICL_VM *pVM, char *text, int fNewline);
53240843Smsmithvoid        vmThrow  (FICL_VM *pVM, int except);
53340843Smsmithvoid        vmThrowErr(FICL_VM *pVM, char *fmt, ...);
53440843Smsmith
53551786Sdcs#define vmGetRunningWord(pVM) ((pVM)->runningWord)
53651786Sdcs
53751786Sdcs
53840843Smsmith/*
53951786Sdcs** The inner interpreter - coded as a macro (see note for
54051786Sdcs** INLINE_INNER_LOOP in sysdep.h for complaints about VC++ 5
54151786Sdcs*/
54260959Sdcs#define M_VM_STEP(pVM) \
54351786Sdcs        FICL_WORD *tempFW = *(pVM)->ip++; \
54451786Sdcs        (pVM)->runningWord = tempFW; \
54551786Sdcs        tempFW->code(pVM); \
54651786Sdcs
54760959Sdcs#define M_INNER_LOOP(pVM) \
54860959Sdcs    for (;;)  { M_VM_STEP(pVM) }
54951786Sdcs
55060959Sdcs
55151786Sdcs#if INLINE_INNER_LOOP != 0
55251786Sdcs#define     vmInnerLoop(pVM) M_INNER_LOOP(pVM)
55351786Sdcs#else
55451786Sdcsvoid        vmInnerLoop(FICL_VM *pVM);
55551786Sdcs#endif
55651786Sdcs
55751786Sdcs/*
55840843Smsmith** vmCheckStack needs a vm pointer because it might have to say
55940843Smsmith** something if it finds a problem. Parms popCells and pushCells
56040843Smsmith** correspond to the number of parameters on the left and right of
56140843Smsmith** a word's stack effect comment.
56240843Smsmith*/
56340843Smsmithvoid        vmCheckStack(FICL_VM *pVM, int popCells, int pushCells);
56440843Smsmith
56540843Smsmith/*
56640843Smsmith** TIB access routines...
56740843Smsmith** ANS forth seems to require the input buffer to be represented
56840843Smsmith** as a pointer to the start of the buffer, and an index to the
56940843Smsmith** next character to read.
57040843Smsmith** PushTib points the VM to a new input string and optionally
57140843Smsmith**  returns a copy of the current state
57240843Smsmith** PopTib restores the TIB state given a saved TIB from PushTib
57340843Smsmith** GetInBuf returns a pointer to the next unused char of the TIB
57440843Smsmith*/
57551786Sdcsvoid        vmPushTib(FICL_VM *pVM, char *text, INT32 nChars, TIB *pSaveTib);
57640843Smsmithvoid        vmPopTib(FICL_VM *pVM, TIB *pTib);
57740843Smsmith#define     vmGetInBuf(pVM) ((pVM)->tib.cp + (pVM)->tib.index)
57851786Sdcs#define     vmGetInBufLen(pVM) ((pVM)->tib.end - (pVM)->tib.cp)
57951786Sdcs#define     vmGetInBufEnd(pVM) ((pVM)->tib.end)
58040843Smsmith#define     vmSetTibIndex(pVM, i) (pVM)->tib.index = i
58140843Smsmith#define     vmUpdateTib(pVM, str) (pVM)->tib.index = (str) - (pVM)->tib.cp
58240843Smsmith
58340843Smsmith/*
58440843Smsmith** Generally useful string manipulators omitted by ANSI C...
58540843Smsmith** ltoa complements strtol
58640843Smsmith*/
58740843Smsmith#if defined(_WIN32) && !FICL_MAIN
58840843Smsmith/* #SHEESH
58940843Smsmith** Why do Microsoft Meatballs insist on contaminating
59040843Smsmith** my namespace with their string functions???
59140843Smsmith*/
59240843Smsmith#pragma warning(disable: 4273)
59340843Smsmith#endif
59440843Smsmith
59551786Sdcsint        isPowerOfTwo(FICL_UNS u);
59651786Sdcs
59751786Sdcschar       *ltoa( FICL_INT value, char *string, int radix );
59851786Sdcschar       *ultoa(FICL_UNS value, char *string, int radix );
59940843Smsmithchar        digit_to_char(int value);
60040843Smsmithchar       *strrev( char *string );
60151786Sdcschar       *skipSpace(char *cp, char *end);
60240843Smsmithchar       *caseFold(char *cp);
60340843Smsmithint         strincmp(char *cp1, char *cp2, FICL_COUNT count);
60440843Smsmith
60540843Smsmith#if defined(_WIN32) && !FICL_MAIN
60640843Smsmith#pragma warning(default: 4273)
60740843Smsmith#endif
60840843Smsmith
60940843Smsmith/*
61040843Smsmith** Ficl hash table - variable size.
61140843Smsmith** assert(size > 0)
61240843Smsmith** If size is 1, the table degenerates into a linked list.
61340843Smsmith** A WORDLIST (see the search order word set in DPANS) is
61440843Smsmith** just a pointer to a FICL_HASH in this implementation.
61540843Smsmith*/
61651786Sdcs#if !defined HASHSIZE /* Default size of hash table. For most uniform */
61740843Smsmith#define HASHSIZE 127  /*   performance, use a prime number!   */
61840843Smsmith#endif
61940843Smsmith
62040843Smsmithtypedef struct ficl_hash
62140843Smsmith{
62240843Smsmith    struct ficl_hash *link;  /* eventual inheritance support */
62340843Smsmith    unsigned   size;
62440843Smsmith    FICL_WORD *table[1];
62540843Smsmith} FICL_HASH;
62640843Smsmith
62740843Smsmithvoid        hashForget(FICL_HASH *pHash, void *where);
62840843SmsmithUNS16       hashHashCode(STRINGINFO si);
62940843Smsmithvoid        hashInsertWord(FICL_HASH *pHash, FICL_WORD *pFW);
63040843SmsmithFICL_WORD  *hashLookup(struct ficl_hash *pHash,
63140843Smsmith                       STRINGINFO si,
63240843Smsmith                       UNS16 hashCode);
63340843Smsmithvoid        hashReset(FICL_HASH *pHash);
63440843Smsmith
63540843Smsmith/*
63640843Smsmith** A Dictionary is a linked list of FICL_WORDs. It is also Ficl's
63740843Smsmith** memory model. Description of fields:
63840843Smsmith**
63940843Smsmith** here -- points to the next free byte in the dictionary. This
64040843Smsmith**      pointer is forced to be CELL-aligned before a definition is added.
64140843Smsmith**      Do not assume any specific alignment otherwise - Use dictAlign().
64240843Smsmith**
64340843Smsmith** smudge -- pointer to word currently being defined (or last defined word)
64440843Smsmith**      If the definition completes successfully, the word will be
64540843Smsmith**      linked into the hash table. If unsuccessful, dictUnsmudge
64640843Smsmith**      uses this pointer to restore the previous state of the dictionary.
64740843Smsmith**      Smudge prevents unintentional recursion as a side-effect: the
64840843Smsmith**      dictionary search algo examines only completed definitions, so a
64940843Smsmith**      word cannot invoke itself by name. See the ficl word "recurse".
65040843Smsmith**      NOTE: smudge always points to the last word defined. IMMEDIATE
65140843Smsmith**      makes use of this fact. Smudge is initially NULL.
65240843Smsmith**
65340843Smsmith** pForthWords -- pointer to the default wordlist (FICL_HASH).
65440843Smsmith**      This is the initial compilation list, and contains all
65540843Smsmith**      ficl's precompiled words.
65640843Smsmith**
65740843Smsmith** pCompile -- compilation wordlist - initially equal to pForthWords
65840843Smsmith** pSearch  -- array of pointers to wordlists. Managed as a stack.
65940843Smsmith**      Highest index is the first list in the search order.
66040843Smsmith** nLists   -- number of lists in pSearch. nLists-1 is the highest
66140843Smsmith**      filled slot in pSearch, and points to the first wordlist
66240843Smsmith**      in the search order
66340843Smsmith** size -- number of cells in the dictionary (total)
66440843Smsmith** dict -- start of data area. Must be at the end of the struct.
66540843Smsmith*/
66640843Smsmithtypedef struct ficl_dict
66740843Smsmith{
66840843Smsmith    CELL *here;
66940843Smsmith    FICL_WORD *smudge;
67040843Smsmith    FICL_HASH *pForthWords;
67140843Smsmith    FICL_HASH *pCompile;
67240843Smsmith    FICL_HASH *pSearch[FICL_DEFAULT_VOCS];
67340843Smsmith    int        nLists;
67440843Smsmith    unsigned   size;    /* Number of cells in dict (total)*/
67560014Sdcs    CELL       *dict;   /* Base of dictionary memory      */
67640843Smsmith} FICL_DICT;
67740843Smsmith
67840843Smsmithvoid       *alignPtr(void *ptr);
67940843Smsmithvoid        dictAbortDefinition(FICL_DICT *pDict);
68040843Smsmithvoid        dictAlign(FICL_DICT *pDict);
68140843Smsmithint         dictAllot(FICL_DICT *pDict, int n);
68240843Smsmithint         dictAllotCells(FICL_DICT *pDict, int nCells);
68340843Smsmithvoid        dictAppendCell(FICL_DICT *pDict, CELL c);
68440843Smsmithvoid        dictAppendChar(FICL_DICT *pDict, char c);
68540843SmsmithFICL_WORD  *dictAppendWord(FICL_DICT *pDict,
68640843Smsmith                           char *name,
68740843Smsmith                           FICL_CODE pCode,
68840843Smsmith                           UNS8 flags);
68940843SmsmithFICL_WORD  *dictAppendWord2(FICL_DICT *pDict,
69040843Smsmith                           STRINGINFO si,
69140843Smsmith                           FICL_CODE pCode,
69240843Smsmith                           UNS8 flags);
69351786Sdcsvoid        dictAppendUNS(FICL_DICT *pDict, FICL_UNS u);
69440843Smsmithint         dictCellsAvail(FICL_DICT *pDict);
69540843Smsmithint         dictCellsUsed (FICL_DICT *pDict);
69640843Smsmithvoid        dictCheck(FICL_DICT *pDict, FICL_VM *pVM, int nCells);
69740843SmsmithFICL_DICT  *dictCreate(unsigned nCELLS);
69840843SmsmithFICL_DICT  *dictCreateHashed(unsigned nCells, unsigned nHash);
69940843Smsmithvoid        dictDelete(FICL_DICT *pDict);
70040843Smsmithvoid        dictEmpty(FICL_DICT *pDict, unsigned nHash);
70140843Smsmithint         dictIncludes(FICL_DICT *pDict, void *p);
70240843SmsmithFICL_WORD  *dictLookup(FICL_DICT *pDict, STRINGINFO si);
70340843Smsmith#if FICL_WANT_LOCALS
70440843SmsmithFICL_WORD  *dictLookupLoc(FICL_DICT *pDict, STRINGINFO si);
70540843Smsmith#endif
70640843Smsmithvoid        dictResetSearchOrder(FICL_DICT *pDict);
70740843Smsmithvoid        dictSetFlags(FICL_DICT *pDict, UNS8 set, UNS8 clr);
70840843Smsmithvoid        dictSetImmediate(FICL_DICT *pDict);
70940843Smsmithvoid        dictUnsmudge(FICL_DICT *pDict);
71040843SmsmithCELL       *dictWhere(FICL_DICT *pDict);
71140843Smsmith
71240843Smsmith
71340843Smsmith/*
71440843Smsmith** External interface to FICL...
71540843Smsmith*/
71640843Smsmith/*
71740843Smsmith** f i c l I n i t S y s t e m
71840843Smsmith** Binds a global dictionary to the interpreter system and initializes
71940843Smsmith** the dict to contain the ANSI CORE wordset.
72040843Smsmith** You specify the address and size of the allocated area.
72140843Smsmith** After that, ficl manages it.
72240843Smsmith** First step is to set up the static pointers to the area.
72340843Smsmith** Then write the "precompiled" portion of the dictionary in.
72440843Smsmith** The dictionary needs to be at least large enough to hold the
72540843Smsmith** precompiled part. Try 1K cells minimum. Use "words" to find
72640843Smsmith** out how much of the dictionary is used at any time.
72740843Smsmith*/
72840843Smsmithvoid       ficlInitSystem(int nDictCells);
72940843Smsmith
73040843Smsmith/*
73140843Smsmith** f i c l T e r m S y s t e m
73240843Smsmith** Deletes the system dictionary and all virtual machines that
73340843Smsmith** were created with ficlNewVM (see below). Call this function to
73440843Smsmith** reclaim all memory used by the dictionary and VMs.
73540843Smsmith*/
73640843Smsmithvoid       ficlTermSystem(void);
73740843Smsmith
73840843Smsmith/*
73940843Smsmith** f i c l E x e c
74040843Smsmith** Evaluates a block of input text in the context of the
74140843Smsmith** specified interpreter. Emits any requested output to the
74251786Sdcs** interpreter's output function. If the input string is NULL
74351786Sdcs** terminated, you can pass -1 as nChars rather than count it.
74440843Smsmith** Execution returns when the text block has been executed,
74540843Smsmith** or an error occurs.
74640843Smsmith** Returns one of the VM_XXXX codes defined in ficl.h:
74740843Smsmith** VM_OUTOFTEXT is the normal exit condition
74840843Smsmith** VM_ERREXIT means that the interp encountered a syntax error
74940843Smsmith**      and the vm has been reset to recover (some or all
75040843Smsmith**      of the text block got ignored
75140843Smsmith** VM_USEREXIT means that the user executed the "bye" command
75240843Smsmith**      to shut down the interpreter. This would be a good
75340843Smsmith**      time to delete the vm, etc -- or you can ignore this
75440843Smsmith**      signal.
75543078Smsmith** VM_ABORT and VM_ABORTQ are generated by 'abort' and 'abort"'
75643078Smsmith**      commands.
75740843Smsmith** Preconditions: successful execution of ficlInitSystem,
75840843Smsmith**      Successful creation and init of the VM by ficlNewVM (or equiv)
75940843Smsmith*/
76051786Sdcsint        ficlExec (FICL_VM *pVM, char *pText);
76151786Sdcsint        ficlExecC(FICL_VM *pVM, char *pText, INT32 nChars);
76251786Sdcsint        ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord);
76340843Smsmith
76440843Smsmith/*
76540989Sjkh** ficlExecFD(FICL_VM *pVM, int fd);
76640989Sjkh * Evaluates text from file passed in via fd.
76740989Sjkh * Execution returns when all of file has been executed or an
76840989Sjkh * error occurs.
76940989Sjkh */
77040989Sjkhint        ficlExecFD(FICL_VM *pVM, int fd);
77140989Sjkh
77240989Sjkh/*
77340843Smsmith** Create a new VM from the heap, and link it into the system VM list.
77440843Smsmith** Initializes the VM and binds default sized stacks to it. Returns the
77540843Smsmith** address of the VM, or NULL if an error occurs.
77640843Smsmith** Precondition: successful execution of ficlInitSystem
77740843Smsmith*/
77840843SmsmithFICL_VM   *ficlNewVM(void);
77940843Smsmith
78040843Smsmith/*
78160959Sdcs** Force deletion of a VM. You do not need to do this
78260959Sdcs** unless you're creating and discarding a lot of VMs.
78360959Sdcs** For systems that use a constant pool of VMs for the life
78460959Sdcs** of the system, ficltermSystem takes care of VM cleanup
78560959Sdcs** automatically.
78660959Sdcs*/
78760959Sdcsvoid ficlFreeVM(FICL_VM *pVM);
78860959Sdcs
78960959Sdcs
79060959Sdcs/*
79151786Sdcs** Set the stack sizes (return and parameter) to be used for all
79251786Sdcs** subsequently created VMs. Returns actual stack size to be used.
79351786Sdcs*/
79451786Sdcsint ficlSetStackSize(int nStackCells);
79551786Sdcs
79651786Sdcs/*
79740843Smsmith** Returns the address of the most recently defined word in the system
79840843Smsmith** dictionary with the given name, or NULL if no match.
79940843Smsmith** Precondition: successful execution of ficlInitSystem
80040843Smsmith*/
80140843SmsmithFICL_WORD *ficlLookup(char *name);
80240843Smsmith
80340843Smsmith/*
80440843Smsmith** f i c l G e t D i c t
80540843Smsmith** Utility function - returns the address of the system dictionary.
80640843Smsmith** Precondition: successful execution of ficlInitSystem
80740843Smsmith*/
80840843SmsmithFICL_DICT *ficlGetDict(void);
80940843SmsmithFICL_DICT *ficlGetEnv(void);
81040843Smsmithvoid       ficlSetEnv(char *name, UNS32 value);
81140843Smsmithvoid       ficlSetEnvD(char *name, UNS32 hi, UNS32 lo);
81240843Smsmith#if FICL_WANT_LOCALS
81340843SmsmithFICL_DICT *ficlGetLoc(void);
81440843Smsmith#endif
81540843Smsmith/*
81640843Smsmith** f i c l B u i l d
81740843Smsmith** Builds a word into the system default dictionary in a thread-safe way.
81840843Smsmith** Preconditions: system must be initialized, and there must
81940843Smsmith** be enough space for the new word's header! Operation is
82040843Smsmith** controlled by ficlLockDictionary, so any initialization
82140843Smsmith** required by your version of the function (if you "overrode"
82240843Smsmith** it) must be complete at this point.
82340843Smsmith** Parameters:
82440843Smsmith** name  -- the name of the word to be built
82540843Smsmith** code  -- code to execute when the word is invoked - must take a single param
82640843Smsmith**          pointer to a FICL_VM
82740843Smsmith** flags -- 0 or more of FW_IMMEDIATE, FW_COMPILE, use bitwise OR!
82840843Smsmith**          Most words can use FW_DEFAULT.
82940843Smsmith** nAllot - number of extra cells to allocate in the parameter area (usually zero)
83040843Smsmith*/
83140843Smsmithint        ficlBuild(char *name, FICL_CODE code, char flags);
83240843Smsmith
83340843Smsmith/*
83440843Smsmith** f i c l C o m p i l e C o r e
83540843Smsmith** Builds the ANS CORE wordset into the dictionary - called by
83640843Smsmith** ficlInitSystem - no need to waste dict space by doing it again.
83740843Smsmith*/
83840843Smsmithvoid       ficlCompileCore(FICL_DICT *dp);
83940843Smsmithvoid       ficlCompileSoftCore(FICL_VM *pVM);
84040843Smsmith
84140843Smsmith/*
84240843Smsmith** from words.c...
84340843Smsmith*/
84440843Smsmithvoid       constantParen(FICL_VM *pVM);
84540843Smsmithvoid       twoConstParen(FICL_VM *pVM);
84640843Smsmith
84743139Smsmith/*
84860014Sdcs** Dictionary on-demand resizing
84960014Sdcs*/
85060014Sdcsextern unsigned int dictThreshold;
85160014Sdcsextern unsigned int dictIncrease;
85260014Sdcs
85360014Sdcs/*
85443139Smsmith** So we can more easily debug...
85543139Smsmith*/
85643139Smsmith#ifdef FICL_TRACE
85743139Smsmithextern int ficl_trace;
85843139Smsmith#endif
85943139Smsmith
86042679Sabial#if defined(__i386__) && !defined(TESTMAIN)
86142679Sabialextern void ficlOutb(FICL_VM *pVM);
86242679Sabialextern void ficlInb(FICL_VM *pVM);
86342634Sabial#endif
86442634Sabial
86540843Smsmith#ifdef __cplusplus
86640843Smsmith}
86740843Smsmith#endif
86840843Smsmith
86940843Smsmith#endif /* __FICL_H__ */
870