ficl.h (77443) | ficl.h (94290) |
---|---|
1/******************************************************************* 2** f i c l . h 3** Forth Inspired Command Language 4** Author: John Sadler (john_sadler@alum.mit.edu) 5** Created: 19 July 1997 | 1/******************************************************************* 2** f i c l . h 3** Forth Inspired Command Language 4** Author: John Sadler (john_sadler@alum.mit.edu) 5** Created: 19 July 1997 |
6** $Id: ficl.h,v 1.11 2001-04-26 21:41:48-07 jsadler Exp jsadler $ | 6** Dedicated to RHS, in loving memory 7** $Id: ficl.h,v 1.18 2001/12/05 07:21:34 jsadler Exp $ |
7*******************************************************************/ 8/* 9** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) 10** All rights reserved. 11** 12** Get the latest Ficl release at http://ficl.sourceforge.net 13** | 8*******************************************************************/ 9/* 10** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) 11** All rights reserved. 12** 13** Get the latest Ficl release at http://ficl.sourceforge.net 14** |
15** I am interested in hearing from anyone who uses ficl. If you have 16** a problem, a success story, a defect, an enhancement request, or 17** if you would like to contribute to the ficl release, please 18** contact me by email at the address above. 19** |
|
14** L I C E N S E and D I S C L A I M E R 15** 16** Redistribution and use in source and binary forms, with or without 17** modification, are permitted provided that the following conditions 18** are met: 19** 1. Redistributions of source code must retain the above copyright 20** notice, this list of conditions and the following disclaimer. 21** 2. Redistributions in binary form must reproduce the above copyright --- 6 unchanged lines hidden (view full) --- 28** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 29** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35** SUCH DAMAGE. | 20** L I C E N S E and D I S C L A I M E R 21** 22** Redistribution and use in source and binary forms, with or without 23** modification, are permitted provided that the following conditions 24** are met: 25** 1. Redistributions of source code must retain the above copyright 26** notice, this list of conditions and the following disclaimer. 27** 2. Redistributions in binary form must reproduce the above copyright --- 6 unchanged lines hidden (view full) --- 34** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 35** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 40** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 41** SUCH DAMAGE. |
36** 37** I am interested in hearing from anyone who uses ficl. If you have 38** a problem, a success story, a defect, an enhancement request, or 39** if you would like to contribute to the ficl release, please send 40** contact me by email at the address above. 41** 42** $Id: ficl.h,v 1.11 2001-04-26 21:41:48-07 jsadler Exp jsadler $ | |
43*/ 44 | 42*/ 43 |
45/* $FreeBSD: head/sys/boot/ficl/ficl.h 77443 2001-05-29 23:44:12Z dcs $ */ | 44/* $FreeBSD: head/sys/boot/ficl/ficl.h 94290 2002-04-09 17:45:28Z dcs $ */ |
46 47#if !defined (__FICL_H__) 48#define __FICL_H__ 49/* 50** Ficl (Forth-inspired command language) is an ANS Forth 51** interpreter written in C. Unlike traditional Forths, this 52** interpreter is designed to be embedded into other systems 53** as a command/macro/development prototype language. --- 66 unchanged lines hidden (view full) --- 120** ficlLockDictionary, and ficlTextOut to work with your operating system. 121** Finally, use testmain.c as a guide to installing the Ficl system and 122** one or more virtual machines into your code. You do not need to include 123** testmain.c in your build. 124** 125** T o D o L i s t 126** 127** 1. Unimplemented system dependent CORE word: key | 45 46#if !defined (__FICL_H__) 47#define __FICL_H__ 48/* 49** Ficl (Forth-inspired command language) is an ANS Forth 50** interpreter written in C. Unlike traditional Forths, this 51** interpreter is designed to be embedded into other systems 52** as a command/macro/development prototype language. --- 66 unchanged lines hidden (view full) --- 119** ficlLockDictionary, and ficlTextOut to work with your operating system. 120** Finally, use testmain.c as a guide to installing the Ficl system and 121** one or more virtual machines into your code. You do not need to include 122** testmain.c in your build. 123** 124** T o D o L i s t 125** 126** 1. Unimplemented system dependent CORE word: key |
128** 2. Kludged CORE word: ACCEPT 129** 3. Dictionary locking is full of holes - only one vm at a time 130** can alter the dict. 131** 4. Ficl uses the pad in CORE words - this violates the standard, | 127** 2. Ficl uses the PAD in some CORE words - this violates the standard, |
132** but it's cleaner for a multithreaded system. I'll have to make a 133** second pad for reference by the word PAD to fix this. 134** 135** F o r M o r e I n f o r m a t i o n 136** 137** Web home of ficl | 128** but it's cleaner for a multithreaded system. I'll have to make a 129** second pad for reference by the word PAD to fix this. 130** 131** F o r M o r e I n f o r m a t i o n 132** 133** Web home of ficl |
138** http://www.taygeta.com/forth/compilers | 134** http://ficl.sourceforge.net |
139** Check this website for Forth literature (including the ANSI standard) 140** http://www.taygeta.com/forthlit.html 141** and here for software and more links 142** http://www.taygeta.com/forth.html 143** 144** Obvious Performance enhancement opportunities 145** Compile speed 146** - work on interpret speed 147** - turn off locals (FICL_WANT_LOCALS) 148** Interpret speed 149** - Change inner interpreter (and everything else) 150** so that a definition is a list of pointers to functions 151** and inline data rather than pointers to words. This gets 152** rid of vm->runningWord and a level of indirection in the 153** inner loop. I'll look at it for ficl 3.0 154** - Make the main hash table a bigger prime (HASHSIZE) 155** - FORGET about twiddling the hash function - my experience is 156** that that is a waste of time. | 135** Check this website for Forth literature (including the ANSI standard) 136** http://www.taygeta.com/forthlit.html 137** and here for software and more links 138** http://www.taygeta.com/forth.html 139** 140** Obvious Performance enhancement opportunities 141** Compile speed 142** - work on interpret speed 143** - turn off locals (FICL_WANT_LOCALS) 144** Interpret speed 145** - Change inner interpreter (and everything else) 146** so that a definition is a list of pointers to functions 147** and inline data rather than pointers to words. This gets 148** rid of vm->runningWord and a level of indirection in the 149** inner loop. I'll look at it for ficl 3.0 150** - Make the main hash table a bigger prime (HASHSIZE) 151** - FORGET about twiddling the hash function - my experience is 152** that that is a waste of time. |
157** - eliminate the need to pass the pVM parameter on the stack | 153** - Eliminate the need to pass the pVM parameter on the stack |
158** by dedicating a register to it. Most words need access to the 159** vm, but the parameter passing overhead can be reduced. One way 160** requires that the host OS have a task switch callout. Create 161** a global variable for the running VM and refer to it in words 162** that need VM access. Alternative: use thread local storage. 163** For single threaded implementations, you can just use a global. 164** The first two solutions create portability problems, so I 165** haven't considered doing them. Another possibility is to --- 57 unchanged lines hidden (view full) --- 223 224#include "sysdep.h" 225#include <limits.h> /* UCHAR_MAX */ 226 227/* 228** Forward declarations... read on. 229*/ 230struct ficl_word; | 154** by dedicating a register to it. Most words need access to the 155** vm, but the parameter passing overhead can be reduced. One way 156** requires that the host OS have a task switch callout. Create 157** a global variable for the running VM and refer to it in words 158** that need VM access. Alternative: use thread local storage. 159** For single threaded implementations, you can just use a global. 160** The first two solutions create portability problems, so I 161** haven't considered doing them. Another possibility is to --- 57 unchanged lines hidden (view full) --- 219 220#include "sysdep.h" 221#include <limits.h> /* UCHAR_MAX */ 222 223/* 224** Forward declarations... read on. 225*/ 226struct ficl_word; |
227typedef struct ficl_word FICL_WORD; |
|
231struct vm; | 228struct vm; |
229typedef struct vm FICL_VM; |
|
232struct ficl_dict; | 230struct ficl_dict; |
231typedef struct ficl_dict FICL_DICT; |
|
233struct ficl_system; 234typedef struct ficl_system FICL_SYSTEM; | 232struct ficl_system; 233typedef struct ficl_system FICL_SYSTEM; |
234struct ficl_system_info; 235typedef struct ficl_system_info FICL_SYSTEM_INFO; |
|
235 236/* 237** the Good Stuff starts here... 238*/ | 236 237/* 238** the Good Stuff starts here... 239*/ |
239#define FICL_VER "2.05" | 240#define FICL_VER "3.02" 241#define FICL_VER_MAJOR 3 242#define FICL_VER_MINOR 2 |
240#if !defined (FICL_PROMPT) 241#define FICL_PROMPT "ok> " 242#endif 243 244/* 245** ANS Forth requires false to be zero, and true to be the ones 246** complement of false... that unifies logical and bitwise operations 247** nicely. 248*/ 249#define FICL_TRUE ((unsigned long)~(0L)) 250#define FICL_FALSE (0) 251#define FICL_BOOL(x) ((x) ? FICL_TRUE : FICL_FALSE) 252 253 254/* 255** A CELL is the main storage type. It must be large enough 256** to contain a pointer or a scalar. In order to accommodate | 243#if !defined (FICL_PROMPT) 244#define FICL_PROMPT "ok> " 245#endif 246 247/* 248** ANS Forth requires false to be zero, and true to be the ones 249** complement of false... that unifies logical and bitwise operations 250** nicely. 251*/ 252#define FICL_TRUE ((unsigned long)~(0L)) 253#define FICL_FALSE (0) 254#define FICL_BOOL(x) ((x) ? FICL_TRUE : FICL_FALSE) 255 256 257/* 258** A CELL is the main storage type. It must be large enough 259** to contain a pointer or a scalar. In order to accommodate |
257** 32 bit and 64 bit processors, use abstract types for i and u. | 260** 32 bit and 64 bit processors, use abstract types for int, 261** unsigned, and float. |
258*/ 259typedef union _cell 260{ 261 FICL_INT i; 262 FICL_UNS u; 263#if (FICL_WANT_FLOAT) 264 FICL_FLOAT f; 265#endif 266 void *p; 267 void (*fn)(void); 268} CELL; 269 270/* | 262*/ 263typedef union _cell 264{ 265 FICL_INT i; 266 FICL_UNS u; 267#if (FICL_WANT_FLOAT) 268 FICL_FLOAT f; 269#endif 270 void *p; 271 void (*fn)(void); 272} CELL; 273 274/* |
271** LVALUEtoCELL does a little pointer trickery to cast any 32 bit | 275** LVALUEtoCELL does a little pointer trickery to cast any CELL sized |
272** lvalue (informal definition: an expression whose result has an 273** address) to CELL. Remember that constants and casts are NOT 274** themselves lvalues! 275*/ 276#define LVALUEtoCELL(v) (*(CELL *)&v) 277 278/* 279** PTRtoCELL is a cast through void * intended to satisfy the --- 78 unchanged lines hidden (view full) --- 358 CELL *pFrame; /* link reg for stack frame */ 359 CELL *sp; /* stack pointer */ 360 CELL base[1]; /* Top of stack */ 361} FICL_STACK; 362 363/* 364** Stack methods... many map closely to required Forth words. 365*/ | 276** lvalue (informal definition: an expression whose result has an 277** address) to CELL. Remember that constants and casts are NOT 278** themselves lvalues! 279*/ 280#define LVALUEtoCELL(v) (*(CELL *)&v) 281 282/* 283** PTRtoCELL is a cast through void * intended to satisfy the --- 78 unchanged lines hidden (view full) --- 362 CELL *pFrame; /* link reg for stack frame */ 363 CELL *sp; /* stack pointer */ 364 CELL base[1]; /* Top of stack */ 365} FICL_STACK; 366 367/* 368** Stack methods... many map closely to required Forth words. 369*/ |
366FICL_STACK *stackCreate(unsigned nCells); 367void stackDelete(FICL_STACK *pStack); 368int stackDepth (FICL_STACK *pStack); 369void stackDrop (FICL_STACK *pStack, int n); 370CELL stackFetch (FICL_STACK *pStack, int n); 371CELL stackGetTop(FICL_STACK *pStack); 372void stackLink (FICL_STACK *pStack, int nCells); 373void stackPick (FICL_STACK *pStack, int n); 374CELL stackPop (FICL_STACK *pStack); 375void *stackPopPtr(FICL_STACK *pStack); 376FICL_UNS stackPopUNS(FICL_STACK *pStack); 377FICL_INT stackPopINT(FICL_STACK *pStack); 378void stackPush (FICL_STACK *pStack, CELL c); | 370FICL_STACK *stackCreate (unsigned nCells); 371void stackDelete (FICL_STACK *pStack); 372int stackDepth (FICL_STACK *pStack); 373void stackDrop (FICL_STACK *pStack, int n); 374CELL stackFetch (FICL_STACK *pStack, int n); 375CELL stackGetTop (FICL_STACK *pStack); 376void stackLink (FICL_STACK *pStack, int nCells); 377void stackPick (FICL_STACK *pStack, int n); 378CELL stackPop (FICL_STACK *pStack); 379void *stackPopPtr (FICL_STACK *pStack); 380FICL_UNS stackPopUNS (FICL_STACK *pStack); 381FICL_INT stackPopINT (FICL_STACK *pStack); 382void stackPush (FICL_STACK *pStack, CELL c); |
379void stackPushPtr (FICL_STACK *pStack, void *ptr); | 383void stackPushPtr (FICL_STACK *pStack, void *ptr); |
380void stackPushUNS(FICL_STACK *pStack, FICL_UNS u); 381void stackPushINT(FICL_STACK *pStack, FICL_INT i); 382void stackReset (FICL_STACK *pStack); 383void stackRoll (FICL_STACK *pStack, int n); 384void stackSetTop(FICL_STACK *pStack, CELL c); 385void stackStore (FICL_STACK *pStack, int n, CELL c); 386void stackUnlink(FICL_STACK *pStack); | 384void stackPushUNS (FICL_STACK *pStack, FICL_UNS u); 385void stackPushINT (FICL_STACK *pStack, FICL_INT i); 386void stackReset (FICL_STACK *pStack); 387void stackRoll (FICL_STACK *pStack, int n); 388void stackSetTop (FICL_STACK *pStack, CELL c); 389void stackStore (FICL_STACK *pStack, int n, CELL c); 390void stackUnlink (FICL_STACK *pStack); |
387 388#if (FICL_WANT_FLOAT) 389float stackPopFloat (FICL_STACK *pStack); | 391 392#if (FICL_WANT_FLOAT) 393float stackPopFloat (FICL_STACK *pStack); |
390void stackPushFloat(FICL_STACK *pStack, float f); | 394void stackPushFloat(FICL_STACK *pStack, FICL_FLOAT f); |
391#endif 392 393/* 394** Shortcuts (Guy Carver) 395*/ | 395#endif 396 397/* 398** Shortcuts (Guy Carver) 399*/ |
396#define PUSHPTR(p) stackPushPtr(pVM->pStack,p) 397#define PUSHUNS(u) stackPushUNS(pVM->pStack,u) 398#define PUSHINT(i) stackPushINT(pVM->pStack,i) 399#define PUSHFLOAT(f) stackPushFloat(pVM->fStack,f) 400#define PUSH(c) stackPush(pVM->pStack,c) 401#define POPPTR() stackPopPtr(pVM->pStack) 402#define POPUNS() stackPopUNS(pVM->pStack) 403#define POPINT() stackPopINT(pVM->pStack) 404#define POPFLOAT() stackPopFloat(pVM->fStack) 405#define POP() stackPop(pVM->pStack) 406#define GETTOP() stackGetTop(pVM->pStack) 407#define SETTOP(c) stackSetTop(pVM->pStack,LVALUEtoCELL(c)) 408#define GETTOPF() stackGetTop(pVM->fStack) 409#define SETTOPF(c) stackSetTop(pVM->fStack,LVALUEtoCELL(c)) 410#define STORE(n,c) stackStore(pVM->pStack,n,LVALUEtoCELL(c)) 411#define DEPTH() stackDepth(pVM->pStack) 412#define DROP(n) stackDrop(pVM->pStack,n) 413#define DROPF(n) stackDrop(pVM->fStack,n) 414#define FETCH(n) stackFetch(pVM->pStack,n) 415#define PICK(n) stackPick(pVM->pStack,n) 416#define PICKF(n) stackPick(pVM->fStack,n) 417#define ROLL(n) stackRoll(pVM->pStack,n) 418#define ROLLF(n) stackRoll(pVM->fStack,n) | 400#define PUSHPTR(p) stackPushPtr(pVM->pStack,p) 401#define PUSHUNS(u) stackPushUNS(pVM->pStack,u) 402#define PUSHINT(i) stackPushINT(pVM->pStack,i) 403#define PUSHFLOAT(f) stackPushFloat(pVM->fStack,f) 404#define PUSH(c) stackPush(pVM->pStack,c) 405#define POPPTR() stackPopPtr(pVM->pStack) 406#define POPUNS() stackPopUNS(pVM->pStack) 407#define POPINT() stackPopINT(pVM->pStack) 408#define POPFLOAT() stackPopFloat(pVM->fStack) 409#define POP() stackPop(pVM->pStack) 410#define GETTOP() stackGetTop(pVM->pStack) 411#define SETTOP(c) stackSetTop(pVM->pStack,LVALUEtoCELL(c)) 412#define GETTOPF() stackGetTop(pVM->fStack) 413#define SETTOPF(c) stackSetTop(pVM->fStack,LVALUEtoCELL(c)) 414#define STORE(n,c) stackStore(pVM->pStack,n,LVALUEtoCELL(c)) 415#define DEPTH() stackDepth(pVM->pStack) 416#define DROP(n) stackDrop(pVM->pStack,n) 417#define DROPF(n) stackDrop(pVM->fStack,n) 418#define FETCH(n) stackFetch(pVM->pStack,n) 419#define PICK(n) stackPick(pVM->pStack,n) 420#define PICKF(n) stackPick(pVM->fStack,n) 421#define ROLL(n) stackRoll(pVM->pStack,n) 422#define ROLLF(n) stackRoll(pVM->fStack,n) |
419 420/* 421** The virtual machine (VM) contains the state for one interpreter. 422** Defined operations include: 423** Create & initialize 424** Delete 425** Execute a block of text 426** Parse a word out of the input stream 427** Call return, and branch 428** Text output 429** Throw an exception 430*/ 431 | 423 424/* 425** The virtual machine (VM) contains the state for one interpreter. 426** Defined operations include: 427** Create & initialize 428** Delete 429** Execute a block of text 430** Parse a word out of the input stream 431** Call return, and branch 432** Text output 433** Throw an exception 434*/ 435 |
432typedef struct ficl_word ** IPTYPE; /* the VM's instruction pointer */ | 436typedef FICL_WORD ** IPTYPE; /* the VM's instruction pointer */ |
433 434/* 435** Each VM has a placeholder for an output function - 436** this makes it possible to have each VM do I/O 437** through a different device. If you specify no 438** OUTFUNC, it defaults to ficlTextOut. 439*/ | 437 438/* 439** Each VM has a placeholder for an output function - 440** this makes it possible to have each VM do I/O 441** through a different device. If you specify no 442** OUTFUNC, it defaults to ficlTextOut. 443*/ |
440typedef void (*OUTFUNC)(struct vm *pVM, char *text, int fNewline); | 444typedef void (*OUTFUNC)(FICL_VM *pVM, char *text, int fNewline); |
441 442/* 443** Each VM operates in one of two non-error states: interpreting 444** or compiling. When interpreting, words are simply executed. 445** When compiling, most words in the input stream have their 446** addresses inserted into the word under construction. Some words 447** (known as IMMEDIATE) are executed in the compile state, too. 448*/ --- 14 unchanged lines hidden (view full) --- 463*/ 464#if !defined nFICLNAME 465#define nFICLNAME 31 466#endif 467 468/* 469** OK - now we can really define the VM... 470*/ | 445 446/* 447** Each VM operates in one of two non-error states: interpreting 448** or compiling. When interpreting, words are simply executed. 449** When compiling, most words in the input stream have their 450** addresses inserted into the word under construction. Some words 451** (known as IMMEDIATE) are executed in the compile state, too. 452*/ --- 14 unchanged lines hidden (view full) --- 467*/ 468#if !defined nFICLNAME 469#define nFICLNAME 31 470#endif 471 472/* 473** OK - now we can really define the VM... 474*/ |
471typedef struct vm | 475struct vm |
472{ 473 FICL_SYSTEM *pSys; /* Which system this VM belongs to */ | 476{ 477 FICL_SYSTEM *pSys; /* Which system this VM belongs to */ |
474 struct vm *link; /* Ficl keeps a VM list for simple teardown */ | 478 FICL_VM *link; /* Ficl keeps a VM list for simple teardown */ |
475 jmp_buf *pState; /* crude exception mechanism... */ 476 OUTFUNC textOut; /* Output callback - see sysdep.c */ | 479 jmp_buf *pState; /* crude exception mechanism... */ 480 OUTFUNC textOut; /* Output callback - see sysdep.c */ |
477 void * pExtend; /* vm extension pointer */ | 481 void * pExtend; /* vm extension pointer for app use - initialized from FICL_SYSTEM */ |
478 short fRestart; /* Set TRUE to restart runningWord */ 479 IPTYPE ip; /* instruction pointer */ | 482 short fRestart; /* Set TRUE to restart runningWord */ 483 IPTYPE ip; /* instruction pointer */ |
480 struct ficl_word 481 *runningWord;/* address of currently running word (often just *(ip-1) ) */ | 484 FICL_WORD *runningWord;/* address of currently running word (often just *(ip-1) ) */ |
482 FICL_UNS state; /* compiling or interpreting */ 483 FICL_UNS base; /* number conversion base */ 484 FICL_STACK *pStack; /* param stack */ 485 FICL_STACK *rStack; /* return stack */ 486#if FICL_WANT_FLOAT 487 FICL_STACK *fStack; /* float stack (optional) */ 488#endif | 485 FICL_UNS state; /* compiling or interpreting */ 486 FICL_UNS base; /* number conversion base */ 487 FICL_STACK *pStack; /* param stack */ 488 FICL_STACK *rStack; /* return stack */ 489#if FICL_WANT_FLOAT 490 FICL_STACK *fStack; /* float stack (optional) */ 491#endif |
489 CELL sourceID; /* -1 if string, 0 if normal input */ | 492 CELL sourceID; /* -1 if EVALUATE, 0 if normal input */ |
490 TIB tib; /* address of incoming text string */ 491#if FICL_WANT_USER 492 CELL user[FICL_USER_CELLS]; 493#endif 494 char pad[nPAD]; /* the scratch area (see above) */ | 493 TIB tib; /* address of incoming text string */ 494#if FICL_WANT_USER 495 CELL user[FICL_USER_CELLS]; 496#endif 497 char pad[nPAD]; /* the scratch area (see above) */ |
495} FICL_VM; | 498}; |
496 497/* 498** A FICL_CODE points to a function that gets called to help execute 499** a word in the dictionary. It always gets passed a pointer to the 500** running virtual machine, and from there it can get the address 501** of the parameter area of the word it's supposed to operate on. 502** For precompiled words, the code is all there is. For user defined 503** words, the code assumes that the word's parameter area is a list --- 9 unchanged lines hidden (view full) --- 513#define VM_ASSERT(pVM) 514#endif 515 516/* 517** Ficl models memory as a contiguous space divided into 518** words in a linked list called the dictionary. 519** A FICL_WORD starts each entry in the list. 520** Version 1.02: space for the name characters is allotted from | 499 500/* 501** A FICL_CODE points to a function that gets called to help execute 502** a word in the dictionary. It always gets passed a pointer to the 503** running virtual machine, and from there it can get the address 504** of the parameter area of the word it's supposed to operate on. 505** For precompiled words, the code is all there is. For user defined 506** words, the code assumes that the word's parameter area is a list --- 9 unchanged lines hidden (view full) --- 516#define VM_ASSERT(pVM) 517#endif 518 519/* 520** Ficl models memory as a contiguous space divided into 521** words in a linked list called the dictionary. 522** A FICL_WORD starts each entry in the list. 523** Version 1.02: space for the name characters is allotted from |
521** the dictionary ahead of the word struct - this saves about half 522** the storage on average with very little runtime cost. | 524** the dictionary ahead of the word struct, rather than using 525** a fixed size array for each name. |
523*/ | 526*/ |
524typedef struct ficl_word | 527struct ficl_word |
525{ 526 struct ficl_word *link; /* Previous word in the dictionary */ 527 UNS16 hash; 528 UNS8 flags; /* Immediate, Smudge, Compile-only */ 529 FICL_COUNT nName; /* Number of chars in word name */ 530 char *name; /* First nFICLNAME chars of word name */ 531 FICL_CODE code; /* Native code to execute the word */ 532 CELL param[1]; /* First data cell of the word */ | 528{ 529 struct ficl_word *link; /* Previous word in the dictionary */ 530 UNS16 hash; 531 UNS8 flags; /* Immediate, Smudge, Compile-only */ 532 FICL_COUNT nName; /* Number of chars in word name */ 533 char *name; /* First nFICLNAME chars of word name */ 534 FICL_CODE code; /* Native code to execute the word */ 535 CELL param[1]; /* First data cell of the word */ |
533} FICL_WORD; | 536}; |
534 535/* 536** Worst-case size of a word header: nFICLNAME chars in name 537*/ 538#define CELLS_PER_WORD \ 539 ( (sizeof (FICL_WORD) + nFICLNAME + sizeof (CELL)) \ 540 / (sizeof (CELL)) ) 541 542int wordIsImmediate(FICL_WORD *pFW); 543int wordIsCompileOnly(FICL_WORD *pFW); 544 545/* flag values for word header */ 546#define FW_IMMEDIATE 1 /* execute me even if compiling */ 547#define FW_COMPILE 2 /* error if executed when not compiling */ 548#define FW_SMUDGE 4 /* definition in progress - hide me */ | 537 538/* 539** Worst-case size of a word header: nFICLNAME chars in name 540*/ 541#define CELLS_PER_WORD \ 542 ( (sizeof (FICL_WORD) + nFICLNAME + sizeof (CELL)) \ 543 / (sizeof (CELL)) ) 544 545int wordIsImmediate(FICL_WORD *pFW); 546int wordIsCompileOnly(FICL_WORD *pFW); 547 548/* flag values for word header */ 549#define FW_IMMEDIATE 1 /* execute me even if compiling */ 550#define FW_COMPILE 2 /* error if executed when not compiling */ 551#define FW_SMUDGE 4 /* definition in progress - hide me */ |
552#define FW_ISOBJECT 8 /* word is an object or object member variable */ |
|
549 550#define FW_COMPIMMED (FW_IMMEDIATE | FW_COMPILE) 551#define FW_DEFAULT 0 552 553 554/* 555** Exit codes for vmThrow 556*/ --- 4 unchanged lines hidden (view full) --- 561#define VM_ERREXIT -260 /* interp found an error */ 562#define VM_BREAK -261 /* debugger breakpoint */ 563#define VM_ABORT -1 /* like errexit -- abort */ 564#define VM_ABORTQ -2 /* like errexit -- abort" */ 565#define VM_QUIT -56 /* like errexit, but leave pStack & base alone */ 566 567 568void vmBranchRelative(FICL_VM *pVM, int offset); | 553 554#define FW_COMPIMMED (FW_IMMEDIATE | FW_COMPILE) 555#define FW_DEFAULT 0 556 557 558/* 559** Exit codes for vmThrow 560*/ --- 4 unchanged lines hidden (view full) --- 565#define VM_ERREXIT -260 /* interp found an error */ 566#define VM_BREAK -261 /* debugger breakpoint */ 567#define VM_ABORT -1 /* like errexit -- abort */ 568#define VM_ABORTQ -2 /* like errexit -- abort" */ 569#define VM_QUIT -56 /* like errexit, but leave pStack & base alone */ 570 571 572void vmBranchRelative(FICL_VM *pVM, int offset); |
569FICL_VM * vmCreate (FICL_VM *pVM, unsigned nPStack, unsigned nRStack); 570void vmDelete (FICL_VM *pVM); 571void vmExecute(FICL_VM *pVM, FICL_WORD *pWord); 572char * vmGetString(FICL_VM *pVM, FICL_STRING *spDest, char delimiter); 573STRINGINFO vmGetWord(FICL_VM *pVM); 574STRINGINFO vmGetWord0(FICL_VM *pVM); 575int vmGetWordToPad(FICL_VM *pVM); 576STRINGINFO vmParseString(FICL_VM *pVM, char delimiter); | 573FICL_VM * vmCreate (FICL_VM *pVM, unsigned nPStack, unsigned nRStack); 574void vmDelete (FICL_VM *pVM); 575void vmExecute (FICL_VM *pVM, FICL_WORD *pWord); 576FICL_DICT *vmGetDict (FICL_VM *pVM); 577char * vmGetString (FICL_VM *pVM, FICL_STRING *spDest, char delimiter); 578STRINGINFO vmGetWord (FICL_VM *pVM); 579STRINGINFO vmGetWord0 (FICL_VM *pVM); 580int vmGetWordToPad (FICL_VM *pVM); 581STRINGINFO vmParseString (FICL_VM *pVM, char delimiter); |
577STRINGINFO vmParseStringEx(FICL_VM *pVM, char delimiter, char fSkipLeading); | 582STRINGINFO vmParseStringEx(FICL_VM *pVM, char delimiter, char fSkipLeading); |
578CELL vmPop(FICL_VM *pVM); 579void vmPush(FICL_VM *pVM, CELL c); 580void vmPopIP (FICL_VM *pVM); 581void vmPushIP (FICL_VM *pVM, IPTYPE newIP); 582void vmQuit (FICL_VM *pVM); 583void vmReset (FICL_VM *pVM); 584void vmSetTextOut(FICL_VM *pVM, OUTFUNC textOut); 585#if FICL_WANT_DEBUGGER 586void vmStep(FICL_VM *pVM); 587#endif 588void vmTextOut(FICL_VM *pVM, char *text, int fNewline); 589void vmThrow (FICL_VM *pVM, int except); 590void vmThrowErr(FICL_VM *pVM, char *fmt, ...); | 583CELL vmPop (FICL_VM *pVM); 584void vmPush (FICL_VM *pVM, CELL c); 585void vmPopIP (FICL_VM *pVM); 586void vmPushIP (FICL_VM *pVM, IPTYPE newIP); 587void vmQuit (FICL_VM *pVM); 588void vmReset (FICL_VM *pVM); 589void vmSetTextOut (FICL_VM *pVM, OUTFUNC textOut); 590void vmTextOut (FICL_VM *pVM, char *text, int fNewline); 591void vmTextOut (FICL_VM *pVM, char *text, int fNewline); 592void vmThrow (FICL_VM *pVM, int except); 593void vmThrowErr (FICL_VM *pVM, char *fmt, ...); |
591 592#define vmGetRunningWord(pVM) ((pVM)->runningWord) 593 594 595/* 596** The inner interpreter - coded as a macro (see note for 597** INLINE_INNER_LOOP in sysdep.h for complaints about VC++ 5 598*/ 599#define M_VM_STEP(pVM) \ 600 FICL_WORD *tempFW = *(pVM)->ip++; \ 601 (pVM)->runningWord = tempFW; \ | 594 595#define vmGetRunningWord(pVM) ((pVM)->runningWord) 596 597 598/* 599** The inner interpreter - coded as a macro (see note for 600** INLINE_INNER_LOOP in sysdep.h for complaints about VC++ 5 601*/ 602#define M_VM_STEP(pVM) \ 603 FICL_WORD *tempFW = *(pVM)->ip++; \ 604 (pVM)->runningWord = tempFW; \ |
602 tempFW->code(pVM); \ | 605 tempFW->code(pVM); |
603 604#define M_INNER_LOOP(pVM) \ 605 for (;;) { M_VM_STEP(pVM) } 606 607 608#if INLINE_INNER_LOOP != 0 609#define vmInnerLoop(pVM) M_INNER_LOOP(pVM) 610#else --- 16 unchanged lines hidden (view full) --- 627** ANS forth seems to require the input buffer to be represented 628** as a pointer to the start of the buffer, and an index to the 629** next character to read. 630** PushTib points the VM to a new input string and optionally 631** returns a copy of the current state 632** PopTib restores the TIB state given a saved TIB from PushTib 633** GetInBuf returns a pointer to the next unused char of the TIB 634*/ | 606 607#define M_INNER_LOOP(pVM) \ 608 for (;;) { M_VM_STEP(pVM) } 609 610 611#if INLINE_INNER_LOOP != 0 612#define vmInnerLoop(pVM) M_INNER_LOOP(pVM) 613#else --- 16 unchanged lines hidden (view full) --- 630** ANS forth seems to require the input buffer to be represented 631** as a pointer to the start of the buffer, and an index to the 632** next character to read. 633** PushTib points the VM to a new input string and optionally 634** returns a copy of the current state 635** PopTib restores the TIB state given a saved TIB from PushTib 636** GetInBuf returns a pointer to the next unused char of the TIB 637*/ |
635void vmPushTib(FICL_VM *pVM, char *text, FICL_INT nChars, TIB *pSaveTib); 636void vmPopTib(FICL_VM *pVM, TIB *pTib); 637#define vmGetInBuf(pVM) ((pVM)->tib.cp + (pVM)->tib.index) 638#define vmGetInBufLen(pVM) ((pVM)->tib.end - (pVM)->tib.cp) 639#define vmGetInBufEnd(pVM) ((pVM)->tib.end) | 638void vmPushTib (FICL_VM *pVM, char *text, FICL_INT nChars, TIB *pSaveTib); 639void vmPopTib (FICL_VM *pVM, TIB *pTib); 640#define vmGetInBuf(pVM) ((pVM)->tib.cp + (pVM)->tib.index) 641#define vmGetInBufLen(pVM) ((pVM)->tib.end - (pVM)->tib.cp) 642#define vmGetInBufEnd(pVM) ((pVM)->tib.end) |
640#define vmGetTibIndex(pVM) (pVM)->tib.index 641#define vmSetTibIndex(pVM, i) (pVM)->tib.index = i 642#define vmUpdateTib(pVM, str) (pVM)->tib.index = (str) - (pVM)->tib.cp 643 644/* 645** Generally useful string manipulators omitted by ANSI C... 646** ltoa complements strtol 647*/ --- 33 unchanged lines hidden (view full) --- 681typedef struct ficl_hash 682{ 683 struct ficl_hash *link; /* link to parent class wordlist for OO */ 684 char *name; /* optional pointer to \0 terminated wordlist name */ 685 unsigned size; /* number of buckets in the hash */ 686 FICL_WORD *table[1]; 687} FICL_HASH; 688 | 643#define vmGetTibIndex(pVM) (pVM)->tib.index 644#define vmSetTibIndex(pVM, i) (pVM)->tib.index = i 645#define vmUpdateTib(pVM, str) (pVM)->tib.index = (str) - (pVM)->tib.cp 646 647/* 648** Generally useful string manipulators omitted by ANSI C... 649** ltoa complements strtol 650*/ --- 33 unchanged lines hidden (view full) --- 684typedef struct ficl_hash 685{ 686 struct ficl_hash *link; /* link to parent class wordlist for OO */ 687 char *name; /* optional pointer to \0 terminated wordlist name */ 688 unsigned size; /* number of buckets in the hash */ 689 FICL_WORD *table[1]; 690} FICL_HASH; 691 |
689void hashForget(FICL_HASH *pHash, void *where); 690UNS16 hashHashCode(STRINGINFO si); | 692void hashForget (FICL_HASH *pHash, void *where); 693UNS16 hashHashCode (STRINGINFO si); |
691void hashInsertWord(FICL_HASH *pHash, FICL_WORD *pFW); | 694void hashInsertWord(FICL_HASH *pHash, FICL_WORD *pFW); |
692FICL_WORD *hashLookup(struct ficl_hash *pHash, 693 STRINGINFO si, 694 UNS16 hashCode); 695void hashReset(FICL_HASH *pHash); | 695FICL_WORD *hashLookup (FICL_HASH *pHash, STRINGINFO si, UNS16 hashCode); 696void hashReset (FICL_HASH *pHash); |
696 697/* 698** A Dictionary is a linked list of FICL_WORDs. It is also Ficl's 699** memory model. Description of fields: 700** 701** here -- points to the next free byte in the dictionary. This 702** pointer is forced to be CELL-aligned before a definition is added. 703** Do not assume any specific alignment otherwise - Use dictAlign(). --- 16 unchanged lines hidden (view full) --- 720** pSearch -- array of pointers to wordlists. Managed as a stack. 721** Highest index is the first list in the search order. 722** nLists -- number of lists in pSearch. nLists-1 is the highest 723** filled slot in pSearch, and points to the first wordlist 724** in the search order 725** size -- number of cells in the dictionary (total) 726** dict -- start of data area. Must be at the end of the struct. 727*/ | 697 698/* 699** A Dictionary is a linked list of FICL_WORDs. It is also Ficl's 700** memory model. Description of fields: 701** 702** here -- points to the next free byte in the dictionary. This 703** pointer is forced to be CELL-aligned before a definition is added. 704** Do not assume any specific alignment otherwise - Use dictAlign(). --- 16 unchanged lines hidden (view full) --- 721** pSearch -- array of pointers to wordlists. Managed as a stack. 722** Highest index is the first list in the search order. 723** nLists -- number of lists in pSearch. nLists-1 is the highest 724** filled slot in pSearch, and points to the first wordlist 725** in the search order 726** size -- number of cells in the dictionary (total) 727** dict -- start of data area. Must be at the end of the struct. 728*/ |
728typedef struct ficl_dict | 729struct ficl_dict |
729{ 730 CELL *here; 731 FICL_WORD *smudge; 732 FICL_HASH *pForthWords; 733 FICL_HASH *pCompile; 734 FICL_HASH *pSearch[FICL_DEFAULT_VOCS]; 735 int nLists; 736 unsigned size; /* Number of cells in dict (total)*/ 737 CELL *dict; /* Base of dictionary memory */ | 730{ 731 CELL *here; 732 FICL_WORD *smudge; 733 FICL_HASH *pForthWords; 734 FICL_HASH *pCompile; 735 FICL_HASH *pSearch[FICL_DEFAULT_VOCS]; 736 int nLists; 737 unsigned size; /* Number of cells in dict (total)*/ 738 CELL *dict; /* Base of dictionary memory */ |
738} FICL_DICT; | 739}; |
739 740void *alignPtr(void *ptr); 741void dictAbortDefinition(FICL_DICT *pDict); | 740 741void *alignPtr(void *ptr); 742void dictAbortDefinition(FICL_DICT *pDict); |
742void dictAlign(FICL_DICT *pDict); 743int dictAllot(FICL_DICT *pDict, int n); 744int dictAllotCells(FICL_DICT *pDict, int nCells); 745void dictAppendCell(FICL_DICT *pDict, CELL c); 746void dictAppendChar(FICL_DICT *pDict, char c); 747FICL_WORD *dictAppendWord(FICL_DICT *pDict, | 743void dictAlign (FICL_DICT *pDict); 744int dictAllot (FICL_DICT *pDict, int n); 745int dictAllotCells (FICL_DICT *pDict, int nCells); 746void dictAppendCell (FICL_DICT *pDict, CELL c); 747void dictAppendChar (FICL_DICT *pDict, char c); 748FICL_WORD *dictAppendWord (FICL_DICT *pDict, |
748 char *name, 749 FICL_CODE pCode, 750 UNS8 flags); 751FICL_WORD *dictAppendWord2(FICL_DICT *pDict, 752 STRINGINFO si, 753 FICL_CODE pCode, 754 UNS8 flags); | 749 char *name, 750 FICL_CODE pCode, 751 UNS8 flags); 752FICL_WORD *dictAppendWord2(FICL_DICT *pDict, 753 STRINGINFO si, 754 FICL_CODE pCode, 755 UNS8 flags); |
755void dictAppendUNS(FICL_DICT *pDict, FICL_UNS u); 756int dictCellsAvail(FICL_DICT *pDict); 757int dictCellsUsed (FICL_DICT *pDict); 758void dictCheck(FICL_DICT *pDict, FICL_VM *pVM, int nCells); | 756void dictAppendUNS (FICL_DICT *pDict, FICL_UNS u); 757int dictCellsAvail (FICL_DICT *pDict); 758int dictCellsUsed (FICL_DICT *pDict); 759void dictCheck (FICL_DICT *pDict, FICL_VM *pVM, int n); |
759FICL_DICT *dictCreate(unsigned nCELLS); 760FICL_DICT *dictCreateHashed(unsigned nCells, unsigned nHash); 761FICL_HASH *dictCreateWordlist(FICL_DICT *dp, int nBuckets); | 760FICL_DICT *dictCreate(unsigned nCELLS); 761FICL_DICT *dictCreateHashed(unsigned nCells, unsigned nHash); 762FICL_HASH *dictCreateWordlist(FICL_DICT *dp, int nBuckets); |
762void dictDelete(FICL_DICT *pDict); 763void dictEmpty(FICL_DICT *pDict, unsigned nHash); 764int dictIncludes(FICL_DICT *pDict, void *p); 765FICL_WORD *dictLookup(FICL_DICT *pDict, STRINGINFO si); | 763void dictDelete (FICL_DICT *pDict); 764void dictEmpty (FICL_DICT *pDict, unsigned nHash); 765#if FICL_WANT_FLOAT 766void dictHashSummary(FICL_VM *pVM); 767#endif 768int dictIncludes (FICL_DICT *pDict, void *p); 769FICL_WORD *dictLookup (FICL_DICT *pDict, STRINGINFO si); |
766#if FICL_WANT_LOCALS | 770#if FICL_WANT_LOCALS |
767FICL_WORD *dictLookupLoc(FICL_DICT *pDict, STRINGINFO si); | 771FICL_WORD *ficlLookupLoc (FICL_SYSTEM *pSys, STRINGINFO si); |
768#endif 769void dictResetSearchOrder(FICL_DICT *pDict); | 772#endif 773void dictResetSearchOrder(FICL_DICT *pDict); |
770void dictSetFlags(FICL_DICT *pDict, UNS8 set, UNS8 clr); | 774void dictSetFlags (FICL_DICT *pDict, UNS8 set, UNS8 clr); |
771void dictSetImmediate(FICL_DICT *pDict); | 775void dictSetImmediate(FICL_DICT *pDict); |
772void dictUnsmudge(FICL_DICT *pDict); 773CELL *dictWhere(FICL_DICT *pDict); | 776void dictUnsmudge (FICL_DICT *pDict); 777CELL *dictWhere (FICL_DICT *pDict); |
774 775 776/* 777** P A R S E S T E P 778** (New for 2.05) 779** See words.c: interpWord 780** By default, ficl goes through two attempts to parse each token from its input 781** stream: it first attempts to match it with a word in the dictionary, and --- 20 unchanged lines hidden (view full) --- 802** the dictionary. Precompiled parse steps can use (PARSE-STEP) as their 803** CFA - see parenParseStep in words.c. 804*/ 805int ficlAddParseStep(FICL_SYSTEM *pSys, FICL_WORD *pFW); /* ficl.c */ 806void ficlAddPrecompiledParseStep(FICL_SYSTEM *pSys, char *name, FICL_PARSE_STEP pStep); 807void ficlListParseSteps(FICL_VM *pVM); 808 809/* | 778 779 780/* 781** P A R S E S T E P 782** (New for 2.05) 783** See words.c: interpWord 784** By default, ficl goes through two attempts to parse each token from its input 785** stream: it first attempts to match it with a word in the dictionary, and --- 20 unchanged lines hidden (view full) --- 806** the dictionary. Precompiled parse steps can use (PARSE-STEP) as their 807** CFA - see parenParseStep in words.c. 808*/ 809int ficlAddParseStep(FICL_SYSTEM *pSys, FICL_WORD *pFW); /* ficl.c */ 810void ficlAddPrecompiledParseStep(FICL_SYSTEM *pSys, char *name, FICL_PARSE_STEP pStep); 811void ficlListParseSteps(FICL_VM *pVM); 812 813/* |
814** FICL_BREAKPOINT record. 815** origXT - if NULL, this breakpoint is unused. Otherwise it stores the xt 816** that the breakpoint overwrote. This is restored to the dictionary when the 817** BP executes or gets cleared 818** address - the location of the breakpoint (address of the instruction that 819** has been replaced with the breakpoint trap 820** origXT - The original contents of the location with the breakpoint 821** Note: address is NULL when this breakpoint is empty 822*/ 823typedef struct FICL_BREAKPOINT 824{ 825 void *address; 826 FICL_WORD *origXT; 827} FICL_BREAKPOINT; 828 829 830/* |
|
810** F I C L _ S Y S T E M 811** The top level data structure of the system - ficl_system ties a list of 812** virtual machines with their corresponding dictionaries. Ficl 3.0 will 813** support multiple Ficl systems, allowing multiple concurrent sessions 814** to separate dictionaries with some constraints. 815** The present model allows multiple sessions to one dictionary provided 816** you implement ficlLockDictionary() as specified in sysdep.h | 831** F I C L _ S Y S T E M 832** The top level data structure of the system - ficl_system ties a list of 833** virtual machines with their corresponding dictionaries. Ficl 3.0 will 834** support multiple Ficl systems, allowing multiple concurrent sessions 835** to separate dictionaries with some constraints. 836** The present model allows multiple sessions to one dictionary provided 837** you implement ficlLockDictionary() as specified in sysdep.h |
817** 818** RESTRICTIONS: due to the use of static variables in words.c for compiling 819** comtrol structures faster, if you use multiple ficl systems these variables 820** will point into the most recently initialized dictionary - this is probably 821** not a problem provided the precompiled dictionaries are identical for 822** all systems. | 838** Note: the pExtend pointer is there to provide context for applications. It is copied 839** to each VM's pExtend field as that VM is created. |
823*/ 824struct ficl_system 825{ 826 FICL_SYSTEM *link; | 840*/ 841struct ficl_system 842{ 843 FICL_SYSTEM *link; |
827 FICL_WORD *parseList[FICL_MAX_PARSE_STEPS]; | 844 void *pExtend; /* Initializes VM's pExtend pointer (for application use) */ |
828 FICL_VM *vmList; 829 FICL_DICT *dp; 830 FICL_DICT *envp; 831#ifdef FICL_WANT_LOCALS 832 FICL_DICT *localp; 833#endif 834 FICL_WORD *pInterp[3]; | 845 FICL_VM *vmList; 846 FICL_DICT *dp; 847 FICL_DICT *envp; 848#ifdef FICL_WANT_LOCALS 849 FICL_DICT *localp; 850#endif 851 FICL_WORD *pInterp[3]; |
852 FICL_WORD *parseList[FICL_MAX_PARSE_STEPS]; 853 OUTFUNC textOut; 854 855 FICL_WORD *pBranchParen; 856 FICL_WORD *pDoParen; 857 FICL_WORD *pDoesParen; 858 FICL_WORD *pExitInner; 859 FICL_WORD *pExitParen; 860 FICL_WORD *pIfParen; 861 FICL_WORD *pInterpret; 862 FICL_WORD *pLitParen; 863 FICL_WORD *pTwoLitParen; 864 FICL_WORD *pLoopParen; 865 FICL_WORD *pPLoopParen; 866 FICL_WORD *pQDoParen; 867 FICL_WORD *pSemiParen; 868 FICL_WORD *pStore; 869 FICL_WORD *pCStringLit; 870 FICL_WORD *pStringLit; 871 872#if FICL_WANT_LOCALS 873 FICL_WORD *pGetLocalParen; 874 FICL_WORD *pGet2LocalParen; 875 FICL_WORD *pGetLocal0; 876 FICL_WORD *pGetLocal1; 877 FICL_WORD *pToLocalParen; 878 FICL_WORD *pTo2LocalParen; 879 FICL_WORD *pToLocal0; 880 FICL_WORD *pToLocal1; 881 FICL_WORD *pLinkParen; 882 FICL_WORD *pUnLinkParen; 883 FICL_INT nLocals; 884 CELL *pMarkLocals; 885#endif 886 887 FICL_BREAKPOINT bpStep; |
|
835}; 836 | 888}; 889 |
890struct ficl_system_info 891{ 892 int size; /* structure size tag for versioning */ 893 int nDictCells; /* Size of system's Dictionary */ 894 OUTFUNC textOut; /* default textOut function */ 895 void *pExtend; /* Initializes VM's pExtend pointer - for application use */ 896 int nEnvCells; /* Size of Environment dictionary */ 897}; 898 899 900#define ficlInitInfo(x) { memset((x), 0, sizeof(FICL_SYSTEM_INFO)); \ 901 (x)->size = sizeof(FICL_SYSTEM_INFO); } 902 |
|
837/* 838** External interface to FICL... 839*/ 840/* 841** f i c l I n i t S y s t e m 842** Binds a global dictionary to the interpreter system and initializes 843** the dict to contain the ANSI CORE wordset. | 903/* 904** External interface to FICL... 905*/ 906/* 907** f i c l I n i t S y s t e m 908** Binds a global dictionary to the interpreter system and initializes 909** the dict to contain the ANSI CORE wordset. |
844** You specify the address and size of the allocated area. | 910** You can specify the address and size of the allocated area. 911** Using ficlInitSystemEx you can also specify the text output function. |
845** After that, ficl manages it. 846** First step is to set up the static pointers to the area. 847** Then write the "precompiled" portion of the dictionary in. 848** The dictionary needs to be at least large enough to hold the 849** precompiled part. Try 1K cells minimum. Use "words" to find 850** out how much of the dictionary is used at any time. 851*/ | 912** After that, ficl manages it. 913** First step is to set up the static pointers to the area. 914** Then write the "precompiled" portion of the dictionary in. 915** The dictionary needs to be at least large enough to hold the 916** precompiled part. Try 1K cells minimum. Use "words" to find 917** out how much of the dictionary is used at any time. 918*/ |
852void ficlInitSystem(int nDictCells); | 919FICL_SYSTEM *ficlInitSystemEx(FICL_SYSTEM_INFO *fsi); |
853 | 920 |
921/* Deprecated call */ 922FICL_SYSTEM *ficlInitSystem(int nDictCells); 923 |
|
854/* 855** f i c l T e r m S y s t e m 856** Deletes the system dictionary and all virtual machines that 857** were created with ficlNewVM (see below). Call this function to 858** reclaim all memory used by the dictionary and VMs. 859*/ | 924/* 925** f i c l T e r m S y s t e m 926** Deletes the system dictionary and all virtual machines that 927** were created with ficlNewVM (see below). Call this function to 928** reclaim all memory used by the dictionary and VMs. 929*/ |
860void ficlTermSystem(void); | 930void ficlTermSystem(FICL_SYSTEM *pSys); |
861 862/* | 931 932/* |
933** f i c l E v a l u a t e 934** Evaluates a block of input text in the context of the 935** specified interpreter. Also sets SOURCE-ID properly. 936** 937** PLEASE USE THIS FUNCTION when throwing a hard-coded 938** string to the FICL interpreter. 939*/ 940int ficlEvaluate(FICL_VM *pVM, char *pText); 941 942/* |
|
863** f i c l E x e c 864** Evaluates a block of input text in the context of the 865** specified interpreter. Emits any requested output to the 866** interpreter's output function. If the input string is NULL 867** terminated, you can pass -1 as nChars rather than count it. 868** Execution returns when the text block has been executed, 869** or an error occurs. 870** Returns one of the VM_XXXX codes defined in ficl.h: --- 4 unchanged lines hidden (view full) --- 875** VM_USEREXIT means that the user executed the "bye" command 876** to shut down the interpreter. This would be a good 877** time to delete the vm, etc -- or you can ignore this 878** signal. 879** VM_ABORT and VM_ABORTQ are generated by 'abort' and 'abort"' 880** commands. 881** Preconditions: successful execution of ficlInitSystem, 882** Successful creation and init of the VM by ficlNewVM (or equiv) | 943** f i c l E x e c 944** Evaluates a block of input text in the context of the 945** specified interpreter. Emits any requested output to the 946** interpreter's output function. If the input string is NULL 947** terminated, you can pass -1 as nChars rather than count it. 948** Execution returns when the text block has been executed, 949** or an error occurs. 950** Returns one of the VM_XXXX codes defined in ficl.h: --- 4 unchanged lines hidden (view full) --- 955** VM_USEREXIT means that the user executed the "bye" command 956** to shut down the interpreter. This would be a good 957** time to delete the vm, etc -- or you can ignore this 958** signal. 959** VM_ABORT and VM_ABORTQ are generated by 'abort' and 'abort"' 960** commands. 961** Preconditions: successful execution of ficlInitSystem, 962** Successful creation and init of the VM by ficlNewVM (or equiv) |
963** 964** If you call ficlExec() or one of its brothers, you MUST 965** ensure pVM->sourceID was set to a sensible value. 966** ficlExec() explicitly DOES NOT manage SOURCE-ID for you. |
|
883*/ 884int ficlExec (FICL_VM *pVM, char *pText); 885int ficlExecC(FICL_VM *pVM, char *pText, FICL_INT nChars); 886int ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord); 887 888/* 889** ficlExecFD(FICL_VM *pVM, int fd); 890 * Evaluates text from file passed in via fd. 891 * Execution returns when all of file has been executed or an 892 * error occurs. 893 */ 894int ficlExecFD(FICL_VM *pVM, int fd); 895 896/* 897** Create a new VM from the heap, and link it into the system VM list. 898** Initializes the VM and binds default sized stacks to it. Returns the 899** address of the VM, or NULL if an error occurs. 900** Precondition: successful execution of ficlInitSystem 901*/ | 967*/ 968int ficlExec (FICL_VM *pVM, char *pText); 969int ficlExecC(FICL_VM *pVM, char *pText, FICL_INT nChars); 970int ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord); 971 972/* 973** ficlExecFD(FICL_VM *pVM, int fd); 974 * Evaluates text from file passed in via fd. 975 * Execution returns when all of file has been executed or an 976 * error occurs. 977 */ 978int ficlExecFD(FICL_VM *pVM, int fd); 979 980/* 981** Create a new VM from the heap, and link it into the system VM list. 982** Initializes the VM and binds default sized stacks to it. Returns the 983** address of the VM, or NULL if an error occurs. 984** Precondition: successful execution of ficlInitSystem 985*/ |
902FICL_VM *ficlNewVM(void); | 986FICL_VM *ficlNewVM(FICL_SYSTEM *pSys); |
903 904/* 905** Force deletion of a VM. You do not need to do this 906** unless you're creating and discarding a lot of VMs. 907** For systems that use a constant pool of VMs for the life 908** of the system, ficltermSystem takes care of VM cleanup 909** automatically. 910*/ --- 6 unchanged lines hidden (view full) --- 917*/ 918int ficlSetStackSize(int nStackCells); 919 920/* 921** Returns the address of the most recently defined word in the system 922** dictionary with the given name, or NULL if no match. 923** Precondition: successful execution of ficlInitSystem 924*/ | 987 988/* 989** Force deletion of a VM. You do not need to do this 990** unless you're creating and discarding a lot of VMs. 991** For systems that use a constant pool of VMs for the life 992** of the system, ficltermSystem takes care of VM cleanup 993** automatically. 994*/ --- 6 unchanged lines hidden (view full) --- 1001*/ 1002int ficlSetStackSize(int nStackCells); 1003 1004/* 1005** Returns the address of the most recently defined word in the system 1006** dictionary with the given name, or NULL if no match. 1007** Precondition: successful execution of ficlInitSystem 1008*/ |
925FICL_WORD *ficlLookup(char *name); | 1009FICL_WORD *ficlLookup(FICL_SYSTEM *pSys, char *name); |
926 927/* 928** f i c l G e t D i c t 929** Utility function - returns the address of the system dictionary. 930** Precondition: successful execution of ficlInitSystem 931*/ | 1010 1011/* 1012** f i c l G e t D i c t 1013** Utility function - returns the address of the system dictionary. 1014** Precondition: successful execution of ficlInitSystem 1015*/ |
932FICL_DICT *ficlGetDict(void); 933FICL_DICT *ficlGetEnv(void); 934void ficlSetEnv(char *name, FICL_UNS value); 935void ficlSetEnvD(char *name, FICL_UNS hi, FICL_UNS lo); | 1016FICL_DICT *ficlGetDict(FICL_SYSTEM *pSys); 1017FICL_DICT *ficlGetEnv (FICL_SYSTEM *pSys); 1018void ficlSetEnv (FICL_SYSTEM *pSys, char *name, FICL_UNS value); 1019void ficlSetEnvD(FICL_SYSTEM *pSys, char *name, FICL_UNS hi, FICL_UNS lo); |
936#if FICL_WANT_LOCALS | 1020#if FICL_WANT_LOCALS |
937FICL_DICT *ficlGetLoc(void); | 1021FICL_DICT *ficlGetLoc (FICL_SYSTEM *pSys); |
938#endif 939/* 940** f i c l B u i l d 941** Builds a word into the system default dictionary in a thread-safe way. 942** Preconditions: system must be initialized, and there must 943** be enough space for the new word's header! Operation is 944** controlled by ficlLockDictionary, so any initialization 945** required by your version of the function (if you "overrode" 946** it) must be complete at this point. 947** Parameters: 948** name -- the name of the word to be built 949** code -- code to execute when the word is invoked - must take a single param 950** pointer to a FICL_VM 951** flags -- 0 or more of FW_IMMEDIATE, FW_COMPILE, use bitwise OR! 952** Most words can use FW_DEFAULT. 953** nAllot - number of extra cells to allocate in the parameter area (usually zero) 954*/ | 1022#endif 1023/* 1024** f i c l B u i l d 1025** Builds a word into the system default dictionary in a thread-safe way. 1026** Preconditions: system must be initialized, and there must 1027** be enough space for the new word's header! Operation is 1028** controlled by ficlLockDictionary, so any initialization 1029** required by your version of the function (if you "overrode" 1030** it) must be complete at this point. 1031** Parameters: 1032** name -- the name of the word to be built 1033** code -- code to execute when the word is invoked - must take a single param 1034** pointer to a FICL_VM 1035** flags -- 0 or more of FW_IMMEDIATE, FW_COMPILE, use bitwise OR! 1036** Most words can use FW_DEFAULT. 1037** nAllot - number of extra cells to allocate in the parameter area (usually zero) 1038*/ |
955int ficlBuild(char *name, FICL_CODE code, char flags); | 1039int ficlBuild(FICL_SYSTEM *pSys, char *name, FICL_CODE code, char flags); |
956 957/* 958** f i c l C o m p i l e C o r e 959** Builds the ANS CORE wordset into the dictionary - called by 960** ficlInitSystem - no need to waste dict space by doing it again. 961*/ 962void ficlCompileCore(FICL_SYSTEM *pSys); 963void ficlCompilePrefix(FICL_SYSTEM *pSys); 964void ficlCompileSearch(FICL_SYSTEM *pSys); 965void ficlCompileSoftCore(FICL_SYSTEM *pSys); 966void ficlCompileTools(FICL_SYSTEM *pSys); | 1040 1041/* 1042** f i c l C o m p i l e C o r e 1043** Builds the ANS CORE wordset into the dictionary - called by 1044** ficlInitSystem - no need to waste dict space by doing it again. 1045*/ 1046void ficlCompileCore(FICL_SYSTEM *pSys); 1047void ficlCompilePrefix(FICL_SYSTEM *pSys); 1048void ficlCompileSearch(FICL_SYSTEM *pSys); 1049void ficlCompileSoftCore(FICL_SYSTEM *pSys); 1050void ficlCompileTools(FICL_SYSTEM *pSys); |
1051void ficlCompileFile(FICL_SYSTEM *pSys); |
|
967#if FICL_WANT_FLOAT 968void ficlCompileFloat(FICL_SYSTEM *pSys); | 1052#if FICL_WANT_FLOAT 1053void ficlCompileFloat(FICL_SYSTEM *pSys); |
1054int ficlParseFloatNumber( FICL_VM *pVM, STRINGINFO si ); /* float.c */ |
|
969#endif 970#if FICL_PLATFORM_EXTEND 971void ficlCompilePlatform(FICL_SYSTEM *pSys); 972#endif | 1055#endif 1056#if FICL_PLATFORM_EXTEND 1057void ficlCompilePlatform(FICL_SYSTEM *pSys); 1058#endif |
1059int ficlParsePrefix(FICL_VM *pVM, STRINGINFO si); |
|
973 974/* 975** from words.c... 976*/ 977void constantParen(FICL_VM *pVM); 978void twoConstParen(FICL_VM *pVM); 979int ficlParseNumber(FICL_VM *pVM, STRINGINFO si); 980void ficlTick(FICL_VM *pVM); 981void parseStepParen(FICL_VM *pVM); 982 983/* 984** From tools.c 985*/ | 1060 1061/* 1062** from words.c... 1063*/ 1064void constantParen(FICL_VM *pVM); 1065void twoConstParen(FICL_VM *pVM); 1066int ficlParseNumber(FICL_VM *pVM, STRINGINFO si); 1067void ficlTick(FICL_VM *pVM); 1068void parseStepParen(FICL_VM *pVM); 1069 1070/* 1071** From tools.c 1072*/ |
986int isAFiclWord(FICL_WORD *pFW); | 1073int isAFiclWord(FICL_DICT *pd, FICL_WORD *pFW); |
987 988/* 989** The following supports SEE and the debugger. 990*/ 991typedef enum 992{ 993 BRANCH, 994 COLON, 995 CONSTANT, 996 CREATE, 997 DO, 998 DOES, 999 IF, 1000 LITERAL, 1001 LOOP, 1002 PLOOP, 1003 PRIMITIVE, 1004 QDO, 1005 STRINGLIT, | 1074 1075/* 1076** The following supports SEE and the debugger. 1077*/ 1078typedef enum 1079{ 1080 BRANCH, 1081 COLON, 1082 CONSTANT, 1083 CREATE, 1084 DO, 1085 DOES, 1086 IF, 1087 LITERAL, 1088 LOOP, 1089 PLOOP, 1090 PRIMITIVE, 1091 QDO, 1092 STRINGLIT, |
1093 CSTRINGLIT, 1094#if FICL_WANT_USER |
|
1006 USER, | 1095 USER, |
1096#endif |
|
1007 VARIABLE, 1008} WORDKIND; | 1097 VARIABLE, 1098} WORDKIND; |
1099 |
|
1009WORDKIND ficlWordClassify(FICL_WORD *pFW); 1010 1011/* 1012** Dictionary on-demand resizing 1013*/ 1014extern CELL dictThreshold; 1015extern CELL dictIncrease; 1016 --- 14 unchanged lines hidden (view full) --- 1031extern void ficlCopyin(FICL_VM *pVM); 1032extern void ficlCopyout(FICL_VM *pVM); 1033extern void ficlFindfile(FICL_VM *pVM); 1034extern void ficlPnpdevices(FICL_VM *pVM); 1035extern void ficlPnphandlers(FICL_VM *pVM); 1036extern void ficlCcall(FICL_VM *pVM); 1037#endif 1038 | 1100WORDKIND ficlWordClassify(FICL_WORD *pFW); 1101 1102/* 1103** Dictionary on-demand resizing 1104*/ 1105extern CELL dictThreshold; 1106extern CELL dictIncrease; 1107 --- 14 unchanged lines hidden (view full) --- 1122extern void ficlCopyin(FICL_VM *pVM); 1123extern void ficlCopyout(FICL_VM *pVM); 1124extern void ficlFindfile(FICL_VM *pVM); 1125extern void ficlPnpdevices(FICL_VM *pVM); 1126extern void ficlPnphandlers(FICL_VM *pVM); 1127extern void ficlCcall(FICL_VM *pVM); 1128#endif 1129 |
1130/* 1131** Used with File-Access wordset. 1132*/ 1133#define FICL_FAM_READ 1 1134#define FICL_FAM_WRITE 2 1135#define FICL_FAM_APPEND 4 1136#define FICL_FAM_BINARY 8 1137 1138#define FICL_FAM_OPEN_MODE(fam) ((fam) & (FICL_FAM_READ | FICL_FAM_WRITE | FICL_FAM_APPEND)) 1139 1140 1141#if (FICL_WANT_FILE) 1142typedef struct ficlFILE 1143{ 1144 FILE *f; 1145 char filename[256]; 1146} ficlFILE; 1147#endif 1148 |
|
1039#ifdef __cplusplus 1040} 1041#endif 1042 1043#endif /* __FICL_H__ */ | 1149#ifdef __cplusplus 1150} 1151#endif 1152 1153#endif /* __FICL_H__ */ |