diff options
author | dcs <dcs@FreeBSD.org> | 2000-05-26 21:35:08 +0000 |
---|---|---|
committer | dcs <dcs@FreeBSD.org> | 2000-05-26 21:35:08 +0000 |
commit | 7a420274fbed079ac250b4ae0c7b855019210ad1 (patch) | |
tree | 7ae524b4e999135a3abc629f8bb333551970c81a /sys/boot/ficl | |
parent | e7de7487d9f2c8301120a8d7b0764cff65dead8c (diff) | |
download | FreeBSD-src-7a420274fbed079ac250b4ae0c7b855019210ad1.zip FreeBSD-src-7a420274fbed079ac250b4ae0c7b855019210ad1.tar.gz |
Bring in FICL 2.04. No bump of loader version is required by this
commit.
Diffstat (limited to 'sys/boot/ficl')
-rw-r--r-- | sys/boot/ficl/dict.c | 3 | ||||
-rw-r--r-- | sys/boot/ficl/ficl.c | 53 | ||||
-rw-r--r-- | sys/boot/ficl/ficl.h | 24 | ||||
-rw-r--r-- | sys/boot/ficl/softwords/classes.fr | 12 | ||||
-rw-r--r-- | sys/boot/ficl/softwords/jhlocal.fr | 35 | ||||
-rw-r--r-- | sys/boot/ficl/softwords/oo.fr | 36 | ||||
-rw-r--r-- | sys/boot/ficl/softwords/softcore.fr | 2 | ||||
-rw-r--r-- | sys/boot/ficl/vm.c | 48 | ||||
-rw-r--r-- | sys/boot/ficl/words.c | 372 |
9 files changed, 423 insertions, 162 deletions
diff --git a/sys/boot/ficl/dict.c b/sys/boot/ficl/dict.c index a2f5990..5f75a25 100644 --- a/sys/boot/ficl/dict.c +++ b/sys/boot/ficl/dict.c @@ -381,8 +381,7 @@ void dictDelete(FICL_DICT *pDict) /************************************************************************** d i c t E m p t y ** Empty the dictionary, reset its hash table, and reset its search order. -** Clears and (re-)creates the main hash table (pForthWords) with the -** size specified by nHash. +** Clears and (re-)creates the hash table with the size specified by nHash. **************************************************************************/ void dictEmpty(FICL_DICT *pDict, unsigned nHash) { diff --git a/sys/boot/ficl/ficl.c b/sys/boot/ficl/ficl.c index ad776be..60e12b3 100644 --- a/sys/boot/ficl/ficl.c +++ b/sys/boot/ficl/ficl.c @@ -132,6 +132,38 @@ FICL_VM *ficlNewVM(void) /************************************************************************** + f i c l F r e e V M +** Removes the VM in question from the system VM list and deletes the +** memory allocated to it. This is an optional call, since ficlTermSystem +** will do this cleanup for you. This function is handy if you're going to +** do a lot of dynamic creation of VMs. +**************************************************************************/ +void ficlFreeVM(FICL_VM *pVM) +{ + FICL_VM *pList = vmList; + + assert(pVM != 0); + + if (vmList == pVM) + { + vmList = vmList->link; + } + else for (pList; pList != 0; pList = pList->link) + { + if (pList->link == pVM) + { + pList->link = pVM->link; + break; + } + } + + if (pList) + vmDelete(pVM); + return; +} + + +/************************************************************************** f i c l B u i l d ** Builds a word into the dictionary. ** Preconditions: system must be initialized, and there must @@ -151,6 +183,7 @@ int ficlBuild(char *name, FICL_CODE code, char flags) int err = ficlLockDictionary(TRUE); if (err) return err; + assert(dictCellsAvail(dp) > sizeof (FICL_WORD) / sizeof (CELL)); dictAppendWord(dp, name, code, flags); ficlLockDictionary(FALSE); @@ -187,9 +220,8 @@ int ficlExecC(FICL_VM *pVM, char *pText, FICL_INT size) int except; jmp_buf vmState; + jmp_buf *oldState; TIB saveTib; - FICL_VM VM; - FICL_STACK rStack; if (!pInterp) pInterp = ficlLookup("interpret"); @@ -203,11 +235,9 @@ int ficlExecC(FICL_VM *pVM, char *pText, FICL_INT size) vmPushTib(pVM, pText, size, &saveTib); /* - ** Save and restore pVM and pVM->rStack to enable nested calls to ficlExec + ** Save and restore VM's jmp_buf to enable nested calls to ficlExec */ - memcpy((void*)&VM, (void*)pVM, sizeof(FICL_VM)); - memcpy((void*)&rStack, (void*)pVM->rStack, sizeof(FICL_STACK)); - + oldState = pVM->pState; pVM->pState = &vmState; /* This has to come before the setjmp! */ except = setjmp(vmState); @@ -267,14 +297,11 @@ int ficlExecC(FICL_VM *pVM, char *pText, FICL_INT size) #endif } dictResetSearchOrder(dp); - memcpy((void*)pVM, (void*)&VM, sizeof(FICL_VM)); - memcpy((void*)pVM->rStack, (void*)&rStack, sizeof(FICL_STACK)); - stackReset(pVM->pStack); - pVM->base = 10; + vmReset(pVM); break; } - pVM->pState = VM.pState; + pVM->pState = oldState; vmPopTib(pVM, &saveTib); return (except); } @@ -393,7 +420,7 @@ int ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord) vmThrow(pVM, except); } break; - } + } pVM->pState = oldState; return (except); @@ -543,3 +570,5 @@ void ficlTermSystem(void) return; } + + diff --git a/sys/boot/ficl/ficl.h b/sys/boot/ficl/ficl.h index ac5e57e..79199d1 100644 --- a/sys/boot/ficl/ficl.h +++ b/sys/boot/ficl/ficl.h @@ -517,11 +517,17 @@ STRINGINFO vmGetWord(FICL_VM *pVM); STRINGINFO vmGetWord0(FICL_VM *pVM); int vmGetWordToPad(FICL_VM *pVM); STRINGINFO vmParseString(FICL_VM *pVM, char delimiter); +STRINGINFO vmParseStringEx(FICL_VM *pVM, char delimiter, char fSkipLeading); +CELL vmPop(FICL_VM *pVM); +void vmPush(FICL_VM *pVM, CELL c); void vmPopIP (FICL_VM *pVM); void vmPushIP (FICL_VM *pVM, IPTYPE newIP); void vmQuit (FICL_VM *pVM); void vmReset (FICL_VM *pVM); void vmSetTextOut(FICL_VM *pVM, OUTFUNC textOut); +#if FICL_WANT_DEBUGGER +void vmStep(FICL_VM *pVM); +#endif void vmTextOut(FICL_VM *pVM, char *text, int fNewline); void vmThrow (FICL_VM *pVM, int except); void vmThrowErr(FICL_VM *pVM, char *fmt, ...); @@ -533,13 +539,13 @@ void vmThrowErr(FICL_VM *pVM, char *fmt, ...); ** The inner interpreter - coded as a macro (see note for ** INLINE_INNER_LOOP in sysdep.h for complaints about VC++ 5 */ -#define M_INNER_LOOP(pVM) \ - for (;;) \ - { \ +#define M_VM_STEP(pVM) \ FICL_WORD *tempFW = *(pVM)->ip++; \ (pVM)->runningWord = tempFW; \ tempFW->code(pVM); \ - } + +#define M_INNER_LOOP(pVM) \ + for (;;) { M_VM_STEP(pVM) } #if INLINE_INNER_LOOP != 0 @@ -772,6 +778,16 @@ int ficlExecFD(FICL_VM *pVM, int fd); FICL_VM *ficlNewVM(void); /* +** Force deletion of a VM. You do not need to do this +** unless you're creating and discarding a lot of VMs. +** For systems that use a constant pool of VMs for the life +** of the system, ficltermSystem takes care of VM cleanup +** automatically. +*/ +void ficlFreeVM(FICL_VM *pVM); + + +/* ** Set the stack sizes (return and parameter) to be used for all ** subsequently created VMs. Returns actual stack size to be used. */ diff --git a/sys/boot/ficl/softwords/classes.fr b/sys/boot/ficl/softwords/classes.fr index 75dc35a..9e578fb 100644 --- a/sys/boot/ficl/softwords/classes.fr +++ b/sys/boot/ficl/softwords/classes.fr @@ -2,6 +2,8 @@ \ ** F I C L 2 . 0 C L A S S E S \ john sadler 1 sep 98 \ Needs oop.fr +\ +\ $FreeBSD$ .( loading ficl utility classes ) cr also oop definitions @@ -68,6 +70,16 @@ object subclass c-ptr c-4byte => set ; + \ force the pointer to be null + : clr-ptr + 0 -rot c-ptr => .addr c-4byte => set + ; + + \ return flag indicating null-ness + : ?null ( inst class -- flag ) + c-ptr => get-ptr 0= + ; + \ increment the pointer in place : inc-ptr ( inst class -- ) 2dup 2dup ( i c i c i c ) diff --git a/sys/boot/ficl/softwords/jhlocal.fr b/sys/boot/ficl/softwords/jhlocal.fr index 034ada5..85d1fe3 100644 --- a/sys/boot/ficl/softwords/jhlocal.fr +++ b/sys/boot/ficl/softwords/jhlocal.fr @@ -9,6 +9,11 @@ \ locstate: 0 = looking for | or -- or }} \ 1 = found | \ 2 = found -- +\ 3 = found } +\ 4 = end of line +\ +\ $FreeBSD$ + hide 0 constant zero @@ -19,16 +24,18 @@ hide : ?| ( c-addr u -- c-addr u flag ) 2dup s" |" compare 0= ; +\ examine name and push true if it's a 2local +\ (starts with '2'), false otherwise. +: ?2loc ( c-addr u -- c-addr n flag ) + over c@ [char] 2 = if true else false endif ; + : ?delim ( c-addr u -- state | c-addr u 0 ) - ?| if - 2drop 1 - else - ?-- if - 2drop 2 - else - ?} if 2drop 3 else 0 endif - endif - endif + ?| if 2drop 1 exit endif + ?-- if 2drop 2 exit endif + ?} if 2drop 3 exit endif + dup 0= + if 2drop 4 exit endif + 0 ; set-current @@ -45,7 +52,9 @@ set-current repeat \ now unstack the locals - 0 do (local) loop \ ( ) + 0 do + ?2loc if (2local) else (local) endif + loop \ ( ) \ zero locals until -- or } locstate 1 = if @@ -53,7 +62,11 @@ set-current parse-word ?delim dup to locstate 0= while - postpone zero (local) + ?2loc if + postpone zero postpone zero (2local) + else + postpone zero (local) + endif repeat endif diff --git a/sys/boot/ficl/softwords/oo.fr b/sys/boot/ficl/softwords/oo.fr index cd16c77..65ddf33 100644 --- a/sys/boot/ficl/softwords/oo.fr +++ b/sys/boot/ficl/softwords/oo.fr @@ -1,6 +1,9 @@ \ ** ficl/softwords/oo.fr \ ** F I C L O - O E X T E N S I O N S \ ** john sadler aug 1998 +\ +\ $FreeBSD$ + .( loading ficl O-O extensions ) cr 7 ficl-vocabulary oop @@ -216,6 +219,10 @@ set-current previous \ instance of the class. This word gets compiled into \ the wordlist of every class by the SUB method. \ PRECONDITION: current-class contains the class address +\ why use a state variable instead of the stack? +\ >> Stack state is not well-defined during compilation (there are +\ >> control structure match codes on the stack, of undefined size +\ >> easiest way around this is use of this thread-local variable \ : do-do-instance ( -- ) s" : .do-instance does> [ current-class @ ] literal ;" @@ -232,7 +239,8 @@ set-current previous \ :noname wordlist - create immediate + create + immediate 0 , \ NULL parent class dup , \ wid 3 cells , \ instance size @@ -295,6 +303,24 @@ previous --> array-init ; +\ Create an anonymous initialized instance from the heap +: alloc \ ( class metaclass -- instance class ) + locals| meta class | + class meta metaclass => get-size allocate ( -- addr fail-flag ) + abort" allocate failed " ( -- addr ) + class 2dup --> init +; + +\ Create an anonymous array of initialized instances from the heap +: alloc-array \ ( n class metaclass -- instance class ) + locals| meta class nobj | + class meta metaclass => get-size + nobj * allocate ( -- addr fail-flag ) + abort" allocate failed " ( -- addr ) + nobj over class --> array-init + class +; + \ create a proxy object with initialized payload address given : ref ( instance-addr class metaclass "name" -- ) drop create , , @@ -412,6 +438,14 @@ do-do-instance loop ; +\ free storage allocated to a heap instance by alloc or alloc-array +\ NOTE: not protected against errors like FREEing something that's +\ really in the dictionary. +: free \ ( instance class -- ) + drop free + abort" free failed " +; + \ Instance aliases for common class methods \ Upcast to parent class : super ( instance class -- instance parent-class ) diff --git a/sys/boot/ficl/softwords/softcore.fr b/sys/boot/ficl/softwords/softcore.fr index bf584d0..b32ed3e 100644 --- a/sys/boot/ficl/softwords/softcore.fr +++ b/sys/boot/ficl/softwords/softcore.fr @@ -69,6 +69,8 @@ decimal 32 constant bl : local ( name -- ) bl word count (local) ; immediate +: 2local ( name -- ) bl word count (2local) ; immediate + : end-locals ( -- ) 0 0 (local) ; immediate \ #endif diff --git a/sys/boot/ficl/vm.c b/sys/boot/ficl/vm.c index bb6b1f8..0676cdb 100644 --- a/sys/boot/ficl/vm.c +++ b/sys/boot/ficl/vm.c @@ -118,6 +118,7 @@ void vmInnerLoop(FICL_VM *pVM) } #endif + /************************************************************************** v m G e t S t r i n g ** Parses a string out of the VM input buffer and copies up to the first @@ -128,7 +129,7 @@ void vmInnerLoop(FICL_VM *pVM) **************************************************************************/ char *vmGetString(FICL_VM *pVM, FICL_STRING *spDest, char delimiter) { - STRINGINFO si = vmParseString(pVM, delimiter); + STRINGINFO si = vmParseStringEx(pVM, delimiter, 0); if (SI_COUNT(si) > FICL_STRING_MAX) { @@ -229,14 +230,22 @@ int vmGetWordToPad(FICL_VM *pVM) ** trailing delimiter. **************************************************************************/ STRINGINFO vmParseString(FICL_VM *pVM, char delim) +{ + return vmParseStringEx(pVM, delim, 1); +} + +STRINGINFO vmParseStringEx(FICL_VM *pVM, char delim, char fSkipLeading) { STRINGINFO si; char *pSrc = vmGetInBuf(pVM); char *pEnd = vmGetInBufEnd(pVM); char ch; - while ((pSrc != pEnd) && (*pSrc == delim)) /* skip lead delimiters */ - pSrc++; + if (fSkipLeading) + { /* skip lead delimiters */ + while ((pSrc != pEnd) && (*pSrc == delim)) + pSrc++; + } SI_SETPTR(si, pSrc); /* mark start of text */ @@ -260,6 +269,27 @@ STRINGINFO vmParseString(FICL_VM *pVM, char delim) /************************************************************************** + v m P o p +** +**************************************************************************/ +CELL vmPop(FICL_VM *pVM) +{ + return stackPop(pVM->pStack); +} + + +/************************************************************************** + v m P u s h +** +**************************************************************************/ +void vmPush(FICL_VM *pVM, CELL c) +{ + stackPush(pVM->pStack, c); + return; +} + + +/************************************************************************** v m P o p I P ** **************************************************************************/ @@ -364,6 +394,18 @@ void vmSetTextOut(FICL_VM *pVM, OUTFUNC textOut) /************************************************************************** + v m S t e p +** Single step the vm - equivalent to "step into" - used for debugging +**************************************************************************/ +#if FICL_WANT_DEBUGGER +void vmStep(FICL_VM *pVM) +{ + M_VM_STEP(pVM); +} +#endif + + +/************************************************************************** v m T e x t O u t ** Feeds text to the vm's output callback **************************************************************************/ diff --git a/sys/boot/ficl/words.c b/sys/boot/ficl/words.c index 179157c..ab6700d 100644 --- a/sys/boot/ficl/words.c +++ b/sys/boot/ficl/words.c @@ -52,6 +52,7 @@ static FICL_WORD *pExitParen = NULL; static FICL_WORD *pIfParen = NULL; static FICL_WORD *pInterpret = NULL; static FICL_WORD *pLitParen = NULL; +static FICL_WORD *pTwoLitParen = NULL; static FICL_WORD *pLoopParen = NULL; static FICL_WORD *pPLoopParen = NULL; static FICL_WORD *pQDoParen = NULL; @@ -62,16 +63,24 @@ static FICL_WORD *pType = NULL; #if FICL_WANT_LOCALS static FICL_WORD *pGetLocalParen= NULL; +static FICL_WORD *pGet2LocalParen= NULL; static FICL_WORD *pGetLocal0 = NULL; static FICL_WORD *pGetLocal1 = NULL; static FICL_WORD *pToLocalParen = NULL; +static FICL_WORD *pTo2LocalParen = NULL; static FICL_WORD *pToLocal0 = NULL; static FICL_WORD *pToLocal1 = NULL; static FICL_WORD *pLinkParen = NULL; static FICL_WORD *pUnLinkParen = NULL; static int nLocals = 0; +static CELL *pMarkLocals = NULL; + +static void doLocalIm(FICL_VM *pVM); +static void do2LocalIm(FICL_VM *pVM); + #endif + /* ** C O N T R O L S T R U C T U R E B U I L D E R S ** @@ -223,6 +232,18 @@ static int isNumber(FICL_VM *pVM, STRINGINFO si) } +static void ficlIsNum(FICL_VM *pVM) +{ + STRINGINFO si; + FICL_INT ret; + + SI_SETLEN(si, stackPopINT(pVM->pStack)); + SI_SETPTR(si, stackPopPtr(pVM->pStack)); + ret = isNumber(pVM, si) ? FICL_TRUE : FICL_FALSE; + stackPushINT(pVM->pStack, ret); + return; +} + /************************************************************************** a d d & f r i e n d s ** @@ -915,7 +936,7 @@ static void commentLine(FICL_VM *pVM) */ static void commentHang(FICL_VM *pVM) { - vmParseString(pVM, ')'); + vmParseStringEx(pVM, ')', 0); return; } @@ -1068,11 +1089,7 @@ static void ifCoIm(FICL_VM *pVM) ** called (not?branch) since it does "branch if false". **************************************************************************/ -#ifdef FICL_TRACE -void ifParen(FICL_VM *pVM) -#else static void ifParen(FICL_VM *pVM) -#endif { FICL_UNS flag; @@ -1134,11 +1151,7 @@ static void elseCoIm(FICL_VM *pVM) ** compilation address, and branches to that location. **************************************************************************/ -#ifdef FICL_TRACE -void branchParen(FICL_VM *pVM) -#else static void branchParen(FICL_VM *pVM) -#endif { vmBranchRelative(pVM, *(int *)(pVM->ip)); return; @@ -1159,6 +1172,22 @@ static void endifCoIm(FICL_VM *pVM) /************************************************************************** + h a s h +** hash ( c-addr u -- code) +** calculates hashcode of specified string and leaves it on the stack +**************************************************************************/ + +static void hash(FICL_VM *pVM) +{ + STRINGINFO si; + SI_SETLEN(si, stackPopUNS(pVM->pStack)); + SI_SETPTR(si, stackPopPtr(pVM->pStack)); + stackPushUNS(pVM->pStack, hashHashCode(si)); + return; +} + + +/************************************************************************** i n t e r p r e t ** This is the "user interface" of a Forth. It does the following: ** while there are words in the VM's Text Input Buffer @@ -1188,10 +1217,13 @@ static void interpret(FICL_VM *pVM) ** Get next word...if out of text, we're done. */ if (si.count == 0) + { vmThrow(pVM, VM_OUTOFTEXT); + } interpWord(pVM, si); + return; /* back to inner interpreter */ } @@ -1239,6 +1271,7 @@ static void interpWord(FICL_VM *pVM, STRINGINFO si) { vmThrowErr(pVM, "Error: Compile only!"); } + vmExecute(pVM, tempFW); } @@ -1285,11 +1318,8 @@ static void interpWord(FICL_VM *pVM, STRINGINFO si) ** parameter stack at runtime. This code is compiled by "literal". ** **************************************************************************/ -#ifdef FICL_TRACE -void literalParen(FICL_VM *pVM) -#else + static void literalParen(FICL_VM *pVM) -#endif { #if FICL_ROBUST > 1 vmCheckStack(pVM, 0, 1); @@ -1299,6 +1329,17 @@ static void literalParen(FICL_VM *pVM) return; } +static void twoLitParen(FICL_VM *pVM) +{ +#if FICL_ROBUST > 1 + vmCheckStack(pVM, 0, 2); +#endif + stackPushINT(pVM->pStack, *((FICL_INT *)(pVM->ip)+1)); + stackPushINT(pVM->pStack, *(FICL_INT *)(pVM->ip)); + vmBranchRelative(pVM, 2); + return; +} + /************************************************************************** l i t e r a l I m @@ -1320,6 +1361,18 @@ static void literalIm(FICL_VM *pVM) } +static void twoLiteralIm(FICL_VM *pVM) +{ + FICL_DICT *dp = ficlGetDict(); + assert(pTwoLitParen); + + dictAppendCell(dp, LVALUEtoCELL(pTwoLitParen)); + dictAppendCell(dp, stackPop(pVM->pStack)); + dictAppendCell(dp, stackPop(pVM->pStack)); + + return; +} + /************************************************************************** l i s t W o r d s ** @@ -1602,11 +1655,8 @@ static void doCoIm(FICL_VM *pVM) return; } -#ifdef FICL_TRACE -void doParen(FICL_VM *pVM) -#else + static void doParen(FICL_VM *pVM) -#endif { CELL index, limit; #if FICL_ROBUST > 1 @@ -1645,11 +1695,8 @@ static void qDoCoIm(FICL_VM *pVM) return; } -#ifdef FICL_TRACE -void qDoParen(FICL_VM *pVM) -#else + static void qDoParen(FICL_VM *pVM) -#endif { CELL index, limit; #if FICL_ROBUST > 1 @@ -1722,11 +1769,8 @@ static void plusLoopCoIm(FICL_VM *pVM) return; } -#ifdef FICL_TRACE -void loopParen(FICL_VM *pVM) -#else + static void loopParen(FICL_VM *pVM) -#endif { FICL_INT index = stackGetTop(pVM->rStack).i; FICL_INT limit = stackFetch(pVM->rStack, 1).i; @@ -1747,11 +1791,8 @@ static void loopParen(FICL_VM *pVM) return; } -#ifdef FICL_TRACE -void plusLoopParen(FICL_VM *pVM) -#else + static void plusLoopParen(FICL_VM *pVM) -#endif { FICL_INT index = stackGetTop(pVM->rStack).i; FICL_INT limit = stackFetch(pVM->rStack, 1).i; @@ -2057,11 +2098,8 @@ static void compileOnly(FICL_VM *pVM) ** and count on the stack. Finally, update ip to point to the first ** aligned address after the string text. **************************************************************************/ -#ifdef FICL_TRACE -void stringLit(FICL_VM *pVM) -#else + static void stringLit(FICL_VM *pVM) -#endif { FICL_STRING *sp = (FICL_STRING *)(pVM->ip); FICL_COUNT count = sp->count; @@ -2092,8 +2130,6 @@ static void dotParen(FICL_VM *pVM) char *pDest = pVM->pad; char ch; - pSrc = skipSpace(pSrc, pEnd); - for (ch = *pSrc; (pEnd != pSrc) && (ch != ')'); ch = *++pSrc) *pDest++ = ch; @@ -2597,6 +2633,19 @@ static void repeatCoIm(FICL_VM *pVM) } +static void againCoIm(FICL_VM *pVM) +{ + FICL_DICT *dp = ficlGetDict(); + + assert(pBranchParen); + dictAppendCell(dp, LVALUEtoCELL(pBranchParen)); + + /* expect "begin" branch marker */ + resolveBackBranch(dp, pVM, destTag); + return; +} + + /************************************************************************** c h a r & f r i e n d s ** 6.1.0895 CHAR CORE ( "<spaces>name" -- char ) @@ -2723,7 +2772,7 @@ static void environmentQ(FICL_VM *pVM) ** EVALUATE CORE ( i*x c-addr u -- j*x ) ** Save the current input source specification. Store minus-one (-1) in ** SOURCE-ID if it is present. Make the string described by c-addr and u -** both the input source andinput buffer, set >IN to zero, and interpret. +** both the input source and input buffer, set >IN to zero, and interpret. ** When the parse area is empty, restore the prior input source ** specification. Other stack effects are due to the words EVALUATEd. ** @@ -2775,6 +2824,7 @@ static void stringQuoteIm(FICL_VM *pVM) return; } + /************************************************************************** t y p e ** Pop count and char address from stack and print the designated string. @@ -2822,7 +2872,7 @@ static void ficlWord(FICL_VM *pVM) char delim = (char)stackPopINT(pVM->pStack); STRINGINFO si; - si = vmParseString(pVM, delim); + si = vmParseStringEx(pVM, delim, 1); if (SI_COUNT(si) > nPAD-1) SI_SETLEN(si, nPAD-1); @@ -2863,27 +2913,12 @@ static void parseNoCopy(FICL_VM *pVM) **************************************************************************/ static void parse(FICL_VM *pVM) { - char *pSrc = vmGetInBuf(pVM); - char *pEnd = vmGetInBufEnd(pVM); - char *cp; - FICL_UNS count; - char delim = (char)stackPopINT(pVM->pStack); - - cp = pSrc; /* mark start of text */ - - while ((pSrc != pEnd) && (*pSrc != delim)) - { - pSrc++; /* find next delimiter or end */ - } - - count = pSrc - cp; /* set length of result */ - - if ((pSrc != pEnd) && (*pSrc == delim)) /* gobble trailing delimiter */ - pSrc++; + STRINGINFO si; + char delim = (char)stackPopINT(pVM->pStack); - vmUpdateTib(pVM, pSrc); - stackPushPtr(pVM->pStack, cp); - stackPushUNS(pVM->pStack, count); + si = vmParseStringEx(pVM, delim, 0); + stackPushPtr(pVM->pStack, SI_PTR(si)); + stackPushUNS(pVM->pStack, SI_COUNT(si)); return; } @@ -2942,6 +2977,7 @@ static void find(FICL_VM *pVM) } + /************************************************************************** f m S l a s h M o d ** f-m-slash-mod CORE ( d1 n1 -- n2 n3 ) @@ -3189,8 +3225,7 @@ static void sToD(FICL_VM *pVM) ** input buffer. **************************************************************************/ static void source(FICL_VM *pVM) -{ int i; - +{ stackPushPtr(pVM->pStack, pVM->tib.cp); stackPushINT(pVM->pStack, vmGetInBufLen(pVM)); return; @@ -3555,16 +3590,22 @@ static void toValue(FICL_VM *pVM) FICL_WORD *pFW; #if FICL_WANT_LOCALS - FICL_DICT *pLoc = ficlGetLoc(); if ((nLocals > 0) && (pVM->state == COMPILE)) { + FICL_DICT *pLoc = ficlGetLoc(); pFW = dictLookup(pLoc, si); - if (pFW) + if (pFW && (pFW->code == doLocalIm)) { dictAppendCell(dp, LVALUEtoCELL(pToLocalParen)); dictAppendCell(dp, LVALUEtoCELL(pFW->param[0])); return; } + else if (pFW && pFW->code == do2LocalIm) + { + dictAppendCell(dp, LVALUEtoCELL(pTo2LocalParen)); + dictAppendCell(dp, LVALUEtoCELL(pFW->param[0])); + return; + } } #endif @@ -3726,14 +3767,13 @@ static void doLocalIm(FICL_VM *pVM) **************************************************************************/ static void localParen(FICL_VM *pVM) { - static CELL *pMark = NULL; FICL_DICT *pDict = ficlGetDict(); STRINGINFO si; SI_SETLEN(si, stackPopUNS(pVM->pStack)); SI_SETPTR(si, (char *)stackPopPtr(pVM->pStack)); if (SI_COUNT(si) > 0) - { /* add a local to the dict and update nLocals */ + { /* add a local to the **locals** dict and update nLocals */ FICL_DICT *pLoc = ficlGetLoc(); if (nLocals >= FICL_MAX_LOCALS) { @@ -3747,7 +3787,7 @@ static void localParen(FICL_VM *pVM) { /* compile code to create a local stack frame */ dictAppendCell(pDict, LVALUEtoCELL(pLinkParen)); /* save location in dictionary for #locals */ - pMark = pDict->here; + pMarkLocals = pDict->here; dictAppendCell(pDict, LVALUEtoCELL(nLocals)); /* compile code to initialize first local */ dictAppendCell(pDict, LVALUEtoCELL(pToLocal0)); @@ -3766,7 +3806,84 @@ static void localParen(FICL_VM *pVM) } else if (nLocals > 0) { /* write nLocals to (link) param area in dictionary */ - *(FICL_INT *)pMark = nLocals; + *(FICL_INT *)pMarkLocals = nLocals; + } + + return; +} + + +static void get2LocalParen(FICL_VM *pVM) +{ + FICL_INT nLocal = *(FICL_INT *)(pVM->ip++); + stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]); + stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal+1]); + return; +} + + +static void do2LocalIm(FICL_VM *pVM) +{ + FICL_DICT *pDict = ficlGetDict(); + int nLocal = pVM->runningWord->param[0].i; + + if (pVM->state == INTERPRET) + { + stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]); + stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal+1]); + } + else + { + dictAppendCell(pDict, LVALUEtoCELL(pGet2LocalParen)); + dictAppendCell(pDict, LVALUEtoCELL(nLocal)); + } + return; +} + + +static void to2LocalParen(FICL_VM *pVM) +{ + FICL_INT nLocal = *(FICL_INT *)(pVM->ip++); + pVM->rStack->pFrame[nLocal+1] = stackPop(pVM->pStack); + pVM->rStack->pFrame[nLocal] = stackPop(pVM->pStack); + return; +} + + +static void twoLocalParen(FICL_VM *pVM) +{ + FICL_DICT *pDict = ficlGetDict(); + STRINGINFO si; + SI_SETLEN(si, stackPopUNS(pVM->pStack)); + SI_SETPTR(si, (char *)stackPopPtr(pVM->pStack)); + + if (SI_COUNT(si) > 0) + { /* add a local to the **locals** dict and update nLocals */ + FICL_DICT *pLoc = ficlGetLoc(); + if (nLocals >= FICL_MAX_LOCALS) + { + vmThrowErr(pVM, "Error: out of local space"); + } + + dictAppendWord2(pLoc, si, do2LocalIm, FW_COMPIMMED); + dictAppendCell(pLoc, LVALUEtoCELL(nLocals)); + + if (nLocals == 0) + { /* compile code to create a local stack frame */ + dictAppendCell(pDict, LVALUEtoCELL(pLinkParen)); + /* save location in dictionary for #locals */ + pMarkLocals = pDict->here; + dictAppendCell(pDict, LVALUEtoCELL(nLocals)); + } + + dictAppendCell(pDict, LVALUEtoCELL(pTo2LocalParen)); + dictAppendCell(pDict, LVALUEtoCELL(nLocals)); + + nLocals += 2; + } + else if (nLocals > 0) + { /* write nLocals to (link) param area in dictionary */ + *(FICL_INT *)pMarkLocals = nLocals; } return; @@ -3813,11 +3930,7 @@ static void setParentWid(FICL_VM *pVM) ** like it's in the dictionary address range. ** NOTE: this excludes :noname words! */ -#ifdef FICL_TRACE -int isAFiclWord(FICL_WORD *pFW) -#else static int isAFiclWord(FICL_WORD *pFW) -#endif { FICL_DICT *pd = ficlGetDict(); @@ -4262,20 +4375,27 @@ static void fkey(FICL_VM *pVM) ** ** More comments can be found throughout catch's code. ** -** BUGS: do not handle locals unnesting correctly... I think... -** ** Daniel C. Sobral Jan 09/1999 +** sadler may 2000 -- revised to follow ficl.c:ficlExecXT. **************************************************************************/ static void ficlCatch(FICL_VM *pVM) { - int except; + static FICL_WORD *pQuit = NULL; + + int except; jmp_buf vmState; FICL_VM VM; FICL_STACK pStack; FICL_STACK rStack; FICL_WORD *pFW; - IPTYPE exitIP; + + if (!pQuit) + pQuit = ficlLookup("exit-inner"); + + assert(pVM); + assert(pQuit); + /* ** Get xt. @@ -4313,63 +4433,42 @@ static void ficlCatch(FICL_VM *pVM) */ except = setjmp(vmState); - /* - ** And now, choose what to do depending on except. - */ - - /* Things having gone wrong... */ - if(except) - { + switch (except) + { + /* + ** Setup condition - push poison pill so that the VM throws + ** VM_INNEREXIT if the XT terminates normally, then execute + ** the XT + */ + case 0: + vmPushIP(pVM, &pQuit); /* Open mouth, insert emetic */ + vmExecute(pVM, pFW); + vmInnerLoop(pVM); + break; + + /* + ** Normal exit from XT - lose the poison pill, + ** restore old setjmp vector and push a zero. + */ + case VM_INNEREXIT: + vmPopIP(pVM); /* Gack - hurl poison pill */ + pVM->pState = VM.pState; /* Restore just the setjmp vector */ + stackPushINT(pVM->pStack, 0); /* Push 0 -- everything is ok */ + break; + + /* + ** Some other exception got thrown - restore pre-existing VM state + ** and push the exception code + */ + default: /* Restore vm's state */ memcpy((void*)pVM, (void*)&VM, sizeof(FICL_VM)); memcpy((void*)pVM->pStack, (void*)&pStack, sizeof(FICL_STACK)); memcpy((void*)pVM->rStack, (void*)&rStack, sizeof(FICL_STACK)); - /* Push error */ - stackPushINT(pVM->pStack, except); - - } - else /* Things being ok... */ - { - /* - * We need to know when to exit the inner loop - * Colonp, the "code" for colon words, just pushes - * the word's IP onto the RP, and expect the inner - * interpreter to do the rest. Well, I'd rather have - * it done *before* I return from this function, - * losing the automatic variables I'm using to save - * state. Sure, I could save this on dynamic memory - * and save state on RP, or I could even implement - * the poor man's version of this word in Forth with - * sp@, sp!, rp@ and rp!, but we have a lot of state - * neatly tucked away in pVM, so why not save it? - */ - exitIP = pVM->ip; - - /* Execute the xt -- inline code for vmExecute */ - - pVM->runningWord = pFW; - pFW->code(pVM); - - /* - ** Run the inner loop until we get back to exitIP - */ - for (; pVM->ip != exitIP;) - { - pFW = *pVM->ip++; - - /* Inline code for vmExecute */ - pVM->runningWord = pFW; - pFW->code(pVM); - } - - - /* Restore just the setjmp vector */ - pVM->pState = VM.pState; - - /* Push 0 -- everything is ok */ - stackPushINT(pVM->pStack, 0); - } + stackPushINT(pVM->pStack, except);/* Push error */ + break; + } } /* @@ -4393,8 +4492,6 @@ static void ficlThrow(FICL_VM *pVM) } -/*************** freebsd added memory-alloc handling words ******************/ - static void ansAllocate(FICL_VM *pVM) { size_t size; @@ -4652,6 +4749,7 @@ void ficlCompileCore(FICL_DICT *dp) dictAppendWord(dp, ".(", dotParen, FW_DEFAULT); dictAppendWord(dp, ":noname", colonNoName, FW_DEFAULT); dictAppendWord(dp, "?do", qDoCoIm, FW_COMPIMMED); + dictAppendWord(dp, "again", againCoIm, FW_COMPIMMED); dictAppendWord(dp, "parse", parse, FW_DEFAULT); dictAppendWord(dp, "pick", pick, FW_DEFAULT); dictAppendWord(dp, "roll", roll, FW_DEFAULT); @@ -4711,6 +4809,14 @@ void ficlCompileCore(FICL_DICT *dp) ficlSetEnv("stack-cells", FICL_DEFAULT_STACK); /* + ** DOUBLE word set (partial) + */ + dictAppendWord(dp, "2constant", twoConstant, FW_IMMEDIATE); + dictAppendWord(dp, "2literal", twoLiteralIm, FW_IMMEDIATE); + dictAppendWord(dp, "dnegate", dnegate, FW_DEFAULT); + + + /* ** EXCEPTION word set */ dictAppendWord(dp, "catch", ficlCatch, FW_DEFAULT); @@ -4743,6 +4849,12 @@ void ficlCompileCore(FICL_DICT *dp) dictAppendWord(dp, "(toLocal1)",toLocal1, FW_COMPILE); dictAppendWord(dp, "(local)", localParen, FW_COMPILE); + pGet2LocalParen = + dictAppendWord(dp, "(@2local)", get2LocalParen, FW_COMPILE); + pTo2LocalParen = + dictAppendWord(dp, "(to2Local)",to2LocalParen, FW_COMPILE); + dictAppendWord(dp, "(2local)", twoLocalParen, FW_COMPILE); + ficlSetEnv("locals", FICL_TRUE); ficlSetEnv("locals-ext", FICL_TRUE); ficlSetEnv("#locals", FICL_MAX_LOCALS); @@ -4806,15 +4918,15 @@ void ficlCompileCore(FICL_DICT *dp) dictAppendWord(dp, ".env", listEnv, FW_DEFAULT); dictAppendWord(dp, ".ver", ficlVersion, FW_DEFAULT); dictAppendWord(dp, "-roll", minusRoll, FW_DEFAULT); - dictAppendWord(dp, "2constant", twoConstant, FW_IMMEDIATE); /* DOUBLE */ dictAppendWord(dp, ">name", toName, FW_DEFAULT); dictAppendWord(dp, "body>", fromBody, FW_DEFAULT); dictAppendWord(dp, "compare", compareString, FW_DEFAULT); /* STRING */ dictAppendWord(dp, "compile-only", compileOnly, FW_DEFAULT); - dictAppendWord(dp, "dnegate", dnegate, FW_DEFAULT); /* DOUBLE */ dictAppendWord(dp, "endif", endifCoIm, FW_COMPIMMED); dictAppendWord(dp, "forget-wid",forgetWid, FW_DEFAULT); + dictAppendWord(dp, "hash", hash, FW_DEFAULT); + dictAppendWord(dp, "number?", ficlIsNum, FW_DEFAULT); dictAppendWord(dp, "parse-word",parseNoCopy, FW_DEFAULT); dictAppendWord(dp, "sliteral", sLiteralCoIm, FW_COMPIMMED); /* STRING */ dictAppendWord(dp, "wid-set-super", @@ -4835,6 +4947,8 @@ void ficlCompileCore(FICL_DICT *dp) dictAppendWord(dp, "(;)", semiParen, FW_COMPILE); pLitParen = dictAppendWord(dp, "(literal)", literalParen, FW_COMPILE); + pTwoLitParen = + dictAppendWord(dp, "(2literal)",twoLitParen, FW_COMPILE); pStringLit = dictAppendWord(dp, "(.\")", stringLit, FW_COMPILE); pIfParen = |