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