1*ca987d46SWarner Losh /******************************************************************* 2*ca987d46SWarner Losh ** t o o l s . c 3*ca987d46SWarner Losh ** Forth Inspired Command Language - programming tools 4*ca987d46SWarner Losh ** Author: John Sadler (john_sadler@alum.mit.edu) 5*ca987d46SWarner Losh ** Created: 20 June 2000 6*ca987d46SWarner Losh ** $Id: tools.c,v 1.11 2001/12/05 07:21:34 jsadler Exp $ 7*ca987d46SWarner Losh *******************************************************************/ 8*ca987d46SWarner Losh /* 9*ca987d46SWarner Losh ** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) 10*ca987d46SWarner Losh ** All rights reserved. 11*ca987d46SWarner Losh ** 12*ca987d46SWarner Losh ** Get the latest Ficl release at http://ficl.sourceforge.net 13*ca987d46SWarner Losh ** 14*ca987d46SWarner Losh ** I am interested in hearing from anyone who uses ficl. If you have 15*ca987d46SWarner Losh ** a problem, a success story, a defect, an enhancement request, or 16*ca987d46SWarner Losh ** if you would like to contribute to the ficl release, please 17*ca987d46SWarner Losh ** contact me by email at the address above. 18*ca987d46SWarner Losh ** 19*ca987d46SWarner Losh ** L I C E N S E and D I S C L A I M E R 20*ca987d46SWarner Losh ** 21*ca987d46SWarner Losh ** Redistribution and use in source and binary forms, with or without 22*ca987d46SWarner Losh ** modification, are permitted provided that the following conditions 23*ca987d46SWarner Losh ** are met: 24*ca987d46SWarner Losh ** 1. Redistributions of source code must retain the above copyright 25*ca987d46SWarner Losh ** notice, this list of conditions and the following disclaimer. 26*ca987d46SWarner Losh ** 2. Redistributions in binary form must reproduce the above copyright 27*ca987d46SWarner Losh ** notice, this list of conditions and the following disclaimer in the 28*ca987d46SWarner Losh ** documentation and/or other materials provided with the distribution. 29*ca987d46SWarner Losh ** 30*ca987d46SWarner Losh ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 31*ca987d46SWarner Losh ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 32*ca987d46SWarner Losh ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 33*ca987d46SWarner Losh ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 34*ca987d46SWarner Losh ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 35*ca987d46SWarner Losh ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 36*ca987d46SWarner Losh ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 37*ca987d46SWarner Losh ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 38*ca987d46SWarner Losh ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 39*ca987d46SWarner Losh ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 40*ca987d46SWarner Losh ** SUCH DAMAGE. 41*ca987d46SWarner Losh */ 42*ca987d46SWarner Losh 43*ca987d46SWarner Losh /* 44*ca987d46SWarner Losh ** NOTES: 45*ca987d46SWarner Losh ** SEE needs information about the addresses of functions that 46*ca987d46SWarner Losh ** are the CFAs of colon definitions, constants, variables, DOES> 47*ca987d46SWarner Losh ** words, and so on. It gets this information from a table and supporting 48*ca987d46SWarner Losh ** functions in words.c. 49*ca987d46SWarner Losh ** colonParen doDoes createParen variableParen userParen constantParen 50*ca987d46SWarner Losh ** 51*ca987d46SWarner Losh ** Step and break debugger for Ficl 52*ca987d46SWarner Losh ** debug ( xt -- ) Start debugging an xt 53*ca987d46SWarner Losh ** Set a breakpoint 54*ca987d46SWarner Losh ** Specify breakpoint default action 55*ca987d46SWarner Losh */ 56*ca987d46SWarner Losh 57*ca987d46SWarner Losh /* $FreeBSD$ */ 58*ca987d46SWarner Losh 59*ca987d46SWarner Losh #ifdef TESTMAIN 60*ca987d46SWarner Losh #include <stdlib.h> 61*ca987d46SWarner Losh #include <stdio.h> /* sprintf */ 62*ca987d46SWarner Losh #include <ctype.h> 63*ca987d46SWarner Losh #else 64*ca987d46SWarner Losh #include <stand.h> 65*ca987d46SWarner Losh #endif 66*ca987d46SWarner Losh #include <string.h> 67*ca987d46SWarner Losh #include "ficl.h" 68*ca987d46SWarner Losh 69*ca987d46SWarner Losh 70*ca987d46SWarner Losh #if 0 71*ca987d46SWarner Losh /* 72*ca987d46SWarner Losh ** nBREAKPOINTS sizes the breakpoint array. One breakpoint (bp 0) is reserved 73*ca987d46SWarner Losh ** for the STEP command. The rest are user programmable. 74*ca987d46SWarner Losh */ 75*ca987d46SWarner Losh #define nBREAKPOINTS 32 76*ca987d46SWarner Losh 77*ca987d46SWarner Losh #endif 78*ca987d46SWarner Losh 79*ca987d46SWarner Losh 80*ca987d46SWarner Losh /************************************************************************** 81*ca987d46SWarner Losh v m S e t B r e a k 82*ca987d46SWarner Losh ** Set a breakpoint at the current value of IP by 83*ca987d46SWarner Losh ** storing that address in a BREAKPOINT record 84*ca987d46SWarner Losh **************************************************************************/ 85*ca987d46SWarner Losh static void vmSetBreak(FICL_VM *pVM, FICL_BREAKPOINT *pBP) 86*ca987d46SWarner Losh { 87*ca987d46SWarner Losh FICL_WORD *pStep = ficlLookup(pVM->pSys, "step-break"); 88*ca987d46SWarner Losh assert(pStep); 89*ca987d46SWarner Losh 90*ca987d46SWarner Losh pBP->address = pVM->ip; 91*ca987d46SWarner Losh pBP->origXT = *pVM->ip; 92*ca987d46SWarner Losh *pVM->ip = pStep; 93*ca987d46SWarner Losh } 94*ca987d46SWarner Losh 95*ca987d46SWarner Losh 96*ca987d46SWarner Losh /************************************************************************** 97*ca987d46SWarner Losh ** d e b u g P r o m p t 98*ca987d46SWarner Losh **************************************************************************/ 99*ca987d46SWarner Losh static void debugPrompt(FICL_VM *pVM) 100*ca987d46SWarner Losh { 101*ca987d46SWarner Losh vmTextOut(pVM, "dbg> ", 0); 102*ca987d46SWarner Losh } 103*ca987d46SWarner Losh 104*ca987d46SWarner Losh 105*ca987d46SWarner Losh /************************************************************************** 106*ca987d46SWarner Losh ** i s A F i c l W o r d 107*ca987d46SWarner Losh ** Vet a candidate pointer carefully to make sure 108*ca987d46SWarner Losh ** it's not some chunk o' inline data... 109*ca987d46SWarner Losh ** It has to have a name, and it has to look 110*ca987d46SWarner Losh ** like it's in the dictionary address range. 111*ca987d46SWarner Losh ** NOTE: this excludes :noname words! 112*ca987d46SWarner Losh **************************************************************************/ 113*ca987d46SWarner Losh int isAFiclWord(FICL_DICT *pd, FICL_WORD *pFW) 114*ca987d46SWarner Losh { 115*ca987d46SWarner Losh 116*ca987d46SWarner Losh if (!dictIncludes(pd, pFW)) 117*ca987d46SWarner Losh return 0; 118*ca987d46SWarner Losh 119*ca987d46SWarner Losh if (!dictIncludes(pd, pFW->name)) 120*ca987d46SWarner Losh return 0; 121*ca987d46SWarner Losh 122*ca987d46SWarner Losh if ((pFW->link != NULL) && !dictIncludes(pd, pFW->link)) 123*ca987d46SWarner Losh return 0; 124*ca987d46SWarner Losh 125*ca987d46SWarner Losh if ((pFW->nName <= 0) || (pFW->name[pFW->nName] != '\0')) 126*ca987d46SWarner Losh return 0; 127*ca987d46SWarner Losh 128*ca987d46SWarner Losh if (strlen(pFW->name) != pFW->nName) 129*ca987d46SWarner Losh return 0; 130*ca987d46SWarner Losh 131*ca987d46SWarner Losh return 1; 132*ca987d46SWarner Losh } 133*ca987d46SWarner Losh 134*ca987d46SWarner Losh 135*ca987d46SWarner Losh #if 0 136*ca987d46SWarner Losh static int isPrimitive(FICL_WORD *pFW) 137*ca987d46SWarner Losh { 138*ca987d46SWarner Losh WORDKIND wk = ficlWordClassify(pFW); 139*ca987d46SWarner Losh return ((wk != COLON) && (wk != DOES)); 140*ca987d46SWarner Losh } 141*ca987d46SWarner Losh #endif 142*ca987d46SWarner Losh 143*ca987d46SWarner Losh 144*ca987d46SWarner Losh /************************************************************************** 145*ca987d46SWarner Losh f i n d E n c l o s i n g W o r d 146*ca987d46SWarner Losh ** Given a pointer to something, check to make sure it's an address in the 147*ca987d46SWarner Losh ** dictionary. If so, search backwards until we find something that looks 148*ca987d46SWarner Losh ** like a dictionary header. If successful, return the address of the 149*ca987d46SWarner Losh ** FICL_WORD found. Otherwise return NULL. 150*ca987d46SWarner Losh ** nSEARCH_CELLS sets the maximum neighborhood this func will search before giving up 151*ca987d46SWarner Losh **************************************************************************/ 152*ca987d46SWarner Losh #define nSEARCH_CELLS 100 153*ca987d46SWarner Losh 154*ca987d46SWarner Losh static FICL_WORD *findEnclosingWord(FICL_VM *pVM, CELL *cp) 155*ca987d46SWarner Losh { 156*ca987d46SWarner Losh FICL_WORD *pFW; 157*ca987d46SWarner Losh FICL_DICT *pd = vmGetDict(pVM); 158*ca987d46SWarner Losh int i; 159*ca987d46SWarner Losh 160*ca987d46SWarner Losh if (!dictIncludes(pd, (void *)cp)) 161*ca987d46SWarner Losh return NULL; 162*ca987d46SWarner Losh 163*ca987d46SWarner Losh for (i = nSEARCH_CELLS; i > 0; --i, --cp) 164*ca987d46SWarner Losh { 165*ca987d46SWarner Losh pFW = (FICL_WORD *)(cp + 1 - (sizeof (FICL_WORD) / sizeof (CELL))); 166*ca987d46SWarner Losh if (isAFiclWord(pd, pFW)) 167*ca987d46SWarner Losh return pFW; 168*ca987d46SWarner Losh } 169*ca987d46SWarner Losh 170*ca987d46SWarner Losh return NULL; 171*ca987d46SWarner Losh } 172*ca987d46SWarner Losh 173*ca987d46SWarner Losh 174*ca987d46SWarner Losh /************************************************************************** 175*ca987d46SWarner Losh s e e 176*ca987d46SWarner Losh ** TOOLS ( "<spaces>name" -- ) 177*ca987d46SWarner Losh ** Display a human-readable representation of the named word's definition. 178*ca987d46SWarner Losh ** The source of the representation (object-code decompilation, source 179*ca987d46SWarner Losh ** block, etc.) and the particular form of the display is implementation 180*ca987d46SWarner Losh ** defined. 181*ca987d46SWarner Losh **************************************************************************/ 182*ca987d46SWarner Losh /* 183*ca987d46SWarner Losh ** seeColon (for proctologists only) 184*ca987d46SWarner Losh ** Walks a colon definition, decompiling 185*ca987d46SWarner Losh ** on the fly. Knows about primitive control structures. 186*ca987d46SWarner Losh */ 187*ca987d46SWarner Losh static void seeColon(FICL_VM *pVM, CELL *pc) 188*ca987d46SWarner Losh { 189*ca987d46SWarner Losh char *cp; 190*ca987d46SWarner Losh CELL *param0 = pc; 191*ca987d46SWarner Losh FICL_DICT *pd = vmGetDict(pVM); 192*ca987d46SWarner Losh FICL_WORD *pSemiParen = ficlLookup(pVM->pSys, "(;)"); 193*ca987d46SWarner Losh assert(pSemiParen); 194*ca987d46SWarner Losh 195*ca987d46SWarner Losh for (; pc->p != pSemiParen; pc++) 196*ca987d46SWarner Losh { 197*ca987d46SWarner Losh FICL_WORD *pFW = (FICL_WORD *)(pc->p); 198*ca987d46SWarner Losh 199*ca987d46SWarner Losh cp = pVM->pad; 200*ca987d46SWarner Losh if ((void *)pc == (void *)pVM->ip) 201*ca987d46SWarner Losh *cp++ = '>'; 202*ca987d46SWarner Losh else 203*ca987d46SWarner Losh *cp++ = ' '; 204*ca987d46SWarner Losh cp += sprintf(cp, "%3d ", (int)(pc-param0)); 205*ca987d46SWarner Losh 206*ca987d46SWarner Losh if (isAFiclWord(pd, pFW)) 207*ca987d46SWarner Losh { 208*ca987d46SWarner Losh WORDKIND kind = ficlWordClassify(pFW); 209*ca987d46SWarner Losh CELL c; 210*ca987d46SWarner Losh 211*ca987d46SWarner Losh switch (kind) 212*ca987d46SWarner Losh { 213*ca987d46SWarner Losh case LITERAL: 214*ca987d46SWarner Losh c = *++pc; 215*ca987d46SWarner Losh if (isAFiclWord(pd, c.p)) 216*ca987d46SWarner Losh { 217*ca987d46SWarner Losh FICL_WORD *pLit = (FICL_WORD *)c.p; 218*ca987d46SWarner Losh sprintf(cp, "%.*s ( %#lx literal )", 219*ca987d46SWarner Losh pLit->nName, pLit->name, (unsigned long)c.u); 220*ca987d46SWarner Losh } 221*ca987d46SWarner Losh else 222*ca987d46SWarner Losh sprintf(cp, "literal %ld (%#lx)", 223*ca987d46SWarner Losh (long)c.i, (unsigned long)c.u); 224*ca987d46SWarner Losh break; 225*ca987d46SWarner Losh case STRINGLIT: 226*ca987d46SWarner Losh { 227*ca987d46SWarner Losh FICL_STRING *sp = (FICL_STRING *)(void *)++pc; 228*ca987d46SWarner Losh pc = (CELL *)alignPtr(sp->text + sp->count + 1) - 1; 229*ca987d46SWarner Losh sprintf(cp, "s\" %.*s\"", sp->count, sp->text); 230*ca987d46SWarner Losh } 231*ca987d46SWarner Losh break; 232*ca987d46SWarner Losh case CSTRINGLIT: 233*ca987d46SWarner Losh { 234*ca987d46SWarner Losh FICL_STRING *sp = (FICL_STRING *)(void *)++pc; 235*ca987d46SWarner Losh pc = (CELL *)alignPtr(sp->text + sp->count + 1) - 1; 236*ca987d46SWarner Losh sprintf(cp, "c\" %.*s\"", sp->count, sp->text); 237*ca987d46SWarner Losh } 238*ca987d46SWarner Losh break; 239*ca987d46SWarner Losh case IF: 240*ca987d46SWarner Losh c = *++pc; 241*ca987d46SWarner Losh if (c.i > 0) 242*ca987d46SWarner Losh sprintf(cp, "if / while (branch %d)", (int)(pc+c.i-param0)); 243*ca987d46SWarner Losh else 244*ca987d46SWarner Losh sprintf(cp, "until (branch %d)", (int)(pc+c.i-param0)); 245*ca987d46SWarner Losh break; 246*ca987d46SWarner Losh case BRANCH: 247*ca987d46SWarner Losh c = *++pc; 248*ca987d46SWarner Losh if (c.i == 0) 249*ca987d46SWarner Losh sprintf(cp, "repeat (branch %d)", (int)(pc+c.i-param0)); 250*ca987d46SWarner Losh else if (c.i == 1) 251*ca987d46SWarner Losh sprintf(cp, "else (branch %d)", (int)(pc+c.i-param0)); 252*ca987d46SWarner Losh else 253*ca987d46SWarner Losh sprintf(cp, "endof (branch %d)", (int)(pc+c.i-param0)); 254*ca987d46SWarner Losh break; 255*ca987d46SWarner Losh 256*ca987d46SWarner Losh case OF: 257*ca987d46SWarner Losh c = *++pc; 258*ca987d46SWarner Losh sprintf(cp, "of (branch %d)", (int)(pc+c.i-param0)); 259*ca987d46SWarner Losh break; 260*ca987d46SWarner Losh 261*ca987d46SWarner Losh case QDO: 262*ca987d46SWarner Losh c = *++pc; 263*ca987d46SWarner Losh sprintf(cp, "?do (leave %d)", (int)((CELL *)c.p-param0)); 264*ca987d46SWarner Losh break; 265*ca987d46SWarner Losh case DO: 266*ca987d46SWarner Losh c = *++pc; 267*ca987d46SWarner Losh sprintf(cp, "do (leave %d)", (int)((CELL *)c.p-param0)); 268*ca987d46SWarner Losh break; 269*ca987d46SWarner Losh case LOOP: 270*ca987d46SWarner Losh c = *++pc; 271*ca987d46SWarner Losh sprintf(cp, "loop (branch %d)", (int)(pc+c.i-param0)); 272*ca987d46SWarner Losh break; 273*ca987d46SWarner Losh case PLOOP: 274*ca987d46SWarner Losh c = *++pc; 275*ca987d46SWarner Losh sprintf(cp, "+loop (branch %d)", (int)(pc+c.i-param0)); 276*ca987d46SWarner Losh break; 277*ca987d46SWarner Losh default: 278*ca987d46SWarner Losh sprintf(cp, "%.*s", pFW->nName, pFW->name); 279*ca987d46SWarner Losh break; 280*ca987d46SWarner Losh } 281*ca987d46SWarner Losh 282*ca987d46SWarner Losh } 283*ca987d46SWarner Losh else /* probably not a word - punt and print value */ 284*ca987d46SWarner Losh { 285*ca987d46SWarner Losh sprintf(cp, "%ld ( %#lx )", (long)pc->i, (unsigned long)pc->u); 286*ca987d46SWarner Losh } 287*ca987d46SWarner Losh 288*ca987d46SWarner Losh vmTextOut(pVM, pVM->pad, 1); 289*ca987d46SWarner Losh } 290*ca987d46SWarner Losh 291*ca987d46SWarner Losh vmTextOut(pVM, ";", 1); 292*ca987d46SWarner Losh } 293*ca987d46SWarner Losh 294*ca987d46SWarner Losh /* 295*ca987d46SWarner Losh ** Here's the outer part of the decompiler. It's 296*ca987d46SWarner Losh ** just a big nested conditional that checks the 297*ca987d46SWarner Losh ** CFA of the word to decompile for each kind of 298*ca987d46SWarner Losh ** known word-builder code, and tries to do 299*ca987d46SWarner Losh ** something appropriate. If the CFA is not recognized, 300*ca987d46SWarner Losh ** just indicate that it is a primitive. 301*ca987d46SWarner Losh */ 302*ca987d46SWarner Losh static void seeXT(FICL_VM *pVM) 303*ca987d46SWarner Losh { 304*ca987d46SWarner Losh FICL_WORD *pFW; 305*ca987d46SWarner Losh WORDKIND kind; 306*ca987d46SWarner Losh 307*ca987d46SWarner Losh pFW = (FICL_WORD *)stackPopPtr(pVM->pStack); 308*ca987d46SWarner Losh kind = ficlWordClassify(pFW); 309*ca987d46SWarner Losh 310*ca987d46SWarner Losh switch (kind) 311*ca987d46SWarner Losh { 312*ca987d46SWarner Losh case COLON: 313*ca987d46SWarner Losh sprintf(pVM->pad, ": %.*s", pFW->nName, pFW->name); 314*ca987d46SWarner Losh vmTextOut(pVM, pVM->pad, 1); 315*ca987d46SWarner Losh seeColon(pVM, pFW->param); 316*ca987d46SWarner Losh break; 317*ca987d46SWarner Losh 318*ca987d46SWarner Losh case DOES: 319*ca987d46SWarner Losh vmTextOut(pVM, "does>", 1); 320*ca987d46SWarner Losh seeColon(pVM, (CELL *)pFW->param->p); 321*ca987d46SWarner Losh break; 322*ca987d46SWarner Losh 323*ca987d46SWarner Losh case CREATE: 324*ca987d46SWarner Losh vmTextOut(pVM, "create", 1); 325*ca987d46SWarner Losh break; 326*ca987d46SWarner Losh 327*ca987d46SWarner Losh case VARIABLE: 328*ca987d46SWarner Losh sprintf(pVM->pad, "variable = %ld (%#lx)", 329*ca987d46SWarner Losh (long)pFW->param->i, (unsigned long)pFW->param->u); 330*ca987d46SWarner Losh vmTextOut(pVM, pVM->pad, 1); 331*ca987d46SWarner Losh break; 332*ca987d46SWarner Losh 333*ca987d46SWarner Losh #if FICL_WANT_USER 334*ca987d46SWarner Losh case USER: 335*ca987d46SWarner Losh sprintf(pVM->pad, "user variable %ld (%#lx)", 336*ca987d46SWarner Losh (long)pFW->param->i, (unsigned long)pFW->param->u); 337*ca987d46SWarner Losh vmTextOut(pVM, pVM->pad, 1); 338*ca987d46SWarner Losh break; 339*ca987d46SWarner Losh #endif 340*ca987d46SWarner Losh 341*ca987d46SWarner Losh case CONSTANT: 342*ca987d46SWarner Losh sprintf(pVM->pad, "constant = %ld (%#lx)", 343*ca987d46SWarner Losh (long)pFW->param->i, (unsigned long)pFW->param->u); 344*ca987d46SWarner Losh vmTextOut(pVM, pVM->pad, 1); 345*ca987d46SWarner Losh 346*ca987d46SWarner Losh default: 347*ca987d46SWarner Losh sprintf(pVM->pad, "%.*s is a primitive", pFW->nName, pFW->name); 348*ca987d46SWarner Losh vmTextOut(pVM, pVM->pad, 1); 349*ca987d46SWarner Losh break; 350*ca987d46SWarner Losh } 351*ca987d46SWarner Losh 352*ca987d46SWarner Losh if (pFW->flags & FW_IMMEDIATE) 353*ca987d46SWarner Losh { 354*ca987d46SWarner Losh vmTextOut(pVM, "immediate", 1); 355*ca987d46SWarner Losh } 356*ca987d46SWarner Losh 357*ca987d46SWarner Losh if (pFW->flags & FW_COMPILE) 358*ca987d46SWarner Losh { 359*ca987d46SWarner Losh vmTextOut(pVM, "compile-only", 1); 360*ca987d46SWarner Losh } 361*ca987d46SWarner Losh 362*ca987d46SWarner Losh return; 363*ca987d46SWarner Losh } 364*ca987d46SWarner Losh 365*ca987d46SWarner Losh 366*ca987d46SWarner Losh static void see(FICL_VM *pVM) 367*ca987d46SWarner Losh { 368*ca987d46SWarner Losh ficlTick(pVM); 369*ca987d46SWarner Losh seeXT(pVM); 370*ca987d46SWarner Losh return; 371*ca987d46SWarner Losh } 372*ca987d46SWarner Losh 373*ca987d46SWarner Losh 374*ca987d46SWarner Losh /************************************************************************** 375*ca987d46SWarner Losh f i c l D e b u g X T 376*ca987d46SWarner Losh ** debug ( xt -- ) 377*ca987d46SWarner Losh ** Given an xt of a colon definition or a word defined by DOES>, set the 378*ca987d46SWarner Losh ** VM up to debug the word: push IP, set the xt as the next thing to execute, 379*ca987d46SWarner Losh ** set a breakpoint at its first instruction, and run to the breakpoint. 380*ca987d46SWarner Losh ** Note: the semantics of this word are equivalent to "step in" 381*ca987d46SWarner Losh **************************************************************************/ 382*ca987d46SWarner Losh void ficlDebugXT(FICL_VM *pVM) 383*ca987d46SWarner Losh { 384*ca987d46SWarner Losh FICL_WORD *xt = stackPopPtr(pVM->pStack); 385*ca987d46SWarner Losh WORDKIND wk = ficlWordClassify(xt); 386*ca987d46SWarner Losh 387*ca987d46SWarner Losh stackPushPtr(pVM->pStack, xt); 388*ca987d46SWarner Losh seeXT(pVM); 389*ca987d46SWarner Losh 390*ca987d46SWarner Losh switch (wk) 391*ca987d46SWarner Losh { 392*ca987d46SWarner Losh case COLON: 393*ca987d46SWarner Losh case DOES: 394*ca987d46SWarner Losh /* 395*ca987d46SWarner Losh ** Run the colon code and set a breakpoint at the next instruction 396*ca987d46SWarner Losh */ 397*ca987d46SWarner Losh vmExecute(pVM, xt); 398*ca987d46SWarner Losh vmSetBreak(pVM, &(pVM->pSys->bpStep)); 399*ca987d46SWarner Losh break; 400*ca987d46SWarner Losh 401*ca987d46SWarner Losh default: 402*ca987d46SWarner Losh vmExecute(pVM, xt); 403*ca987d46SWarner Losh break; 404*ca987d46SWarner Losh } 405*ca987d46SWarner Losh 406*ca987d46SWarner Losh return; 407*ca987d46SWarner Losh } 408*ca987d46SWarner Losh 409*ca987d46SWarner Losh 410*ca987d46SWarner Losh /************************************************************************** 411*ca987d46SWarner Losh s t e p I n 412*ca987d46SWarner Losh ** FICL 413*ca987d46SWarner Losh ** Execute the next instruction, stepping into it if it's a colon definition 414*ca987d46SWarner Losh ** or a does> word. This is the easy kind of step. 415*ca987d46SWarner Losh **************************************************************************/ 416*ca987d46SWarner Losh void stepIn(FICL_VM *pVM) 417*ca987d46SWarner Losh { 418*ca987d46SWarner Losh /* 419*ca987d46SWarner Losh ** Do one step of the inner loop 420*ca987d46SWarner Losh */ 421*ca987d46SWarner Losh { 422*ca987d46SWarner Losh M_VM_STEP(pVM) 423*ca987d46SWarner Losh } 424*ca987d46SWarner Losh 425*ca987d46SWarner Losh /* 426*ca987d46SWarner Losh ** Now set a breakpoint at the next instruction 427*ca987d46SWarner Losh */ 428*ca987d46SWarner Losh vmSetBreak(pVM, &(pVM->pSys->bpStep)); 429*ca987d46SWarner Losh 430*ca987d46SWarner Losh return; 431*ca987d46SWarner Losh } 432*ca987d46SWarner Losh 433*ca987d46SWarner Losh 434*ca987d46SWarner Losh /************************************************************************** 435*ca987d46SWarner Losh s t e p O v e r 436*ca987d46SWarner Losh ** FICL 437*ca987d46SWarner Losh ** Execute the next instruction atomically. This requires some insight into 438*ca987d46SWarner Losh ** the memory layout of compiled code. Set a breakpoint at the next instruction 439*ca987d46SWarner Losh ** in this word, and run until we hit it 440*ca987d46SWarner Losh **************************************************************************/ 441*ca987d46SWarner Losh void stepOver(FICL_VM *pVM) 442*ca987d46SWarner Losh { 443*ca987d46SWarner Losh FICL_WORD *pFW; 444*ca987d46SWarner Losh WORDKIND kind; 445*ca987d46SWarner Losh FICL_WORD *pStep = ficlLookup(pVM->pSys, "step-break"); 446*ca987d46SWarner Losh assert(pStep); 447*ca987d46SWarner Losh 448*ca987d46SWarner Losh pFW = *pVM->ip; 449*ca987d46SWarner Losh kind = ficlWordClassify(pFW); 450*ca987d46SWarner Losh 451*ca987d46SWarner Losh switch (kind) 452*ca987d46SWarner Losh { 453*ca987d46SWarner Losh case COLON: 454*ca987d46SWarner Losh case DOES: 455*ca987d46SWarner Losh /* 456*ca987d46SWarner Losh ** assume that the next cell holds an instruction 457*ca987d46SWarner Losh ** set a breakpoint there and return to the inner interp 458*ca987d46SWarner Losh */ 459*ca987d46SWarner Losh pVM->pSys->bpStep.address = pVM->ip + 1; 460*ca987d46SWarner Losh pVM->pSys->bpStep.origXT = pVM->ip[1]; 461*ca987d46SWarner Losh pVM->ip[1] = pStep; 462*ca987d46SWarner Losh break; 463*ca987d46SWarner Losh 464*ca987d46SWarner Losh default: 465*ca987d46SWarner Losh stepIn(pVM); 466*ca987d46SWarner Losh break; 467*ca987d46SWarner Losh } 468*ca987d46SWarner Losh 469*ca987d46SWarner Losh return; 470*ca987d46SWarner Losh } 471*ca987d46SWarner Losh 472*ca987d46SWarner Losh 473*ca987d46SWarner Losh /************************************************************************** 474*ca987d46SWarner Losh s t e p - b r e a k 475*ca987d46SWarner Losh ** FICL 476*ca987d46SWarner Losh ** Handles breakpoints for stepped execution. 477*ca987d46SWarner Losh ** Upon entry, bpStep contains the address and replaced instruction 478*ca987d46SWarner Losh ** of the current breakpoint. 479*ca987d46SWarner Losh ** Clear the breakpoint 480*ca987d46SWarner Losh ** Get a command from the console. 481*ca987d46SWarner Losh ** i (step in) - execute the current instruction and set a new breakpoint 482*ca987d46SWarner Losh ** at the IP 483*ca987d46SWarner Losh ** o (step over) - execute the current instruction to completion and set 484*ca987d46SWarner Losh ** a new breakpoint at the IP 485*ca987d46SWarner Losh ** g (go) - execute the current instruction and exit 486*ca987d46SWarner Losh ** q (quit) - abort current word 487*ca987d46SWarner Losh ** b (toggle breakpoint) 488*ca987d46SWarner Losh **************************************************************************/ 489*ca987d46SWarner Losh void stepBreak(FICL_VM *pVM) 490*ca987d46SWarner Losh { 491*ca987d46SWarner Losh STRINGINFO si; 492*ca987d46SWarner Losh FICL_WORD *pFW; 493*ca987d46SWarner Losh FICL_WORD *pOnStep; 494*ca987d46SWarner Losh 495*ca987d46SWarner Losh if (!pVM->fRestart) 496*ca987d46SWarner Losh { 497*ca987d46SWarner Losh assert(pVM->pSys->bpStep.address); 498*ca987d46SWarner Losh assert(pVM->pSys->bpStep.origXT); 499*ca987d46SWarner Losh /* 500*ca987d46SWarner Losh ** Clear the breakpoint that caused me to run 501*ca987d46SWarner Losh ** Restore the original instruction at the breakpoint, 502*ca987d46SWarner Losh ** and restore the IP 503*ca987d46SWarner Losh */ 504*ca987d46SWarner Losh pVM->ip = (IPTYPE)(pVM->pSys->bpStep.address); 505*ca987d46SWarner Losh *pVM->ip = pVM->pSys->bpStep.origXT; 506*ca987d46SWarner Losh 507*ca987d46SWarner Losh /* 508*ca987d46SWarner Losh ** If there's an onStep, do it 509*ca987d46SWarner Losh */ 510*ca987d46SWarner Losh pOnStep = ficlLookup(pVM->pSys, "on-step"); 511*ca987d46SWarner Losh if (pOnStep) 512*ca987d46SWarner Losh ficlExecXT(pVM, pOnStep); 513*ca987d46SWarner Losh 514*ca987d46SWarner Losh /* 515*ca987d46SWarner Losh ** Print the name of the next instruction 516*ca987d46SWarner Losh */ 517*ca987d46SWarner Losh pFW = pVM->pSys->bpStep.origXT; 518*ca987d46SWarner Losh sprintf(pVM->pad, "next: %.*s", pFW->nName, pFW->name); 519*ca987d46SWarner Losh #if 0 520*ca987d46SWarner Losh if (isPrimitive(pFW)) 521*ca987d46SWarner Losh { 522*ca987d46SWarner Losh strcat(pVM->pad, " ( primitive )"); 523*ca987d46SWarner Losh } 524*ca987d46SWarner Losh #endif 525*ca987d46SWarner Losh 526*ca987d46SWarner Losh vmTextOut(pVM, pVM->pad, 1); 527*ca987d46SWarner Losh debugPrompt(pVM); 528*ca987d46SWarner Losh } 529*ca987d46SWarner Losh else 530*ca987d46SWarner Losh { 531*ca987d46SWarner Losh pVM->fRestart = 0; 532*ca987d46SWarner Losh } 533*ca987d46SWarner Losh 534*ca987d46SWarner Losh si = vmGetWord(pVM); 535*ca987d46SWarner Losh 536*ca987d46SWarner Losh if (!strincmp(si.cp, "i", si.count)) 537*ca987d46SWarner Losh { 538*ca987d46SWarner Losh stepIn(pVM); 539*ca987d46SWarner Losh } 540*ca987d46SWarner Losh else if (!strincmp(si.cp, "g", si.count)) 541*ca987d46SWarner Losh { 542*ca987d46SWarner Losh return; 543*ca987d46SWarner Losh } 544*ca987d46SWarner Losh else if (!strincmp(si.cp, "l", si.count)) 545*ca987d46SWarner Losh { 546*ca987d46SWarner Losh FICL_WORD *xt; 547*ca987d46SWarner Losh xt = findEnclosingWord(pVM, (CELL *)(pVM->ip)); 548*ca987d46SWarner Losh if (xt) 549*ca987d46SWarner Losh { 550*ca987d46SWarner Losh stackPushPtr(pVM->pStack, xt); 551*ca987d46SWarner Losh seeXT(pVM); 552*ca987d46SWarner Losh } 553*ca987d46SWarner Losh else 554*ca987d46SWarner Losh { 555*ca987d46SWarner Losh vmTextOut(pVM, "sorry - can't do that", 1); 556*ca987d46SWarner Losh } 557*ca987d46SWarner Losh vmThrow(pVM, VM_RESTART); 558*ca987d46SWarner Losh } 559*ca987d46SWarner Losh else if (!strincmp(si.cp, "o", si.count)) 560*ca987d46SWarner Losh { 561*ca987d46SWarner Losh stepOver(pVM); 562*ca987d46SWarner Losh } 563*ca987d46SWarner Losh else if (!strincmp(si.cp, "q", si.count)) 564*ca987d46SWarner Losh { 565*ca987d46SWarner Losh ficlTextOut(pVM, FICL_PROMPT, 0); 566*ca987d46SWarner Losh vmThrow(pVM, VM_ABORT); 567*ca987d46SWarner Losh } 568*ca987d46SWarner Losh else if (!strincmp(si.cp, "x", si.count)) 569*ca987d46SWarner Losh { 570*ca987d46SWarner Losh /* 571*ca987d46SWarner Losh ** Take whatever's left in the TIB and feed it to a subordinate ficlExec 572*ca987d46SWarner Losh */ 573*ca987d46SWarner Losh int ret; 574*ca987d46SWarner Losh char *cp = pVM->tib.cp + pVM->tib.index; 575*ca987d46SWarner Losh int count = pVM->tib.end - cp; 576*ca987d46SWarner Losh FICL_WORD *oldRun = pVM->runningWord; 577*ca987d46SWarner Losh 578*ca987d46SWarner Losh ret = ficlExecC(pVM, cp, count); 579*ca987d46SWarner Losh 580*ca987d46SWarner Losh if (ret == VM_OUTOFTEXT) 581*ca987d46SWarner Losh { 582*ca987d46SWarner Losh ret = VM_RESTART; 583*ca987d46SWarner Losh pVM->runningWord = oldRun; 584*ca987d46SWarner Losh vmTextOut(pVM, "", 1); 585*ca987d46SWarner Losh } 586*ca987d46SWarner Losh 587*ca987d46SWarner Losh vmThrow(pVM, ret); 588*ca987d46SWarner Losh } 589*ca987d46SWarner Losh else 590*ca987d46SWarner Losh { 591*ca987d46SWarner Losh vmTextOut(pVM, "i -- step In", 1); 592*ca987d46SWarner Losh vmTextOut(pVM, "o -- step Over", 1); 593*ca987d46SWarner Losh vmTextOut(pVM, "g -- Go (execute to completion)", 1); 594*ca987d46SWarner Losh vmTextOut(pVM, "l -- List source code", 1); 595*ca987d46SWarner Losh vmTextOut(pVM, "q -- Quit (stop debugging and abort)", 1); 596*ca987d46SWarner Losh vmTextOut(pVM, "x -- eXecute the rest of the line as ficl words", 1); 597*ca987d46SWarner Losh debugPrompt(pVM); 598*ca987d46SWarner Losh vmThrow(pVM, VM_RESTART); 599*ca987d46SWarner Losh } 600*ca987d46SWarner Losh 601*ca987d46SWarner Losh return; 602*ca987d46SWarner Losh } 603*ca987d46SWarner Losh 604*ca987d46SWarner Losh 605*ca987d46SWarner Losh /************************************************************************** 606*ca987d46SWarner Losh b y e 607*ca987d46SWarner Losh ** TOOLS 608*ca987d46SWarner Losh ** Signal the system to shut down - this causes ficlExec to return 609*ca987d46SWarner Losh ** VM_USEREXIT. The rest is up to you. 610*ca987d46SWarner Losh **************************************************************************/ 611*ca987d46SWarner Losh static void bye(FICL_VM *pVM) 612*ca987d46SWarner Losh { 613*ca987d46SWarner Losh vmThrow(pVM, VM_USEREXIT); 614*ca987d46SWarner Losh return; 615*ca987d46SWarner Losh } 616*ca987d46SWarner Losh 617*ca987d46SWarner Losh 618*ca987d46SWarner Losh /************************************************************************** 619*ca987d46SWarner Losh d i s p l a y S t a c k 620*ca987d46SWarner Losh ** TOOLS 621*ca987d46SWarner Losh ** Display the parameter stack (code for ".s") 622*ca987d46SWarner Losh **************************************************************************/ 623*ca987d46SWarner Losh static void displayPStack(FICL_VM *pVM) 624*ca987d46SWarner Losh { 625*ca987d46SWarner Losh FICL_STACK *pStk = pVM->pStack; 626*ca987d46SWarner Losh int d = stackDepth(pStk); 627*ca987d46SWarner Losh int i; 628*ca987d46SWarner Losh CELL *pCell; 629*ca987d46SWarner Losh 630*ca987d46SWarner Losh vmCheckStack(pVM, 0, 0); 631*ca987d46SWarner Losh 632*ca987d46SWarner Losh if (d == 0) 633*ca987d46SWarner Losh vmTextOut(pVM, "(Stack Empty) ", 0); 634*ca987d46SWarner Losh else 635*ca987d46SWarner Losh { 636*ca987d46SWarner Losh pCell = pStk->base; 637*ca987d46SWarner Losh for (i = 0; i < d; i++) 638*ca987d46SWarner Losh { 639*ca987d46SWarner Losh vmTextOut(pVM, ltoa((*pCell++).i, pVM->pad, pVM->base), 0); 640*ca987d46SWarner Losh vmTextOut(pVM, " ", 0); 641*ca987d46SWarner Losh } 642*ca987d46SWarner Losh } 643*ca987d46SWarner Losh return; 644*ca987d46SWarner Losh } 645*ca987d46SWarner Losh 646*ca987d46SWarner Losh 647*ca987d46SWarner Losh static void displayRStack(FICL_VM *pVM) 648*ca987d46SWarner Losh { 649*ca987d46SWarner Losh FICL_STACK *pStk = pVM->rStack; 650*ca987d46SWarner Losh int d = stackDepth(pStk); 651*ca987d46SWarner Losh int i; 652*ca987d46SWarner Losh CELL *pCell; 653*ca987d46SWarner Losh FICL_DICT *dp = vmGetDict(pVM); 654*ca987d46SWarner Losh 655*ca987d46SWarner Losh vmCheckStack(pVM, 0, 0); 656*ca987d46SWarner Losh 657*ca987d46SWarner Losh if (d == 0) 658*ca987d46SWarner Losh vmTextOut(pVM, "(Stack Empty) ", 0); 659*ca987d46SWarner Losh else 660*ca987d46SWarner Losh { 661*ca987d46SWarner Losh pCell = pStk->base; 662*ca987d46SWarner Losh for (i = 0; i < d; i++) 663*ca987d46SWarner Losh { 664*ca987d46SWarner Losh CELL c = *pCell++; 665*ca987d46SWarner Losh /* 666*ca987d46SWarner Losh ** Attempt to find the word that contains the 667*ca987d46SWarner Losh ** stacked address (as if it is part of a colon definition). 668*ca987d46SWarner Losh ** If this works, print the name of the word. Otherwise print 669*ca987d46SWarner Losh ** the value as a number. 670*ca987d46SWarner Losh */ 671*ca987d46SWarner Losh if (dictIncludes(dp, c.p)) 672*ca987d46SWarner Losh { 673*ca987d46SWarner Losh FICL_WORD *pFW = findEnclosingWord(pVM, c.p); 674*ca987d46SWarner Losh if (pFW) 675*ca987d46SWarner Losh { 676*ca987d46SWarner Losh int offset = (CELL *)c.p - &pFW->param[0]; 677*ca987d46SWarner Losh sprintf(pVM->pad, "%s+%d ", pFW->name, offset); 678*ca987d46SWarner Losh vmTextOut(pVM, pVM->pad, 0); 679*ca987d46SWarner Losh continue; /* no need to print the numeric value */ 680*ca987d46SWarner Losh } 681*ca987d46SWarner Losh } 682*ca987d46SWarner Losh vmTextOut(pVM, ltoa(c.i, pVM->pad, pVM->base), 0); 683*ca987d46SWarner Losh vmTextOut(pVM, " ", 0); 684*ca987d46SWarner Losh } 685*ca987d46SWarner Losh } 686*ca987d46SWarner Losh 687*ca987d46SWarner Losh return; 688*ca987d46SWarner Losh } 689*ca987d46SWarner Losh 690*ca987d46SWarner Losh 691*ca987d46SWarner Losh /************************************************************************** 692*ca987d46SWarner Losh f o r g e t - w i d 693*ca987d46SWarner Losh ** 694*ca987d46SWarner Losh **************************************************************************/ 695*ca987d46SWarner Losh static void forgetWid(FICL_VM *pVM) 696*ca987d46SWarner Losh { 697*ca987d46SWarner Losh FICL_DICT *pDict = vmGetDict(pVM); 698*ca987d46SWarner Losh FICL_HASH *pHash; 699*ca987d46SWarner Losh 700*ca987d46SWarner Losh pHash = (FICL_HASH *)stackPopPtr(pVM->pStack); 701*ca987d46SWarner Losh hashForget(pHash, pDict->here); 702*ca987d46SWarner Losh 703*ca987d46SWarner Losh return; 704*ca987d46SWarner Losh } 705*ca987d46SWarner Losh 706*ca987d46SWarner Losh 707*ca987d46SWarner Losh /************************************************************************** 708*ca987d46SWarner Losh f o r g e t 709*ca987d46SWarner Losh ** TOOLS EXT ( "<spaces>name" -- ) 710*ca987d46SWarner Losh ** Skip leading space delimiters. Parse name delimited by a space. 711*ca987d46SWarner Losh ** Find name, then delete name from the dictionary along with all 712*ca987d46SWarner Losh ** words added to the dictionary after name. An ambiguous 713*ca987d46SWarner Losh ** condition exists if name cannot be found. 714*ca987d46SWarner Losh ** 715*ca987d46SWarner Losh ** If the Search-Order word set is present, FORGET searches the 716*ca987d46SWarner Losh ** compilation word list. An ambiguous condition exists if the 717*ca987d46SWarner Losh ** compilation word list is deleted. 718*ca987d46SWarner Losh **************************************************************************/ 719*ca987d46SWarner Losh static void forget(FICL_VM *pVM) 720*ca987d46SWarner Losh { 721*ca987d46SWarner Losh void *where; 722*ca987d46SWarner Losh FICL_DICT *pDict = vmGetDict(pVM); 723*ca987d46SWarner Losh FICL_HASH *pHash = pDict->pCompile; 724*ca987d46SWarner Losh 725*ca987d46SWarner Losh ficlTick(pVM); 726*ca987d46SWarner Losh where = ((FICL_WORD *)stackPopPtr(pVM->pStack))->name; 727*ca987d46SWarner Losh hashForget(pHash, where); 728*ca987d46SWarner Losh pDict->here = PTRtoCELL where; 729*ca987d46SWarner Losh 730*ca987d46SWarner Losh return; 731*ca987d46SWarner Losh } 732*ca987d46SWarner Losh 733*ca987d46SWarner Losh 734*ca987d46SWarner Losh /************************************************************************** 735*ca987d46SWarner Losh l i s t W o r d s 736*ca987d46SWarner Losh ** 737*ca987d46SWarner Losh **************************************************************************/ 738*ca987d46SWarner Losh #define nCOLWIDTH 8 739*ca987d46SWarner Losh static void listWords(FICL_VM *pVM) 740*ca987d46SWarner Losh { 741*ca987d46SWarner Losh FICL_DICT *dp = vmGetDict(pVM); 742*ca987d46SWarner Losh FICL_HASH *pHash = dp->pSearch[dp->nLists - 1]; 743*ca987d46SWarner Losh FICL_WORD *wp; 744*ca987d46SWarner Losh int nChars = 0; 745*ca987d46SWarner Losh int len; 746*ca987d46SWarner Losh int y = 0; 747*ca987d46SWarner Losh unsigned i; 748*ca987d46SWarner Losh int nWords = 0; 749*ca987d46SWarner Losh char *cp; 750*ca987d46SWarner Losh char *pPad = pVM->pad; 751*ca987d46SWarner Losh 752*ca987d46SWarner Losh for (i = 0; i < pHash->size; i++) 753*ca987d46SWarner Losh { 754*ca987d46SWarner Losh for (wp = pHash->table[i]; wp != NULL; wp = wp->link, nWords++) 755*ca987d46SWarner Losh { 756*ca987d46SWarner Losh if (wp->nName == 0) /* ignore :noname defs */ 757*ca987d46SWarner Losh continue; 758*ca987d46SWarner Losh 759*ca987d46SWarner Losh cp = wp->name; 760*ca987d46SWarner Losh nChars += sprintf(pPad + nChars, "%s", cp); 761*ca987d46SWarner Losh 762*ca987d46SWarner Losh if (nChars > 70) 763*ca987d46SWarner Losh { 764*ca987d46SWarner Losh pPad[nChars] = '\0'; 765*ca987d46SWarner Losh nChars = 0; 766*ca987d46SWarner Losh y++; 767*ca987d46SWarner Losh if(y>23) { 768*ca987d46SWarner Losh y=0; 769*ca987d46SWarner Losh vmTextOut(pVM, "--- Press Enter to continue ---",0); 770*ca987d46SWarner Losh getchar(); 771*ca987d46SWarner Losh vmTextOut(pVM,"\r",0); 772*ca987d46SWarner Losh } 773*ca987d46SWarner Losh vmTextOut(pVM, pPad, 1); 774*ca987d46SWarner Losh } 775*ca987d46SWarner Losh else 776*ca987d46SWarner Losh { 777*ca987d46SWarner Losh len = nCOLWIDTH - nChars % nCOLWIDTH; 778*ca987d46SWarner Losh while (len-- > 0) 779*ca987d46SWarner Losh pPad[nChars++] = ' '; 780*ca987d46SWarner Losh } 781*ca987d46SWarner Losh 782*ca987d46SWarner Losh if (nChars > 70) 783*ca987d46SWarner Losh { 784*ca987d46SWarner Losh pPad[nChars] = '\0'; 785*ca987d46SWarner Losh nChars = 0; 786*ca987d46SWarner Losh y++; 787*ca987d46SWarner Losh if(y>23) { 788*ca987d46SWarner Losh y=0; 789*ca987d46SWarner Losh vmTextOut(pVM, "--- Press Enter to continue ---",0); 790*ca987d46SWarner Losh getchar(); 791*ca987d46SWarner Losh vmTextOut(pVM,"\r",0); 792*ca987d46SWarner Losh } 793*ca987d46SWarner Losh vmTextOut(pVM, pPad, 1); 794*ca987d46SWarner Losh } 795*ca987d46SWarner Losh } 796*ca987d46SWarner Losh } 797*ca987d46SWarner Losh 798*ca987d46SWarner Losh if (nChars > 0) 799*ca987d46SWarner Losh { 800*ca987d46SWarner Losh pPad[nChars] = '\0'; 801*ca987d46SWarner Losh nChars = 0; 802*ca987d46SWarner Losh vmTextOut(pVM, pPad, 1); 803*ca987d46SWarner Losh } 804*ca987d46SWarner Losh 805*ca987d46SWarner Losh sprintf(pVM->pad, "Dictionary: %d words, %ld cells used of %u total", 806*ca987d46SWarner Losh nWords, (long) (dp->here - dp->dict), dp->size); 807*ca987d46SWarner Losh vmTextOut(pVM, pVM->pad, 1); 808*ca987d46SWarner Losh return; 809*ca987d46SWarner Losh } 810*ca987d46SWarner Losh 811*ca987d46SWarner Losh 812*ca987d46SWarner Losh /************************************************************************** 813*ca987d46SWarner Losh l i s t E n v 814*ca987d46SWarner Losh ** Print symbols defined in the environment 815*ca987d46SWarner Losh **************************************************************************/ 816*ca987d46SWarner Losh static void listEnv(FICL_VM *pVM) 817*ca987d46SWarner Losh { 818*ca987d46SWarner Losh FICL_DICT *dp = pVM->pSys->envp; 819*ca987d46SWarner Losh FICL_HASH *pHash = dp->pForthWords; 820*ca987d46SWarner Losh FICL_WORD *wp; 821*ca987d46SWarner Losh unsigned i; 822*ca987d46SWarner Losh int nWords = 0; 823*ca987d46SWarner Losh 824*ca987d46SWarner Losh for (i = 0; i < pHash->size; i++) 825*ca987d46SWarner Losh { 826*ca987d46SWarner Losh for (wp = pHash->table[i]; wp != NULL; wp = wp->link, nWords++) 827*ca987d46SWarner Losh { 828*ca987d46SWarner Losh vmTextOut(pVM, wp->name, 1); 829*ca987d46SWarner Losh } 830*ca987d46SWarner Losh } 831*ca987d46SWarner Losh 832*ca987d46SWarner Losh sprintf(pVM->pad, "Environment: %d words, %ld cells used of %u total", 833*ca987d46SWarner Losh nWords, (long) (dp->here - dp->dict), dp->size); 834*ca987d46SWarner Losh vmTextOut(pVM, pVM->pad, 1); 835*ca987d46SWarner Losh return; 836*ca987d46SWarner Losh } 837*ca987d46SWarner Losh 838*ca987d46SWarner Losh 839*ca987d46SWarner Losh /************************************************************************** 840*ca987d46SWarner Losh e n v C o n s t a n t 841*ca987d46SWarner Losh ** Ficl interface to ficlSetEnv and ficlSetEnvD - allow ficl code to set 842*ca987d46SWarner Losh ** environment constants... 843*ca987d46SWarner Losh **************************************************************************/ 844*ca987d46SWarner Losh static void envConstant(FICL_VM *pVM) 845*ca987d46SWarner Losh { 846*ca987d46SWarner Losh unsigned value; 847*ca987d46SWarner Losh 848*ca987d46SWarner Losh #if FICL_ROBUST > 1 849*ca987d46SWarner Losh vmCheckStack(pVM, 1, 0); 850*ca987d46SWarner Losh #endif 851*ca987d46SWarner Losh 852*ca987d46SWarner Losh vmGetWordToPad(pVM); 853*ca987d46SWarner Losh value = POPUNS(); 854*ca987d46SWarner Losh ficlSetEnv(pVM->pSys, pVM->pad, (FICL_UNS)value); 855*ca987d46SWarner Losh return; 856*ca987d46SWarner Losh } 857*ca987d46SWarner Losh 858*ca987d46SWarner Losh static void env2Constant(FICL_VM *pVM) 859*ca987d46SWarner Losh { 860*ca987d46SWarner Losh unsigned v1, v2; 861*ca987d46SWarner Losh 862*ca987d46SWarner Losh #if FICL_ROBUST > 1 863*ca987d46SWarner Losh vmCheckStack(pVM, 2, 0); 864*ca987d46SWarner Losh #endif 865*ca987d46SWarner Losh 866*ca987d46SWarner Losh vmGetWordToPad(pVM); 867*ca987d46SWarner Losh v2 = POPUNS(); 868*ca987d46SWarner Losh v1 = POPUNS(); 869*ca987d46SWarner Losh ficlSetEnvD(pVM->pSys, pVM->pad, v1, v2); 870*ca987d46SWarner Losh return; 871*ca987d46SWarner Losh } 872*ca987d46SWarner Losh 873*ca987d46SWarner Losh 874*ca987d46SWarner Losh /************************************************************************** 875*ca987d46SWarner Losh f i c l C o m p i l e T o o l s 876*ca987d46SWarner Losh ** Builds wordset for debugger and TOOLS optional word set 877*ca987d46SWarner Losh **************************************************************************/ 878*ca987d46SWarner Losh 879*ca987d46SWarner Losh void ficlCompileTools(FICL_SYSTEM *pSys) 880*ca987d46SWarner Losh { 881*ca987d46SWarner Losh FICL_DICT *dp = pSys->dp; 882*ca987d46SWarner Losh assert (dp); 883*ca987d46SWarner Losh 884*ca987d46SWarner Losh /* 885*ca987d46SWarner Losh ** TOOLS and TOOLS EXT 886*ca987d46SWarner Losh */ 887*ca987d46SWarner Losh dictAppendWord(dp, ".s", displayPStack, FW_DEFAULT); 888*ca987d46SWarner Losh dictAppendWord(dp, "bye", bye, FW_DEFAULT); 889*ca987d46SWarner Losh dictAppendWord(dp, "forget", forget, FW_DEFAULT); 890*ca987d46SWarner Losh dictAppendWord(dp, "see", see, FW_DEFAULT); 891*ca987d46SWarner Losh dictAppendWord(dp, "words", listWords, FW_DEFAULT); 892*ca987d46SWarner Losh 893*ca987d46SWarner Losh /* 894*ca987d46SWarner Losh ** Set TOOLS environment query values 895*ca987d46SWarner Losh */ 896*ca987d46SWarner Losh ficlSetEnv(pSys, "tools", FICL_TRUE); 897*ca987d46SWarner Losh ficlSetEnv(pSys, "tools-ext", FICL_FALSE); 898*ca987d46SWarner Losh 899*ca987d46SWarner Losh /* 900*ca987d46SWarner Losh ** Ficl extras 901*ca987d46SWarner Losh */ 902*ca987d46SWarner Losh dictAppendWord(dp, "r.s", displayRStack, FW_DEFAULT); /* guy carver */ 903*ca987d46SWarner Losh dictAppendWord(dp, ".env", listEnv, FW_DEFAULT); 904*ca987d46SWarner Losh dictAppendWord(dp, "env-constant", 905*ca987d46SWarner Losh envConstant, FW_DEFAULT); 906*ca987d46SWarner Losh dictAppendWord(dp, "env-2constant", 907*ca987d46SWarner Losh env2Constant, FW_DEFAULT); 908*ca987d46SWarner Losh dictAppendWord(dp, "debug-xt", ficlDebugXT, FW_DEFAULT); 909*ca987d46SWarner Losh dictAppendWord(dp, "parse-order", 910*ca987d46SWarner Losh ficlListParseSteps, 911*ca987d46SWarner Losh FW_DEFAULT); 912*ca987d46SWarner Losh dictAppendWord(dp, "step-break",stepBreak, FW_DEFAULT); 913*ca987d46SWarner Losh dictAppendWord(dp, "forget-wid",forgetWid, FW_DEFAULT); 914*ca987d46SWarner Losh dictAppendWord(dp, "see-xt", seeXT, FW_DEFAULT); 915*ca987d46SWarner Losh 916*ca987d46SWarner Losh return; 917*ca987d46SWarner Losh } 918*ca987d46SWarner Losh 919