summaryrefslogtreecommitdiffstats
path: root/sys/boot/ficl/ficl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/boot/ficl/ficl.c')
-rw-r--r--sys/boot/ficl/ficl.c233
1 files changed, 123 insertions, 110 deletions
diff --git a/sys/boot/ficl/ficl.c b/sys/boot/ficl/ficl.c
index 9274c1b..ad776be 100644
--- a/sys/boot/ficl/ficl.c
+++ b/sys/boot/ficl/ficl.c
@@ -21,6 +21,8 @@
** Code is written in ANSI C for portability.
*/
+/* $FreeBSD$ */
+
#ifdef TESTMAIN
#include <stdlib.h>
#else
@@ -174,20 +176,30 @@ int ficlBuild(char *name, FICL_CODE code, char flags)
** time to delete the vm, etc -- or you can ignore this
** signal.
**************************************************************************/
-int ficlExec(FICL_VM *pVM, char *pText, INT32 size)
+int ficlExec(FICL_VM *pVM, char *pText)
{
-#ifdef FICL_TRACE
- extern int isAFiclWord(FICL_WORD *pFW);
-#endif
+ return ficlExecC(pVM, pText, -1);
+}
+
+int ficlExecC(FICL_VM *pVM, char *pText, FICL_INT size)
+{
+ static FICL_WORD *pInterp = NULL;
+
int except;
- FICL_WORD *tempFW;
jmp_buf vmState;
TIB saveTib;
FICL_VM VM;
FICL_STACK rStack;
+ if (!pInterp)
+ pInterp = ficlLookup("interpret");
+
+ assert(pInterp);
assert(pVM);
+ if (size < 0)
+ size = strlen(pText);
+
vmPushTib(pVM, pText, size, &saveTib);
/*
@@ -207,106 +219,12 @@ int ficlExec(FICL_VM *pVM, char *pText, INT32 size)
pVM->fRestart = 0;
pVM->runningWord->code(pVM);
}
-
- /*
- ** the mysterious inner interpreter...
- ** vmThrow gets you out of this loop with a longjmp()
- */
- for (;;)
- {
-#ifdef FICL_TRACE
- CELL c;
- char buffer[40];
-#endif
- tempFW = *pVM->ip++;
-#ifdef FICL_TRACE
- if (ficl_trace && isAFiclWord(tempFW))
- {
- extern void literalParen(FICL_VM*);
- extern void stringLit(FICL_VM*);
- extern void ifParen(FICL_VM*);
- extern void branchParen(FICL_VM*);
- extern void qDoParen(FICL_VM*);
- extern void doParen(FICL_VM*);
- extern void loopParen(FICL_VM*);
- extern void plusLoopParen(FICL_VM*);
-
- if (tempFW->code == literalParen)
- {
- c = *PTRtoCELL(pVM->ip);
- if (isAFiclWord(c.p))
- {
- FICL_WORD *pLit = (FICL_WORD *)c.p;
- sprintf(buffer, " literal %.*s (%#lx)",
- pLit->nName, pLit->name, c.u);
- }
- else
- sprintf(buffer, " literal %ld (%#lx)", c.i, c.u);
- }
- else if (tempFW->code == stringLit)
- {
- FICL_STRING *sp = PTRtoSTRING(pVM->ip);
- sprintf(buffer, " s\" %.*s\"", sp->count, sp->text);
- }
- else if (tempFW->code == ifParen)
- {
- c = *PTRtoCELL(pVM->ip);
- if (c.i > 0)
- sprintf(buffer, " if / while (branch rel %ld)", c.i);
- else
- sprintf(buffer, " until (branch rel %ld)", c.i);
- }
- else if (tempFW->code == branchParen)
- {
- c = *PTRtoCELL(pVM->ip);
- if (c.i > 0)
- sprintf(buffer, " else (branch rel %ld)", c.i);
- else
- sprintf(buffer, " repeat (branch rel %ld)", c.i);
- }
- else if (tempFW->code == qDoParen)
- {
- c = *PTRtoCELL(pVM->ip);
- sprintf(buffer, " ?do (leave abs %#lx)", c.u);
- }
- else if (tempFW->code == doParen)
- {
- c = *PTRtoCELL(pVM->ip);
- sprintf(buffer, " do (leave abs %#lx)", c.u);
- }
- else if (tempFW->code == loopParen)
- {
- c = *PTRtoCELL(pVM->ip);
- sprintf(buffer, " loop (branch rel %ld)", c.i);
- }
- else if (tempFW->code == plusLoopParen)
- {
- c = *PTRtoCELL(pVM->ip);
- sprintf(buffer, " +loop (branch rel %ld)", c.i);
- }
- else /* default: print word's name */
- {
- sprintf(buffer, " %.*s", tempFW->nName, tempFW->name);
- }
-
- vmTextOut(pVM, buffer, 1);
- }
- else if (ficl_trace) /* probably not a word
- * - punt and print value
- */
- {
- sprintf(buffer, " %ld (%#lx)", (PTRtoCELL(pVM->ip))->i, (PTRtoCELL(pVM->ip))->u);
- vmTextOut(pVM, buffer, 1);
- }
-#endif FICL_TRACE
- /*
- ** inline code for
- ** vmExecute(pVM, tempFW);
- */
- pVM->runningWord = tempFW;
- tempFW->code(pVM);
+ else
+ { /* set VM up to interpret text */
+ vmPushIP(pVM, &pInterp);
}
+ vmInnerLoop(pVM);
break;
case VM_RESTART:
@@ -315,6 +233,7 @@ int ficlExec(FICL_VM *pVM, char *pText, INT32 size)
break;
case VM_OUTOFTEXT:
+ vmPopIP(pVM);
#ifdef TESTMAIN
if ((pVM->state != COMPILE) && (pVM->sourceID.i == 0))
ficlTextOut(pVM, FICL_PROMPT, 0);
@@ -322,14 +241,18 @@ int ficlExec(FICL_VM *pVM, char *pText, INT32 size)
break;
case VM_USEREXIT:
+ case VM_INNEREXIT:
break;
case VM_QUIT:
if (pVM->state == COMPILE)
+ {
dictAbortDefinition(dp);
-
- memcpy((void*)pVM, (void*)&VM, sizeof(FICL_VM));
- memcpy((void*)pVM->rStack, (void*)&rStack, sizeof(FICL_STACK));
+#if FICL_WANT_LOCALS
+ dictEmpty(localp, localp->pForthWords->size);
+#endif
+ }
+ vmQuit(pVM);
break;
case VM_ERREXIT:
@@ -386,7 +309,7 @@ int ficlExecFD(FICL_VM *pVM, int fd)
break;
continue;
}
- rval = ficlExec(pVM, cp, i);
+ rval = ficlExecC(pVM, cp, i);
if(rval != VM_QUIT && rval != VM_USEREXIT && rval != VM_OUTOFTEXT)
{
pVM->sourceID = id;
@@ -398,13 +321,86 @@ int ficlExecFD(FICL_VM *pVM, int fd)
** any pending REFILLs (as required by FILE wordset)
*/
pVM->sourceID.i = -1;
- ficlExec(pVM, "", 0);
+ ficlExec(pVM, "");
pVM->sourceID = id;
return rval;
}
/**************************************************************************
+ f i c l E x e c X T
+** Given a pointer to a FICL_WORD, push an inner interpreter and
+** execute the word to completion. This is in contrast with vmExecute,
+** which does not guarantee that the word will have completed when
+** the function returns (ie in the case of colon definitions, which
+** need an inner interpreter to finish)
+**
+** Returns one of the VM_XXXX exception codes listed in ficl.h. Normal
+** exit condition is VM_INNEREXIT, ficl's private signal to exit the
+** inner loop under normal circumstances. If another code is thrown to
+** exit the loop, this function will re-throw it if it's nested under
+** itself or ficlExec.
+**
+** NOTE: this function is intended so that C code can execute ficlWords
+** given their address in the dictionary (xt).
+**************************************************************************/
+int ficlExecXT(FICL_VM *pVM, FICL_WORD *pWord)
+{
+ static FICL_WORD *pQuit = NULL;
+ int except;
+ jmp_buf vmState;
+ jmp_buf *oldState;
+
+ if (!pQuit)
+ pQuit = ficlLookup("exit-inner");
+
+ assert(pVM);
+ assert(pQuit);
+
+ /*
+ ** Save and restore VM's jmp_buf to enable nested calls
+ */
+ oldState = pVM->pState;
+ pVM->pState = &vmState; /* This has to come before the setjmp! */
+ except = setjmp(vmState);
+
+ if (except)
+ vmPopIP(pVM);
+ else
+ vmPushIP(pVM, &pQuit);
+
+ switch (except)
+ {
+ case 0:
+ vmExecute(pVM, pWord);
+ vmInnerLoop(pVM);
+ break;
+
+ case VM_INNEREXIT:
+ break;
+
+ case VM_RESTART:
+ case VM_OUTOFTEXT:
+ case VM_USEREXIT:
+ case VM_QUIT:
+ case VM_ERREXIT:
+ case VM_ABORT:
+ case VM_ABORTQ:
+ default: /* user defined exit code?? */
+ if (oldState)
+ {
+ pVM->pState = oldState;
+ vmThrow(pVM, except);
+ }
+ break;
+ }
+
+ pVM->pState = oldState;
+ return (except);
+}
+
+
+/**************************************************************************
f i c l L o o k u p
** Look in the system dictionary for a match to the given name. If
** found, return the address of the corresponding FICL_WORD. Otherwise
@@ -443,7 +439,7 @@ FICL_DICT *ficlGetEnv(void)
** Create an environment variable with a one-CELL payload. ficlSetEnvD
** makes one with a two-CELL payload.
**************************************************************************/
-void ficlSetEnv(char *name, UNS32 value)
+void ficlSetEnv(char *name, FICL_UNS value)
{
STRINGINFO si;
FICL_WORD *pFW;
@@ -464,7 +460,7 @@ void ficlSetEnv(char *name, UNS32 value)
return;
}
-void ficlSetEnvD(char *name, UNS32 hi, UNS32 lo)
+void ficlSetEnvD(char *name, FICL_UNS hi, FICL_UNS lo)
{
FICL_WORD *pFW;
STRINGINFO si;
@@ -500,6 +496,23 @@ FICL_DICT *ficlGetLoc(void)
#endif
+
+/**************************************************************************
+ f i c l S e t S t a c k S i z e
+** Set the stack sizes (return and parameter) to be used for all
+** subsequently created VMs. Returns actual stack size to be used.
+**************************************************************************/
+int ficlSetStackSize(int nStackCells)
+{
+ if (nStackCells >= FICL_DEFAULT_STACK)
+ defaultStack = nStackCells;
+ else
+ defaultStack = FICL_DEFAULT_STACK;
+
+ return defaultStack;
+}
+
+
/**************************************************************************
f i c l T e r m S y s t e m
** Tear the system down by deleting the dictionaries and all VMs.
OpenPOWER on IntegriCloud