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