summaryrefslogtreecommitdiff
path: root/tools.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools.c')
-rw-r--r--tools.c965
1 files changed, 499 insertions, 466 deletions
diff --git a/tools.c b/tools.c
index ad734e4b8834..3fd65bb89d2a 100644
--- a/tools.c
+++ b/tools.c
@@ -3,7 +3,7 @@
** Forth Inspired Command Language - programming tools
** Author: John Sadler (john_sadler@alum.mit.edu)
** Created: 20 June 2000
-** $Id: tools.c,v 1.11 2001-12-04 17:58:14-08 jsadler Exp jsadler $
+** $Id: tools.c,v 1.12 2010/08/12 13:57:22 asau Exp $
*******************************************************************/
/*
** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
@@ -11,9 +11,9 @@
**
** Get the latest Ficl release at http://ficl.sourceforge.net
**
-** I am interested in hearing from anyone who uses ficl. If you have
+** I am interested in hearing from anyone who uses Ficl. If you have
** a problem, a success story, a defect, an enhancement request, or
-** if you would like to contribute to the ficl release, please
+** if you would like to contribute to the Ficl release, please
** contact me by email at the address above.
**
** L I C E N S E and D I S C L A I M E R
@@ -46,7 +46,7 @@
** are the CFAs of colon definitions, constants, variables, DOES>
** words, and so on. It gets this information from a table and supporting
** functions in words.c.
-** colonParen doDoes createParen variableParen userParen constantParen
+** fiColonParen fiDoDoes createParen fiVariableParen fiUserParen fiConstantParen
**
** Step and break debugger for Ficl
** debug ( xt -- ) Start debugging an xt
@@ -61,14 +61,33 @@
#include "ficl.h"
-#if 0
-/*
-** nBREAKPOINTS sizes the breakpoint array. One breakpoint (bp 0) is reserved
-** for the STEP command. The rest are user programmable.
-*/
-#define nBREAKPOINTS 32
+static void ficlPrimitiveStepIn(ficlVm *vm);
+static void ficlPrimitiveStepOver(ficlVm *vm);
+static void ficlPrimitiveStepBreak(ficlVm *vm);
+
+
+
+void ficlCallbackAssert(ficlCallback *callback, int expression, char *expressionString, char *filename, int line)
+#if FICL_ROBUST >= 1
+{
+ if (!expression)
+ {
+ static char buffer[256];
+ sprintf(buffer, "ASSERTION FAILED at %s:%d: \"%s\"\n", filename, line, expressionString);
+ ficlCallbackTextOut(callback, buffer);
+ exit(-1);
+ }
+}
+#else /* FICL_ROBUST >= 1 */
+{
+ FICL_IGNORE(callback);
+ FICL_IGNORE(expression);
+ FICL_IGNORE(expressionString);
+ FICL_IGNORE(filename);
+ FICL_IGNORE(line);
+}
+#endif /* FICL_ROBUST >= 1 */
-#endif
/**************************************************************************
@@ -76,213 +95,112 @@
** Set a breakpoint at the current value of IP by
** storing that address in a BREAKPOINT record
**************************************************************************/
-static void vmSetBreak(FICL_VM *pVM, FICL_BREAKPOINT *pBP)
+static void ficlVmSetBreak(ficlVm *vm, ficlBreakpoint *pBP)
{
- FICL_WORD *pStep = ficlLookup(pVM->pSys, "step-break");
- assert(pStep);
+ ficlWord *pStep = ficlSystemLookup(vm->callback.system, "step-break");
+ FICL_VM_ASSERT(vm, pStep);
- pBP->address = pVM->ip;
- pBP->origXT = *pVM->ip;
- *pVM->ip = pStep;
+ pBP->address = vm->ip;
+ pBP->oldXT = *vm->ip;
+ *vm->ip = pStep;
}
/**************************************************************************
** d e b u g P r o m p t
**************************************************************************/
-static void debugPrompt(FICL_VM *pVM)
+static void ficlDebugPrompt(ficlVm *vm)
{
- vmTextOut(pVM, "dbg> ", 0);
-}
-
-
-/**************************************************************************
-** i s A F i c l W o r d
-** Vet a candidate pointer carefully to make sure
-** it's not some chunk o' inline data...
-** It has to have a name, and it has to look
-** like it's in the dictionary address range.
-** NOTE: this excludes :noname words!
-**************************************************************************/
-int isAFiclWord(FICL_DICT *pd, FICL_WORD *pFW)
-{
-
- if (!dictIncludes(pd, pFW))
- return 0;
-
- if (!dictIncludes(pd, pFW->name))
- return 0;
-
- if ((pFW->link != NULL) && !dictIncludes(pd, pFW->link))
- return 0;
-
- if ((pFW->nName <= 0) || (pFW->name[pFW->nName] != '\0'))
- return 0;
-
- if (strlen(pFW->name) != pFW->nName)
- return 0;
-
- return 1;
+ ficlVmTextOut(vm, "dbg> ");
}
#if 0
-static int isPrimitive(FICL_WORD *pFW)
+static int isPrimitive(ficlWord *word)
{
- WORDKIND wk = ficlWordClassify(pFW);
+ ficlWordKind wk = ficlWordClassify(word);
return ((wk != COLON) && (wk != DOES));
}
#endif
/**************************************************************************
- f i n d E n c l o s i n g W o r d
-** Given a pointer to something, check to make sure it's an address in the
-** dictionary. If so, search backwards until we find something that looks
-** like a dictionary header. If successful, return the address of the
-** FICL_WORD found. Otherwise return NULL.
-** nSEARCH_CELLS sets the maximum neighborhood this func will search before giving up
+ d i c t H a s h S u m m a r y
+** Calculate a figure of merit for the dictionary hash table based
+** on the average search depth for all the words in the dictionary,
+** assuming uniform distribution of target keys. The figure of merit
+** is the ratio of the total search depth for all keys in the table
+** versus a theoretical optimum that would be achieved if the keys
+** were distributed into the table as evenly as possible.
+** The figure would be worse if the hash table used an open
+** addressing scheme (i.e. collisions resolved by searching the
+** table for an empty slot) for a given size table.
**************************************************************************/
-#define nSEARCH_CELLS 100
-
-static FICL_WORD *findEnclosingWord(FICL_VM *pVM, CELL *cp)
+#if FICL_WANT_FLOAT
+void ficlPrimitiveHashSummary(ficlVm *vm)
{
- FICL_WORD *pFW;
- FICL_DICT *pd = vmGetDict(pVM);
- int i;
-
- if (!dictIncludes(pd, (void *)cp))
- return NULL;
-
- for (i = nSEARCH_CELLS; i > 0; --i, --cp)
- {
- pFW = (FICL_WORD *)(cp + 1 - (sizeof (FICL_WORD) / sizeof (CELL)));
- if (isAFiclWord(pd, pFW))
- return pFW;
- }
-
- return NULL;
-}
+ ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+ ficlHash *pFHash;
+ ficlWord **hash;
+ unsigned size;
+ ficlWord *word;
+ unsigned i;
+ int nMax = 0;
+ int nWords = 0;
+ int nFilled;
+ double avg = 0.0;
+ double best;
+ int nAvg, nRem, nDepth;
+ FICL_VM_DICTIONARY_CHECK(vm, dictionary, 0);
-/**************************************************************************
- s e e
-** TOOLS ( "<spaces>name" -- )
-** Display a human-readable representation of the named word's definition.
-** The source of the representation (object-code decompilation, source
-** block, etc.) and the particular form of the display is implementation
-** defined.
-**************************************************************************/
-/*
-** seeColon (for proctologists only)
-** Walks a colon definition, decompiling
-** on the fly. Knows about primitive control structures.
-*/
-static void seeColon(FICL_VM *pVM, CELL *pc)
-{
- char *cp;
- CELL *param0 = pc;
- FICL_DICT *pd = vmGetDict(pVM);
- FICL_WORD *pSemiParen = ficlLookup(pVM->pSys, "(;)");
- assert(pSemiParen);
+ pFHash = dictionary->wordlists[dictionary->wordlistCount - 1];
+ hash = pFHash->table;
+ size = pFHash->size;
+ nFilled = size;
- for (; pc->p != pSemiParen; pc++)
+ for (i = 0; i < size; i++)
{
- FICL_WORD *pFW = (FICL_WORD *)(pc->p);
-
- cp = pVM->pad;
- if ((void *)pc == (void *)pVM->ip)
- *cp++ = '>';
- else
- *cp++ = ' ';
- cp += sprintf(cp, "%3d ", pc-param0);
-
- if (isAFiclWord(pd, pFW))
- {
- WORDKIND kind = ficlWordClassify(pFW);
- CELL c;
+ int n = 0;
+ word = hash[i];
- switch (kind)
- {
- case LITERAL:
- c = *++pc;
- if (isAFiclWord(pd, c.p))
- {
- FICL_WORD *pLit = (FICL_WORD *)c.p;
- sprintf(cp, "%.*s ( %#lx literal )",
- pLit->nName, pLit->name, c.u);
- }
- else
- sprintf(cp, "literal %ld (%#lx)", c.i, c.u);
- break;
- case STRINGLIT:
- {
- FICL_STRING *sp = (FICL_STRING *)(void *)++pc;
- pc = (CELL *)alignPtr(sp->text + sp->count + 1) - 1;
- sprintf(cp, "s\" %.*s\"", sp->count, sp->text);
- }
- break;
- case CSTRINGLIT:
- {
- FICL_STRING *sp = (FICL_STRING *)(void *)++pc;
- pc = (CELL *)alignPtr(sp->text + sp->count + 1) - 1;
- sprintf(cp, "c\" %.*s\"", sp->count, sp->text);
- }
- break;
- case IF:
- c = *++pc;
- if (c.i > 0)
- sprintf(cp, "if / while (branch %d)", pc+c.i-param0);
- else
- sprintf(cp, "until (branch %d)", pc+c.i-param0);
- break;
- case BRANCH:
- c = *++pc;
- if (c.i == 0)
- sprintf(cp, "repeat (branch %d)", pc+c.i-param0);
- else if (c.i == 1)
- sprintf(cp, "else (branch %d)", pc+c.i-param0);
- else
- sprintf(cp, "endof (branch %d)", pc+c.i-param0);
- break;
-
- case OF:
- c = *++pc;
- sprintf(cp, "of (branch %d)", pc+c.i-param0);
- break;
-
- case QDO:
- c = *++pc;
- sprintf(cp, "?do (leave %d)", (CELL *)c.p-param0);
- break;
- case DO:
- c = *++pc;
- sprintf(cp, "do (leave %d)", (CELL *)c.p-param0);
- break;
- case LOOP:
- c = *++pc;
- sprintf(cp, "loop (branch %d)", pc+c.i-param0);
- break;
- case PLOOP:
- c = *++pc;
- sprintf(cp, "+loop (branch %d)", pc+c.i-param0);
- break;
- default:
- sprintf(cp, "%.*s", pFW->nName, pFW->name);
- break;
- }
-
- }
- else /* probably not a word - punt and print value */
+ while (word)
{
- sprintf(cp, "%ld ( %#lx )", pc->i, pc->u);
+ ++n;
+ ++nWords;
+ word = word->link;
}
- vmTextOut(pVM, pVM->pad, 1);
+ avg += (double)(n * (n+1)) / 2.0;
+
+ if (n > nMax)
+ nMax = n;
+ if (n == 0)
+ --nFilled;
}
- vmTextOut(pVM, ";", 1);
+ /* Calc actual avg search depth for this hash */
+ avg = avg / nWords;
+
+ /* Calc best possible performance with this size hash */
+ nAvg = nWords / size;
+ nRem = nWords % size;
+ nDepth = size * (nAvg * (nAvg+1))/2 + (nAvg+1)*nRem;
+ best = (double)nDepth/nWords;
+
+ sprintf(vm->pad,
+ "%d bins, %2.0f%% filled, Depth: Max=%d, Avg=%2.1f, Best=%2.1f, Score: %2.0f%%\n",
+ size,
+ (double)nFilled * 100.0 / size, nMax,
+ avg,
+ best,
+ 100.0 * best / avg);
+
+ ficlVmTextOut(vm, vm->pad);
+
+ return;
}
+#endif
/*
** Here's the outer part of the decompiler. It's
@@ -292,71 +210,77 @@ static void seeColon(FICL_VM *pVM, CELL *pc)
** something appropriate. If the CFA is not recognized,
** just indicate that it is a primitive.
*/
-static void seeXT(FICL_VM *pVM)
+static void ficlPrimitiveSeeXT(ficlVm *vm)
{
- FICL_WORD *pFW;
- WORDKIND kind;
+ ficlWord *word;
+ ficlWordKind kind;
- pFW = (FICL_WORD *)stackPopPtr(pVM->pStack);
- kind = ficlWordClassify(pFW);
+ word = (ficlWord *)ficlStackPopPointer(vm->dataStack);
+ kind = ficlWordClassify(word);
switch (kind)
{
- case COLON:
- sprintf(pVM->pad, ": %.*s", pFW->nName, pFW->name);
- vmTextOut(pVM, pVM->pad, 1);
- seeColon(pVM, pFW->param);
+ case FICL_WORDKIND_COLON:
+ sprintf(vm->pad, ": %.*s\n", word->length, word->name);
+ ficlVmTextOut(vm, vm->pad);
+ ficlDictionarySee(ficlVmGetDictionary(vm), word, &(vm->callback));
break;
- case DOES:
- vmTextOut(pVM, "does>", 1);
- seeColon(pVM, (CELL *)pFW->param->p);
+ case FICL_WORDKIND_DOES:
+ ficlVmTextOut(vm, "does>\n");
+ ficlDictionarySee(ficlVmGetDictionary(vm), (ficlWord *)word->param->p, &(vm->callback));
break;
- case CREATE:
- vmTextOut(pVM, "create", 1);
+ case FICL_WORDKIND_CREATE:
+ ficlVmTextOut(vm, "create\n");
break;
- case VARIABLE:
- sprintf(pVM->pad, "variable = %ld (%#lx)", pFW->param->i, pFW->param->u);
- vmTextOut(pVM, pVM->pad, 1);
+ case FICL_WORDKIND_VARIABLE:
+ sprintf(vm->pad, "variable = %ld (%#lx)\n", word->param->i, word->param->u);
+ ficlVmTextOut(vm, vm->pad);
break;
#if FICL_WANT_USER
- case USER:
- sprintf(pVM->pad, "user variable %ld (%#lx)", pFW->param->i, pFW->param->u);
- vmTextOut(pVM, pVM->pad, 1);
+ case FICL_WORDKIND_USER:
+ sprintf(vm->pad, "user variable %ld (%#lx)\n", word->param->i, word->param->u);
+ ficlVmTextOut(vm, vm->pad);
break;
#endif
- case CONSTANT:
- sprintf(pVM->pad, "constant = %ld (%#lx)", pFW->param->i, pFW->param->u);
- vmTextOut(pVM, pVM->pad, 1);
+ case FICL_WORDKIND_CONSTANT:
+ sprintf(vm->pad, "constant = %ld (%#lx)\n", word->param->i, word->param->u);
+ ficlVmTextOut(vm, vm->pad);
+ break;
+
+ case FICL_WORDKIND_2CONSTANT:
+ sprintf(vm->pad, "constant = %ld %ld (%#lx %#lx)\n", word->param[1].i, word->param->i, word->param[1].u, word->param->u);
+ ficlVmTextOut(vm, vm->pad);
+ break;
default:
- sprintf(pVM->pad, "%.*s is a primitive", pFW->nName, pFW->name);
- vmTextOut(pVM, pVM->pad, 1);
+ sprintf(vm->pad, "%.*s is a primitive\n", word->length, word->name);
+ ficlVmTextOut(vm, vm->pad);
break;
}
- if (pFW->flags & FW_IMMEDIATE)
+ if (word->flags & FICL_WORD_IMMEDIATE)
{
- vmTextOut(pVM, "immediate", 1);
+ ficlVmTextOut(vm, "immediate\n");
}
- if (pFW->flags & FW_COMPILE)
+ if (word->flags & FICL_WORD_COMPILE_ONLY)
{
- vmTextOut(pVM, "compile-only", 1);
+ ficlVmTextOut(vm, "compile-only\n");
}
return;
}
-static void see(FICL_VM *pVM)
+static void ficlPrimitiveSee(ficlVm *vm)
{
- ficlTick(pVM);
- seeXT(pVM);
+ ficlPrimitiveTick(vm);
+ ficlPrimitiveSeeXT(vm);
return;
}
@@ -369,27 +293,27 @@ static void see(FICL_VM *pVM)
** set a breakpoint at its first instruction, and run to the breakpoint.
** Note: the semantics of this word are equivalent to "step in"
**************************************************************************/
-void ficlDebugXT(FICL_VM *pVM)
+static void ficlPrimitiveDebugXT(ficlVm *vm)
{
- FICL_WORD *xt = stackPopPtr(pVM->pStack);
- WORDKIND wk = ficlWordClassify(xt);
+ ficlWord *xt = ficlStackPopPointer(vm->dataStack);
+ ficlWordKind wk = ficlWordClassify(xt);
- stackPushPtr(pVM->pStack, xt);
- seeXT(pVM);
+ ficlStackPushPointer(vm->dataStack, xt);
+ ficlPrimitiveSeeXT(vm);
switch (wk)
{
- case COLON:
- case DOES:
+ case FICL_WORDKIND_COLON:
+ case FICL_WORDKIND_DOES:
/*
** Run the colon code and set a breakpoint at the next instruction
*/
- vmExecute(pVM, xt);
- vmSetBreak(pVM, &(pVM->pSys->bpStep));
+ ficlVmExecuteWord(vm, xt);
+ ficlVmSetBreak(vm, &(vm->callback.system->breakpoint));
break;
default:
- vmExecute(pVM, xt);
+ ficlVmExecuteWord(vm, xt);
break;
}
@@ -399,23 +323,21 @@ void ficlDebugXT(FICL_VM *pVM)
/**************************************************************************
s t e p I n
-** FICL
+** Ficl
** Execute the next instruction, stepping into it if it's a colon definition
** or a does> word. This is the easy kind of step.
**************************************************************************/
-void stepIn(FICL_VM *pVM)
+static void ficlPrimitiveStepIn(ficlVm *vm)
{
/*
** Do one step of the inner loop
*/
- {
- M_VM_STEP(pVM)
- }
+ ficlVmExecuteWord(vm, *vm->ip++);
/*
** Now set a breakpoint at the next instruction
*/
- vmSetBreak(pVM, &(pVM->pSys->bpStep));
+ ficlVmSetBreak(vm, &(vm->callback.system->breakpoint));
return;
}
@@ -423,36 +345,36 @@ void stepIn(FICL_VM *pVM)
/**************************************************************************
s t e p O v e r
-** FICL
+** Ficl
** Execute the next instruction atomically. This requires some insight into
** the memory layout of compiled code. Set a breakpoint at the next instruction
** in this word, and run until we hit it
**************************************************************************/
-void stepOver(FICL_VM *pVM)
+static void ficlPrimitiveStepOver(ficlVm *vm)
{
- FICL_WORD *pFW;
- WORDKIND kind;
- FICL_WORD *pStep = ficlLookup(pVM->pSys, "step-break");
- assert(pStep);
+ ficlWord *word;
+ ficlWordKind kind;
+ ficlWord *pStep = ficlSystemLookup(vm->callback.system, "step-break");
+ FICL_VM_ASSERT(vm, pStep);
- pFW = *pVM->ip;
- kind = ficlWordClassify(pFW);
+ word = *vm->ip;
+ kind = ficlWordClassify(word);
switch (kind)
{
- case COLON:
- case DOES:
+ case FICL_WORDKIND_COLON:
+ case FICL_WORDKIND_DOES:
/*
- ** assume that the next cell holds an instruction
- ** set a breakpoint there and return to the inner interp
+ ** assume that the next ficlCell holds an instruction
+ ** set a breakpoint there and return to the inner interpreter
*/
- pVM->pSys->bpStep.address = pVM->ip + 1;
- pVM->pSys->bpStep.origXT = pVM->ip[1];
- pVM->ip[1] = pStep;
+ vm->callback.system->breakpoint.address = vm->ip + 1;
+ vm->callback.system->breakpoint.oldXT = vm->ip[1];
+ vm->ip[1] = pStep;
break;
default:
- stepIn(pVM);
+ ficlPrimitiveStepIn(vm);
break;
}
@@ -462,9 +384,9 @@ void stepOver(FICL_VM *pVM)
/**************************************************************************
s t e p - b r e a k
-** FICL
+** Ficl
** Handles breakpoints for stepped execution.
-** Upon entry, bpStep contains the address and replaced instruction
+** Upon entry, breakpoint contains the address and replaced instruction
** of the current breakpoint.
** Clear the breakpoint
** Get a command from the console.
@@ -476,118 +398,141 @@ void stepOver(FICL_VM *pVM)
** q (quit) - abort current word
** b (toggle breakpoint)
**************************************************************************/
-void stepBreak(FICL_VM *pVM)
+
+extern char *ficlDictionaryInstructionNames[];
+
+static void ficlPrimitiveStepBreak(ficlVm *vm)
{
- STRINGINFO si;
- FICL_WORD *pFW;
- FICL_WORD *pOnStep;
+ ficlString command;
+ ficlWord *word;
+ ficlWord *pOnStep;
+ ficlWordKind kind;
- if (!pVM->fRestart)
+ if (!vm->restart)
{
- assert(pVM->pSys->bpStep.address);
- assert(pVM->pSys->bpStep.origXT);
+ FICL_VM_ASSERT(vm, vm->callback.system->breakpoint.address);
+ FICL_VM_ASSERT(vm, vm->callback.system->breakpoint.oldXT);
/*
** Clear the breakpoint that caused me to run
** Restore the original instruction at the breakpoint,
** and restore the IP
*/
- pVM->ip = (IPTYPE)(pVM->pSys->bpStep.address);
- *pVM->ip = pVM->pSys->bpStep.origXT;
+ vm->ip = (ficlIp)(vm->callback.system->breakpoint.address);
+ *vm->ip = vm->callback.system->breakpoint.oldXT;
/*
** If there's an onStep, do it
*/
- pOnStep = ficlLookup(pVM->pSys, "on-step");
+ pOnStep = ficlSystemLookup(vm->callback.system, "on-step");
if (pOnStep)
- ficlExecXT(pVM, pOnStep);
+ ficlVmExecuteXT(vm, pOnStep);
/*
** Print the name of the next instruction
*/
- pFW = pVM->pSys->bpStep.origXT;
- sprintf(pVM->pad, "next: %.*s", pFW->nName, pFW->name);
-#if 0
- if (isPrimitive(pFW))
- {
- strcat(pVM->pad, " ( primitive )");
- }
-#endif
+ word = vm->callback.system->breakpoint.oldXT;
- vmTextOut(pVM, pVM->pad, 1);
- debugPrompt(pVM);
- }
- else
- {
- pVM->fRestart = 0;
- }
-
- si = vmGetWord(pVM);
+ kind = ficlWordClassify(word);
- if (!strincmp(si.cp, "i", si.count))
- {
- stepIn(pVM);
- }
- else if (!strincmp(si.cp, "g", si.count))
- {
- return;
- }
- else if (!strincmp(si.cp, "l", si.count))
- {
- FICL_WORD *xt;
- xt = findEnclosingWord(pVM, (CELL *)(pVM->ip));
- if (xt)
+ switch (kind)
{
- stackPushPtr(pVM->pStack, xt);
- seeXT(pVM);
- }
- else
- {
- vmTextOut(pVM, "sorry - can't do that", 1);
- }
- vmThrow(pVM, VM_RESTART);
- }
- else if (!strincmp(si.cp, "o", si.count))
- {
- stepOver(pVM);
- }
- else if (!strincmp(si.cp, "q", si.count))
- {
- ficlTextOut(pVM, FICL_PROMPT, 0);
- vmThrow(pVM, VM_ABORT);
- }
- else if (!strincmp(si.cp, "x", si.count))
- {
- /*
- ** Take whatever's left in the TIB and feed it to a subordinate ficlExec
- */
- int ret;
- char *cp = pVM->tib.cp + pVM->tib.index;
- int count = pVM->tib.end - cp;
- FICL_WORD *oldRun = pVM->runningWord;
-
- ret = ficlExecC(pVM, cp, count);
-
- if (ret == VM_OUTOFTEXT)
- {
- ret = VM_RESTART;
- pVM->runningWord = oldRun;
- vmTextOut(pVM, "", 1);
- }
-
- vmThrow(pVM, ret);
+ case FICL_WORDKIND_INSTRUCTION:
+ case FICL_WORDKIND_INSTRUCTION_WITH_ARGUMENT:
+ sprintf(vm->pad, "next: %s (instruction %ld)\n", ficlDictionaryInstructionNames[(long)word], (long)word);
+ break;
+ default:
+ sprintf(vm->pad, "next: %s\n", word->name);
+ break;
+ }
+
+ ficlVmTextOut(vm, vm->pad);
+ ficlDebugPrompt(vm);
}
else
{
- vmTextOut(pVM, "i -- step In", 1);
- vmTextOut(pVM, "o -- step Over", 1);
- vmTextOut(pVM, "g -- Go (execute to completion)", 1);
- vmTextOut(pVM, "l -- List source code", 1);
- vmTextOut(pVM, "q -- Quit (stop debugging and abort)", 1);
- vmTextOut(pVM, "x -- eXecute the rest of the line as ficl words", 1);
- debugPrompt(pVM);
- vmThrow(pVM, VM_RESTART);
+ vm->restart = 0;
}
+ command = ficlVmGetWord(vm);
+
+ switch (command.text[0])
+ {
+ case 'i':
+ ficlPrimitiveStepIn(vm);
+ break;
+
+ case 'o':
+ ficlPrimitiveStepOver(vm);
+ break;
+
+ case 'g':
+ break;
+
+ case 'l':
+ {
+ ficlWord *xt;
+ xt = ficlDictionaryFindEnclosingWord(ficlVmGetDictionary(vm), (ficlCell *)(vm->ip));
+ if (xt)
+ {
+ ficlStackPushPointer(vm->dataStack, xt);
+ ficlPrimitiveSeeXT(vm);
+ }
+ else
+ {
+ ficlVmTextOut(vm, "sorry - can't do that\n");
+ }
+ ficlVmThrow(vm, FICL_VM_STATUS_RESTART);
+ break;
+ }
+
+ case 'q':
+ {
+ ficlVmTextOut(vm, FICL_PROMPT);
+ ficlVmThrow(vm, FICL_VM_STATUS_ABORT);
+ break;
+ }
+
+ case 'x':
+ {
+ /*
+ ** Take whatever's left in the TIB and feed it to a subordinate ficlVmExecuteString
+ */
+ int returnValue;
+ ficlString s;
+ ficlWord *oldRunningWord = vm->runningWord;
+
+ FICL_STRING_SET_POINTER(s, vm->tib.text + vm->tib.index);
+ FICL_STRING_SET_LENGTH(s, vm->tib.end - FICL_STRING_GET_POINTER(s));
+
+ returnValue = ficlVmExecuteString(vm, s);
+
+ if (returnValue == FICL_VM_STATUS_OUT_OF_TEXT)
+ {
+ returnValue = FICL_VM_STATUS_RESTART;
+ vm->runningWord = oldRunningWord;
+ ficlVmTextOut(vm, "\n");
+ }
+
+ ficlVmThrow(vm, returnValue);
+ break;
+ }
+
+ default:
+ {
+ ficlVmTextOut(vm,
+ "i -- step In\n"
+ "o -- step Over\n"
+ "g -- Go (execute to completion)\n"
+ "l -- List source code\n"
+ "q -- Quit (stop debugging and abort)\n"
+ "x -- eXecute the rest of the line as Ficl words\n"
+ );
+ ficlDebugPrompt(vm);
+ ficlVmThrow(vm, FICL_VM_STATUS_RESTART);
+ break;
+ }
+ }
+
return;
}
@@ -598,9 +543,9 @@ void stepBreak(FICL_VM *pVM)
** Signal the system to shut down - this causes ficlExec to return
** VM_USEREXIT. The rest is up to you.
**************************************************************************/
-static void bye(FICL_VM *pVM)
+static void ficlPrimitiveBye(ficlVm *vm)
{
- vmThrow(pVM, VM_USEREXIT);
+ ficlVmThrow(vm, FICL_VM_STATUS_USER_EXIT);
return;
}
@@ -610,85 +555,141 @@ static void bye(FICL_VM *pVM)
** TOOLS
** Display the parameter stack (code for ".s")
**************************************************************************/
-static void displayPStack(FICL_VM *pVM)
+
+struct stackContext
{
- FICL_STACK *pStk = pVM->pStack;
- int d = stackDepth(pStk);
- int i;
- CELL *pCell;
+ ficlVm *vm;
+ ficlDictionary *dictionary;
+ int count;
+};
- vmCheckStack(pVM, 0, 0);
+static ficlInteger ficlStackDisplayCallback(void *c, ficlCell *cell)
+{
+ struct stackContext *context = (struct stackContext *)c;
+ char buffer[64];
+ sprintf(buffer, "[0x%08x %3d]: %12d (0x%08x)\n", cell, context->count++, cell->i, cell->i);
+ ficlVmTextOut(context->vm, buffer);
+ return FICL_TRUE;
+}
- if (d == 0)
- vmTextOut(pVM, "(Stack Empty) ", 0);
- else
+void ficlStackDisplay(ficlStack *stack, ficlStackWalkFunction callback, void *context)
+{
+ ficlVm *vm = stack->vm;
+ char buffer[128];
+ struct stackContext myContext;
+
+ FICL_STACK_CHECK(stack, 0, 0);
+
+ sprintf(buffer, "[%s stack has %d entries, top at 0x%08x]\n", stack->name, ficlStackDepth(stack), stack->top);
+ ficlVmTextOut(vm, buffer);
+
+ if (callback == NULL)
{
- pCell = pStk->base;
- for (i = 0; i < d; i++)
- {
- vmTextOut(pVM, ltoa((*pCell++).i, pVM->pad, pVM->base), 0);
- vmTextOut(pVM, " ", 0);
- }
+ myContext.vm = vm;
+ myContext.count = 0;
+ context = &myContext;
+ callback = ficlStackDisplayCallback;
}
+ ficlStackWalk(stack, callback, context, FICL_FALSE);
+
+ sprintf(buffer, "[%s stack base at 0x%08x]\n", stack->name, stack->base);
+ ficlVmTextOut(vm, buffer);
+
return;
}
-static void displayRStack(FICL_VM *pVM)
+void ficlVmDisplayDataStack(ficlVm *vm)
{
- FICL_STACK *pStk = pVM->rStack;
- int d = stackDepth(pStk);
- int i;
- CELL *pCell;
- FICL_DICT *dp = vmGetDict(pVM);
+ ficlStackDisplay(vm->dataStack, NULL, NULL);
+ return;
+}
- vmCheckStack(pVM, 0, 0);
- if (d == 0)
- vmTextOut(pVM, "(Stack Empty) ", 0);
- else
+
+
+static ficlInteger ficlStackDisplaySimpleCallback(void *c, ficlCell *cell)
+{
+ struct stackContext *context = (struct stackContext *)c;
+ char buffer[32];
+ sprintf(buffer, "%s%d", context->count ? " " : "", cell->i);
+ context->count++;
+ ficlVmTextOut(context->vm, buffer);
+ return FICL_TRUE;
+}
+
+
+void ficlVmDisplayDataStackSimple(ficlVm *vm)
+{
+ ficlStack *stack = vm->dataStack;
+ char buffer[32];
+ struct stackContext context;
+
+ FICL_STACK_CHECK(stack, 0, 0);
+
+ sprintf(buffer, "[%d] ", ficlStackDepth(stack));
+ ficlVmTextOut(vm, buffer);
+
+ context.vm = vm;
+ context.count = 0;
+ ficlStackWalk(stack, ficlStackDisplaySimpleCallback, &context, FICL_TRUE);
+ return;
+}
+
+
+
+
+static ficlInteger ficlReturnStackDisplayCallback(void *c, ficlCell *cell)
+{
+ struct stackContext *context = (struct stackContext *)c;
+ char buffer[128];
+
+ sprintf(buffer, "[0x%08x %3d] %12d (0x%08x)", cell, context->count++, cell->i, cell->i);
+
+ /*
+ ** Attempt to find the word that contains the return
+ ** stack address (as if it is part of a colon definition).
+ ** If this works, also print the name of the word.
+ */
+ if (ficlDictionaryIncludes(context->dictionary, cell->p))
{
- pCell = pStk->base;
- for (i = 0; i < d; i++)
+ ficlWord *word = ficlDictionaryFindEnclosingWord(context->dictionary, cell->p);
+ if (word)
{
- CELL c = *pCell++;
- /*
- ** Attempt to find the word that contains the
- ** stacked address (as if it is part of a colon definition).
- ** If this works, print the name of the word. Otherwise print
- ** the value as a number.
- */
- if (dictIncludes(dp, c.p))
- {
- FICL_WORD *pFW = findEnclosingWord(pVM, c.p);
- if (pFW)
- {
- int offset = (CELL *)c.p - &pFW->param[0];
- sprintf(pVM->pad, "%s+%d ", pFW->name, offset);
- vmTextOut(pVM, pVM->pad, 0);
- continue; /* no need to print the numeric value */
- }
- }
- vmTextOut(pVM, ltoa(c.i, pVM->pad, pVM->base), 0);
- vmTextOut(pVM, " ", 0);
+ int offset = (ficlCell *)cell->p - &word->param[0];
+ sprintf(buffer + strlen(buffer), ", %s + %d ", word->name, offset);
}
}
+ strcat(buffer, "\n");
+ ficlVmTextOut(context->vm, buffer);
+ return FICL_TRUE;
+}
+
+void ficlVmDisplayReturnStack(ficlVm *vm)
+{
+ struct stackContext context;
+ context.vm = vm;
+ context.count = 0;
+ context.dictionary = ficlVmGetDictionary(vm);
+ ficlStackDisplay(vm->returnStack, ficlReturnStackDisplayCallback, &context);
return;
}
+
+
/**************************************************************************
f o r g e t - w i d
**
**************************************************************************/
-static void forgetWid(FICL_VM *pVM)
+static void ficlPrimitiveForgetWid(ficlVm *vm)
{
- FICL_DICT *pDict = vmGetDict(pVM);
- FICL_HASH *pHash;
+ ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+ ficlHash *hash;
- pHash = (FICL_HASH *)stackPopPtr(pVM->pStack);
- hashForget(pHash, pDict->here);
+ hash = (ficlHash *)ficlStackPopPointer(vm->dataStack);
+ ficlHashForget(hash, dictionary->here);
return;
}
@@ -706,43 +707,43 @@ static void forgetWid(FICL_VM *pVM)
** compilation word list. An ambiguous condition exists if the
** compilation word list is deleted.
**************************************************************************/
-static void forget(FICL_VM *pVM)
+static void ficlPrimitiveForget(ficlVm *vm)
{
void *where;
- FICL_DICT *pDict = vmGetDict(pVM);
- FICL_HASH *pHash = pDict->pCompile;
+ ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+ ficlHash *hash = dictionary->compilationWordlist;
- ficlTick(pVM);
- where = ((FICL_WORD *)stackPopPtr(pVM->pStack))->name;
- hashForget(pHash, where);
- pDict->here = PTRtoCELL where;
+ ficlPrimitiveTick(vm);
+ where = ((ficlWord *)ficlStackPopPointer(vm->dataStack))->name;
+ ficlHashForget(hash, where);
+ dictionary->here = FICL_POINTER_TO_CELL(where);
return;
}
/**************************************************************************
- l i s t W o r d s
+ w o r d s
**
**************************************************************************/
#define nCOLWIDTH 8
-static void listWords(FICL_VM *pVM)
+static void ficlPrimitiveWords(ficlVm *vm)
{
- FICL_DICT *dp = vmGetDict(pVM);
- FICL_HASH *pHash = dp->pSearch[dp->nLists - 1];
- FICL_WORD *wp;
+ ficlDictionary *dictionary = ficlVmGetDictionary(vm);
+ ficlHash *hash = dictionary->wordlists[dictionary->wordlistCount - 1];
+ ficlWord *wp;
int nChars = 0;
int len;
unsigned i;
int nWords = 0;
char *cp;
- char *pPad = pVM->pad;
+ char *pPad = vm->pad;
- for (i = 0; i < pHash->size; i++)
+ for (i = 0; i < hash->size; i++)
{
- for (wp = pHash->table[i]; wp != NULL; wp = wp->link, nWords++)
+ for (wp = hash->table[i]; wp != NULL; wp = wp->link, nWords++)
{
- if (wp->nName == 0) /* ignore :noname defs */
+ if (wp->length == 0) /* ignore :noname defs */
continue;
cp = wp->name;
@@ -750,9 +751,10 @@ static void listWords(FICL_VM *pVM)
if (nChars > 70)
{
+ pPad[nChars++] = '\n';
pPad[nChars] = '\0';
nChars = 0;
- vmTextOut(pVM, pPad, 1);
+ ficlVmTextOut(vm, pPad);
}
else
{
@@ -763,23 +765,25 @@ static void listWords(FICL_VM *pVM)
if (nChars > 70)
{
+ pPad[nChars++] = '\n';
pPad[nChars] = '\0';
nChars = 0;
- vmTextOut(pVM, pPad, 1);
+ ficlVmTextOut(vm, pPad);
}
}
}
if (nChars > 0)
{
+ pPad[nChars++] = '\n';
pPad[nChars] = '\0';
nChars = 0;
- vmTextOut(pVM, pPad, 1);
+ ficlVmTextOut(vm, pPad);
}
- sprintf(pVM->pad, "Dictionary: %d words, %ld cells used of %u total",
- nWords, (long) (dp->here - dp->dict), dp->size);
- vmTextOut(pVM, pVM->pad, 1);
+ sprintf(vm->pad, "Dictionary: %d words, %ld cells used of %u total\n",
+ nWords, (long) (dictionary->here - dictionary->base), dictionary->size);
+ ficlVmTextOut(vm, vm->pad);
return;
}
@@ -788,60 +792,82 @@ static void listWords(FICL_VM *pVM)
l i s t E n v
** Print symbols defined in the environment
**************************************************************************/
-static void listEnv(FICL_VM *pVM)
+static void ficlPrimitiveListEnv(ficlVm *vm)
{
- FICL_DICT *dp = pVM->pSys->envp;
- FICL_HASH *pHash = dp->pForthWords;
- FICL_WORD *wp;
+ ficlDictionary *dictionary = vm->callback.system->environment;
+ ficlHash *hash = dictionary->forthWordlist;
+ ficlWord *word;
unsigned i;
- int nWords = 0;
+ int counter = 0;
- for (i = 0; i < pHash->size; i++)
+ for (i = 0; i < hash->size; i++)
{
- for (wp = pHash->table[i]; wp != NULL; wp = wp->link, nWords++)
+ for (word = hash->table[i]; word != NULL; word = word->link, counter++)
{
- vmTextOut(pVM, wp->name, 1);
+ ficlVmTextOut(vm, word->name);
+ ficlVmTextOut(vm, "\n");
}
}
- sprintf(pVM->pad, "Environment: %d words, %ld cells used of %u total",
- nWords, (long) (dp->here - dp->dict), dp->size);
- vmTextOut(pVM, pVM->pad, 1);
+ sprintf(vm->pad, "Environment: %d words, %ld cells used of %u total\n",
+ counter, (long) (dictionary->here - dictionary->base), dictionary->size);
+ ficlVmTextOut(vm, vm->pad);
+ return;
+}
+
+
+
+
+/*
+** This word lists the parse steps in order
+*/
+void ficlPrimitiveParseStepList(ficlVm *vm)
+{
+ int i;
+ ficlSystem *system = vm->callback.system;
+ FICL_VM_ASSERT(vm, system);
+
+ ficlVmTextOut(vm, "Parse steps:\n");
+ ficlVmTextOut(vm, "lookup\n");
+
+ for (i = 0; i < FICL_MAX_PARSE_STEPS; i++)
+ {
+ if (system->parseList[i] != NULL)
+ {
+ ficlVmTextOut(vm, system->parseList[i]->name);
+ ficlVmTextOut(vm, "\n");
+ }
+ else break;
+ }
return;
}
/**************************************************************************
e n v C o n s t a n t
-** Ficl interface to ficlSetEnv and ficlSetEnvD - allow ficl code to set
+** Ficl interface to ficlSystemSetEnvironment and ficlSetEnvD - allow Ficl code to set
** environment constants...
**************************************************************************/
-static void envConstant(FICL_VM *pVM)
+static void ficlPrimitiveEnvConstant(ficlVm *vm)
{
unsigned value;
+ FICL_STACK_CHECK(vm->dataStack, 1, 0);
-#if FICL_ROBUST > 1
- vmCheckStack(pVM, 1, 0);
-#endif
-
- vmGetWordToPad(pVM);
- value = POPUNS();
- ficlSetEnv(pVM->pSys, pVM->pad, (FICL_UNS)value);
+ ficlVmGetWordToPad(vm);
+ value = ficlStackPopUnsigned(vm->dataStack);
+ ficlDictionarySetConstant(ficlSystemGetEnvironment(vm->callback.system), vm->pad, (ficlUnsigned)value);
return;
}
-static void env2Constant(FICL_VM *pVM)
+static void ficlPrimitiveEnv2Constant(ficlVm *vm)
{
- unsigned v1, v2;
+ ficl2Integer value;
-#if FICL_ROBUST > 1
- vmCheckStack(pVM, 2, 0);
-#endif
+ FICL_STACK_CHECK(vm->dataStack, 2, 0);
- vmGetWordToPad(pVM);
- v2 = POPUNS();
- v1 = POPUNS();
- ficlSetEnvD(pVM->pSys, pVM->pad, v1, v2);
+ ficlVmGetWordToPad(vm);
+ value = ficlStackPop2Integer(vm->dataStack);
+ ficlDictionarySet2Constant(ficlSystemGetEnvironment(vm->callback.system), vm->pad, value);
return;
}
@@ -851,42 +877,49 @@ static void env2Constant(FICL_VM *pVM)
** Builds wordset for debugger and TOOLS optional word set
**************************************************************************/
-void ficlCompileTools(FICL_SYSTEM *pSys)
+void ficlSystemCompileTools(ficlSystem *system)
{
- FICL_DICT *dp = pSys->dp;
- assert (dp);
+ ficlDictionary *dictionary = ficlSystemGetDictionary(system);
+ ficlDictionary *environment = ficlSystemGetEnvironment(system);
+
+ FICL_SYSTEM_ASSERT(system, dictionary);
+ FICL_SYSTEM_ASSERT(system, environment);
+
/*
** TOOLS and TOOLS EXT
*/
- dictAppendWord(dp, ".s", displayPStack, FW_DEFAULT);
- dictAppendWord(dp, "bye", bye, FW_DEFAULT);
- dictAppendWord(dp, "forget", forget, FW_DEFAULT);
- dictAppendWord(dp, "see", see, FW_DEFAULT);
- dictAppendWord(dp, "words", listWords, FW_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, ".s", ficlVmDisplayDataStack, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, ".s-simple", ficlVmDisplayDataStackSimple, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "bye", ficlPrimitiveBye, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "forget", ficlPrimitiveForget, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "see", ficlPrimitiveSee, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "words", ficlPrimitiveWords, FICL_WORD_DEFAULT);
/*
** Set TOOLS environment query values
*/
- ficlSetEnv(pSys, "tools", FICL_TRUE);
- ficlSetEnv(pSys, "tools-ext", FICL_FALSE);
+ ficlDictionarySetConstant(environment, "tools", FICL_TRUE);
+ ficlDictionarySetConstant(environment, "tools-ext", FICL_FALSE);
/*
** Ficl extras
*/
- dictAppendWord(dp, "r.s", displayRStack, FW_DEFAULT); /* guy carver */
- dictAppendWord(dp, ".env", listEnv, FW_DEFAULT);
- dictAppendWord(dp, "env-constant",
- envConstant, FW_DEFAULT);
- dictAppendWord(dp, "env-2constant",
- env2Constant, FW_DEFAULT);
- dictAppendWord(dp, "debug-xt", ficlDebugXT, FW_DEFAULT);
- dictAppendWord(dp, "parse-order",
- ficlListParseSteps,
- FW_DEFAULT);
- dictAppendWord(dp, "step-break",stepBreak, FW_DEFAULT);
- dictAppendWord(dp, "forget-wid",forgetWid, FW_DEFAULT);
- dictAppendWord(dp, "see-xt", seeXT, FW_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "r.s", ficlVmDisplayReturnStack, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, ".env", ficlPrimitiveListEnv, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "env-constant",
+ ficlPrimitiveEnvConstant, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "env-2constant",
+ ficlPrimitiveEnv2Constant, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "debug-xt", ficlPrimitiveDebugXT, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "parse-order", ficlPrimitiveParseStepList, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "step-break",ficlPrimitiveStepBreak, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "forget-wid",ficlPrimitiveForgetWid, FICL_WORD_DEFAULT);
+ ficlDictionarySetPrimitive(dictionary, "see-xt", ficlPrimitiveSeeXT, FICL_WORD_DEFAULT);
+
+#if FICL_WANT_FLOAT
+ ficlDictionarySetPrimitive(dictionary, ".hash", ficlPrimitiveHashSummary,FICL_WORD_DEFAULT);
+#endif
return;
}