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