xref: /freebsd/stand/ficl/words.c (revision 2a63c3be158216222d89a073dcbd6a72ee4aab5a)
1ca987d46SWarner Losh /*******************************************************************
2ca987d46SWarner Losh ** w o r d s . c
3ca987d46SWarner Losh ** Forth Inspired Command Language
4ca987d46SWarner Losh ** ANS Forth CORE word-set written in C
5ca987d46SWarner Losh ** Author: John Sadler (john_sadler@alum.mit.edu)
6ca987d46SWarner Losh ** Created: 19 July 1997
7ca987d46SWarner Losh ** $Id: words.c,v 1.17 2001/12/05 07:21:34 jsadler Exp $
8ca987d46SWarner Losh *******************************************************************/
9ca987d46SWarner Losh /*
10ca987d46SWarner Losh ** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
11ca987d46SWarner Losh ** All rights reserved.
12ca987d46SWarner Losh **
13ca987d46SWarner Losh ** Get the latest Ficl release at http://ficl.sourceforge.net
14ca987d46SWarner Losh **
15ca987d46SWarner Losh ** I am interested in hearing from anyone who uses ficl. If you have
16ca987d46SWarner Losh ** a problem, a success story, a defect, an enhancement request, or
17ca987d46SWarner Losh ** if you would like to contribute to the ficl release, please
18ca987d46SWarner Losh ** contact me by email at the address above.
19ca987d46SWarner Losh **
20ca987d46SWarner Losh ** L I C E N S E  and  D I S C L A I M E R
21ca987d46SWarner Losh **
22ca987d46SWarner Losh ** Redistribution and use in source and binary forms, with or without
23ca987d46SWarner Losh ** modification, are permitted provided that the following conditions
24ca987d46SWarner Losh ** are met:
25ca987d46SWarner Losh ** 1. Redistributions of source code must retain the above copyright
26ca987d46SWarner Losh **    notice, this list of conditions and the following disclaimer.
27ca987d46SWarner Losh ** 2. Redistributions in binary form must reproduce the above copyright
28ca987d46SWarner Losh **    notice, this list of conditions and the following disclaimer in the
29ca987d46SWarner Losh **    documentation and/or other materials provided with the distribution.
30ca987d46SWarner Losh **
31ca987d46SWarner Losh ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
32ca987d46SWarner Losh ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33ca987d46SWarner Losh ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34ca987d46SWarner Losh ** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
35ca987d46SWarner Losh ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36ca987d46SWarner Losh ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37ca987d46SWarner Losh ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38ca987d46SWarner Losh ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39ca987d46SWarner Losh ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40ca987d46SWarner Losh ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41ca987d46SWarner Losh ** SUCH DAMAGE.
42ca987d46SWarner Losh */
43ca987d46SWarner Losh 
44ca987d46SWarner Losh 
45ca987d46SWarner Losh #ifdef TESTMAIN
46ca987d46SWarner Losh #include <stdlib.h>
47ca987d46SWarner Losh #include <stdio.h>
48ca987d46SWarner Losh #include <ctype.h>
49ca987d46SWarner Losh #include <fcntl.h>
50ca987d46SWarner Losh #else
51ca987d46SWarner Losh #include <stand.h>
52ca987d46SWarner Losh #endif
53ca987d46SWarner Losh #include <string.h>
54ca987d46SWarner Losh #include "ficl.h"
55ca987d46SWarner Losh #include "math64.h"
56ca987d46SWarner Losh 
57ca987d46SWarner Losh static void colonParen(FICL_VM *pVM);
58ca987d46SWarner Losh static void literalIm(FICL_VM *pVM);
59ca987d46SWarner Losh static int  ficlParseWord(FICL_VM *pVM, STRINGINFO si);
60ca987d46SWarner Losh 
61ca987d46SWarner Losh /*
62ca987d46SWarner Losh ** Control structure building words use these
63ca987d46SWarner Losh ** strings' addresses as markers on the stack to
64ca987d46SWarner Losh ** check for structure completion.
65ca987d46SWarner Losh */
66ca987d46SWarner Losh static char doTag[]    = "do";
67ca987d46SWarner Losh static char colonTag[] = "colon";
68ca987d46SWarner Losh static char leaveTag[] = "leave";
69ca987d46SWarner Losh 
70ca987d46SWarner Losh static char destTag[]  = "target";
71ca987d46SWarner Losh static char origTag[]  = "origin";
72ca987d46SWarner Losh 
73ca987d46SWarner Losh static char caseTag[]  = "case";
74ca987d46SWarner Losh static char ofTag[]  = "of";
75ca987d46SWarner Losh static char fallthroughTag[]  = "fallthrough";
76ca987d46SWarner Losh 
77ca987d46SWarner Losh #if FICL_WANT_LOCALS
78ca987d46SWarner Losh static void doLocalIm(FICL_VM *pVM);
79ca987d46SWarner Losh static void do2LocalIm(FICL_VM *pVM);
80ca987d46SWarner Losh #endif
81ca987d46SWarner Losh 
82ca987d46SWarner Losh 
83ca987d46SWarner Losh /*
84ca987d46SWarner Losh ** C O N T R O L   S T R U C T U R E   B U I L D E R S
85ca987d46SWarner Losh **
86ca987d46SWarner Losh ** Push current dict location for later branch resolution.
87ca987d46SWarner Losh ** The location may be either a branch target or a patch address...
88ca987d46SWarner Losh */
markBranch(FICL_DICT * dp,FICL_VM * pVM,char * tag)89ca987d46SWarner Losh static void markBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag)
90ca987d46SWarner Losh {
91ca987d46SWarner Losh     PUSHPTR(dp->here);
92ca987d46SWarner Losh     PUSHPTR(tag);
93ca987d46SWarner Losh     return;
94ca987d46SWarner Losh }
95ca987d46SWarner Losh 
markControlTag(FICL_VM * pVM,char * tag)96ca987d46SWarner Losh static void markControlTag(FICL_VM *pVM, char *tag)
97ca987d46SWarner Losh {
98ca987d46SWarner Losh     PUSHPTR(tag);
99ca987d46SWarner Losh     return;
100ca987d46SWarner Losh }
101ca987d46SWarner Losh 
matchControlTag(FICL_VM * pVM,char * tag)102ca987d46SWarner Losh static void matchControlTag(FICL_VM *pVM, char *tag)
103ca987d46SWarner Losh {
104ca987d46SWarner Losh     char *cp;
105ca987d46SWarner Losh #if FICL_ROBUST > 1
106ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
107ca987d46SWarner Losh #endif
108ca987d46SWarner Losh     cp = (char *)stackPopPtr(pVM->pStack);
109ca987d46SWarner Losh     /*
110ca987d46SWarner Losh     ** Changed the code below to compare the pointers first (by popular demand)
111ca987d46SWarner Losh     */
112ca987d46SWarner Losh     if ( (cp != tag) && strcmp(cp, tag) )
113ca987d46SWarner Losh     {
114ca987d46SWarner Losh         vmThrowErr(pVM, "Error -- unmatched control structure \"%s\"", tag);
115ca987d46SWarner Losh     }
116ca987d46SWarner Losh 
117ca987d46SWarner Losh     return;
118ca987d46SWarner Losh }
119ca987d46SWarner Losh 
120ca987d46SWarner Losh /*
121ca987d46SWarner Losh ** Expect a branch target address on the param stack,
122ca987d46SWarner Losh ** compile a literal offset from the current dict location
123ca987d46SWarner Losh ** to the target address
124ca987d46SWarner Losh */
resolveBackBranch(FICL_DICT * dp,FICL_VM * pVM,char * tag)125ca987d46SWarner Losh static void resolveBackBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag)
126ca987d46SWarner Losh {
127ca987d46SWarner Losh     FICL_INT offset;
128ca987d46SWarner Losh     CELL *patchAddr;
129ca987d46SWarner Losh 
130ca987d46SWarner Losh     matchControlTag(pVM, tag);
131ca987d46SWarner Losh 
132ca987d46SWarner Losh #if FICL_ROBUST > 1
133ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
134ca987d46SWarner Losh #endif
135ca987d46SWarner Losh     patchAddr = (CELL *)stackPopPtr(pVM->pStack);
136ca987d46SWarner Losh     offset = patchAddr - dp->here;
137ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(offset));
138ca987d46SWarner Losh 
139ca987d46SWarner Losh     return;
140ca987d46SWarner Losh }
141ca987d46SWarner Losh 
142ca987d46SWarner Losh 
143ca987d46SWarner Losh /*
144ca987d46SWarner Losh ** Expect a branch patch address on the param stack,
145ca987d46SWarner Losh ** compile a literal offset from the patch location
146ca987d46SWarner Losh ** to the current dict location
147ca987d46SWarner Losh */
resolveForwardBranch(FICL_DICT * dp,FICL_VM * pVM,char * tag)148ca987d46SWarner Losh static void resolveForwardBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag)
149ca987d46SWarner Losh {
150ca987d46SWarner Losh     FICL_INT offset;
151ca987d46SWarner Losh     CELL *patchAddr;
152ca987d46SWarner Losh 
153ca987d46SWarner Losh     matchControlTag(pVM, tag);
154ca987d46SWarner Losh 
155ca987d46SWarner Losh #if FICL_ROBUST > 1
156ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
157ca987d46SWarner Losh #endif
158ca987d46SWarner Losh     patchAddr = (CELL *)stackPopPtr(pVM->pStack);
159ca987d46SWarner Losh     offset = dp->here - patchAddr;
160ca987d46SWarner Losh     *patchAddr = LVALUEtoCELL(offset);
161ca987d46SWarner Losh 
162ca987d46SWarner Losh     return;
163ca987d46SWarner Losh }
164ca987d46SWarner Losh 
165ca987d46SWarner Losh /*
166ca987d46SWarner Losh ** Match the tag to the top of the stack. If success,
167ca987d46SWarner Losh ** sopy "here" address into the cell whose address is next
168ca987d46SWarner Losh ** on the stack. Used by do..leave..loop.
169ca987d46SWarner Losh */
resolveAbsBranch(FICL_DICT * dp,FICL_VM * pVM,char * tag)170ca987d46SWarner Losh static void resolveAbsBranch(FICL_DICT *dp, FICL_VM *pVM, char *tag)
171ca987d46SWarner Losh {
172ca987d46SWarner Losh     CELL *patchAddr;
173ca987d46SWarner Losh     char *cp;
174ca987d46SWarner Losh 
175ca987d46SWarner Losh #if FICL_ROBUST > 1
176ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
177ca987d46SWarner Losh #endif
178ca987d46SWarner Losh     cp = stackPopPtr(pVM->pStack);
179ca987d46SWarner Losh     /*
180ca987d46SWarner Losh     ** Changed the comparison below to compare the pointers first (by popular demand)
181ca987d46SWarner Losh     */
182ca987d46SWarner Losh     if ((cp != tag) && strcmp(cp, tag))
183ca987d46SWarner Losh     {
184ca987d46SWarner Losh         vmTextOut(pVM, "Warning -- Unmatched control word: ", 0);
185ca987d46SWarner Losh         vmTextOut(pVM, tag, 1);
186ca987d46SWarner Losh     }
187ca987d46SWarner Losh 
188ca987d46SWarner Losh     patchAddr = (CELL *)stackPopPtr(pVM->pStack);
189ca987d46SWarner Losh     *patchAddr = LVALUEtoCELL(dp->here);
190ca987d46SWarner Losh 
191ca987d46SWarner Losh     return;
192ca987d46SWarner Losh }
193ca987d46SWarner Losh 
194ca987d46SWarner Losh 
195ca987d46SWarner Losh /**************************************************************************
196ca987d46SWarner Losh                         f i c l P a r s e N u m b e r
197ca987d46SWarner Losh ** Attempts to convert the NULL terminated string in the VM's pad to
198ca987d46SWarner Losh ** a number using the VM's current base. If successful, pushes the number
199ca987d46SWarner Losh ** onto the param stack and returns TRUE. Otherwise, returns FALSE.
200ca987d46SWarner Losh ** (jws 8/01) Trailing decimal point causes a zero cell to be pushed. (See
201ca987d46SWarner Losh ** the standard for DOUBLE wordset.
202ca987d46SWarner Losh **************************************************************************/
203ca987d46SWarner Losh 
ficlParseNumber(FICL_VM * pVM,STRINGINFO si)204ca987d46SWarner Losh int ficlParseNumber(FICL_VM *pVM, STRINGINFO si)
205ca987d46SWarner Losh {
206ca987d46SWarner Losh     FICL_INT accum  = 0;
207ca987d46SWarner Losh     char isNeg      = FALSE;
208ca987d46SWarner Losh 	char hasDP      = FALSE;
209ca987d46SWarner Losh     unsigned base   = pVM->base;
210ca987d46SWarner Losh     char *cp        = SI_PTR(si);
211ca987d46SWarner Losh     FICL_COUNT count= (FICL_COUNT)SI_COUNT(si);
212ca987d46SWarner Losh     unsigned ch;
213ca987d46SWarner Losh     unsigned digit;
214ca987d46SWarner Losh 
215ca987d46SWarner Losh     if (count > 1)
216ca987d46SWarner Losh     {
217ca987d46SWarner Losh         switch (*cp)
218ca987d46SWarner Losh         {
219ca987d46SWarner Losh         case '-':
220ca987d46SWarner Losh             cp++;
221ca987d46SWarner Losh             count--;
222ca987d46SWarner Losh             isNeg = TRUE;
223ca987d46SWarner Losh             break;
224ca987d46SWarner Losh         case '+':
225ca987d46SWarner Losh             cp++;
226ca987d46SWarner Losh             count--;
227ca987d46SWarner Losh             isNeg = FALSE;
228ca987d46SWarner Losh             break;
229ca987d46SWarner Losh         default:
230ca987d46SWarner Losh             break;
231ca987d46SWarner Losh         }
232ca987d46SWarner Losh     }
233ca987d46SWarner Losh 
234ca987d46SWarner Losh     if ((count > 0) && (cp[count-1] == '.')) /* detect & remove trailing decimal */
235ca987d46SWarner Losh     {
236ca987d46SWarner Losh         hasDP = TRUE;
237ca987d46SWarner Losh         count--;
238ca987d46SWarner Losh     }
239ca987d46SWarner Losh 
240ca987d46SWarner Losh     if (count == 0)        /* detect "+", "-", ".", "+." etc */
241ca987d46SWarner Losh         return FALSE;
242ca987d46SWarner Losh 
243ca987d46SWarner Losh     while ((count--) && ((ch = *cp++) != '\0'))
244ca987d46SWarner Losh     {
245ca987d46SWarner Losh         if (!isalnum(ch))
246ca987d46SWarner Losh             return FALSE;
247ca987d46SWarner Losh 
248ca987d46SWarner Losh         digit = ch - '0';
249ca987d46SWarner Losh 
250ca987d46SWarner Losh         if (digit > 9)
251ca987d46SWarner Losh             digit = tolower(ch) - 'a' + 10;
252ca987d46SWarner Losh 
253ca987d46SWarner Losh         if (digit >= base)
254ca987d46SWarner Losh             return FALSE;
255ca987d46SWarner Losh 
256ca987d46SWarner Losh         accum = accum * base + digit;
257ca987d46SWarner Losh     }
258ca987d46SWarner Losh 
259ca987d46SWarner Losh 	if (hasDP)		/* simple (required) DOUBLE support */
260ca987d46SWarner Losh 		PUSHINT(0);
261ca987d46SWarner Losh 
262ca987d46SWarner Losh     if (isNeg)
263ca987d46SWarner Losh         accum = -accum;
264ca987d46SWarner Losh 
265ca987d46SWarner Losh     PUSHINT(accum);
266ca987d46SWarner Losh     if (pVM->state == COMPILE)
267ca987d46SWarner Losh         literalIm(pVM);
268ca987d46SWarner Losh 
269ca987d46SWarner Losh     return TRUE;
270ca987d46SWarner Losh }
271ca987d46SWarner Losh 
272ca987d46SWarner Losh 
273ca987d46SWarner Losh /**************************************************************************
274ca987d46SWarner Losh                         a d d   &   f r i e n d s
275ca987d46SWarner Losh **
276ca987d46SWarner Losh **************************************************************************/
277ca987d46SWarner Losh 
add(FICL_VM * pVM)278ca987d46SWarner Losh static void add(FICL_VM *pVM)
279ca987d46SWarner Losh {
280ca987d46SWarner Losh     FICL_INT i;
281ca987d46SWarner Losh #if FICL_ROBUST > 1
282ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
283ca987d46SWarner Losh #endif
284ca987d46SWarner Losh     i = stackPopINT(pVM->pStack);
285ca987d46SWarner Losh     i += stackGetTop(pVM->pStack).i;
286ca987d46SWarner Losh     stackSetTop(pVM->pStack, LVALUEtoCELL(i));
287ca987d46SWarner Losh     return;
288ca987d46SWarner Losh }
289ca987d46SWarner Losh 
sub(FICL_VM * pVM)290ca987d46SWarner Losh static void sub(FICL_VM *pVM)
291ca987d46SWarner Losh {
292ca987d46SWarner Losh     FICL_INT i;
293ca987d46SWarner Losh #if FICL_ROBUST > 1
294ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
295ca987d46SWarner Losh #endif
296ca987d46SWarner Losh     i = stackPopINT(pVM->pStack);
297ca987d46SWarner Losh     i = stackGetTop(pVM->pStack).i - i;
298ca987d46SWarner Losh     stackSetTop(pVM->pStack, LVALUEtoCELL(i));
299ca987d46SWarner Losh     return;
300ca987d46SWarner Losh }
301ca987d46SWarner Losh 
mul(FICL_VM * pVM)302ca987d46SWarner Losh static void mul(FICL_VM *pVM)
303ca987d46SWarner Losh {
304ca987d46SWarner Losh     FICL_INT i;
305ca987d46SWarner Losh #if FICL_ROBUST > 1
306ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
307ca987d46SWarner Losh #endif
308ca987d46SWarner Losh     i = stackPopINT(pVM->pStack);
309ca987d46SWarner Losh     i *= stackGetTop(pVM->pStack).i;
310ca987d46SWarner Losh     stackSetTop(pVM->pStack, LVALUEtoCELL(i));
311ca987d46SWarner Losh     return;
312ca987d46SWarner Losh }
313ca987d46SWarner Losh 
negate(FICL_VM * pVM)314ca987d46SWarner Losh static void negate(FICL_VM *pVM)
315ca987d46SWarner Losh {
316ca987d46SWarner Losh     FICL_INT i;
317ca987d46SWarner Losh #if FICL_ROBUST > 1
318ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
319ca987d46SWarner Losh #endif
320ca987d46SWarner Losh     i = -stackPopINT(pVM->pStack);
321ca987d46SWarner Losh     PUSHINT(i);
322ca987d46SWarner Losh     return;
323ca987d46SWarner Losh }
324ca987d46SWarner Losh 
ficlDiv(FICL_VM * pVM)325ca987d46SWarner Losh static void ficlDiv(FICL_VM *pVM)
326ca987d46SWarner Losh {
327ca987d46SWarner Losh     FICL_INT i;
328ca987d46SWarner Losh #if FICL_ROBUST > 1
329ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
330ca987d46SWarner Losh #endif
331ca987d46SWarner Losh     i = stackPopINT(pVM->pStack);
332ca987d46SWarner Losh     i = stackGetTop(pVM->pStack).i / i;
333ca987d46SWarner Losh     stackSetTop(pVM->pStack, LVALUEtoCELL(i));
334ca987d46SWarner Losh     return;
335ca987d46SWarner Losh }
336ca987d46SWarner Losh 
337ca987d46SWarner Losh /*
338ca987d46SWarner Losh ** slash-mod        CORE ( n1 n2 -- n3 n4 )
339ca987d46SWarner Losh ** Divide n1 by n2, giving the single-cell remainder n3 and the single-cell
340ca987d46SWarner Losh ** quotient n4. An ambiguous condition exists if n2 is zero. If n1 and n2
341ca987d46SWarner Losh ** differ in sign, the implementation-defined result returned will be the
342ca987d46SWarner Losh ** same as that returned by either the phrase
343ca987d46SWarner Losh ** >R S>D R> FM/MOD or the phrase >R S>D R> SM/REM .
344ca987d46SWarner Losh ** NOTE: Ficl complies with the second phrase (symmetric division)
345ca987d46SWarner Losh */
slashMod(FICL_VM * pVM)346ca987d46SWarner Losh static void slashMod(FICL_VM *pVM)
347ca987d46SWarner Losh {
348ca987d46SWarner Losh     DPINT n1;
349ca987d46SWarner Losh     FICL_INT n2;
350ca987d46SWarner Losh     INTQR qr;
351ca987d46SWarner Losh 
352ca987d46SWarner Losh #if FICL_ROBUST > 1
353ca987d46SWarner Losh     vmCheckStack(pVM, 2, 2);
354ca987d46SWarner Losh #endif
355ca987d46SWarner Losh     n2    = stackPopINT(pVM->pStack);
356ca987d46SWarner Losh     n1.lo = stackPopINT(pVM->pStack);
357ca987d46SWarner Losh     i64Extend(n1);
358ca987d46SWarner Losh 
359ca987d46SWarner Losh     qr = m64SymmetricDivI(n1, n2);
360ca987d46SWarner Losh     PUSHINT(qr.rem);
361ca987d46SWarner Losh     PUSHINT(qr.quot);
362ca987d46SWarner Losh     return;
363ca987d46SWarner Losh }
364ca987d46SWarner Losh 
onePlus(FICL_VM * pVM)365ca987d46SWarner Losh static void onePlus(FICL_VM *pVM)
366ca987d46SWarner Losh {
367ca987d46SWarner Losh     FICL_INT i;
368ca987d46SWarner Losh #if FICL_ROBUST > 1
369ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
370ca987d46SWarner Losh #endif
371ca987d46SWarner Losh     i = stackGetTop(pVM->pStack).i;
372ca987d46SWarner Losh     i += 1;
373ca987d46SWarner Losh     stackSetTop(pVM->pStack, LVALUEtoCELL(i));
374ca987d46SWarner Losh     return;
375ca987d46SWarner Losh }
376ca987d46SWarner Losh 
oneMinus(FICL_VM * pVM)377ca987d46SWarner Losh static void oneMinus(FICL_VM *pVM)
378ca987d46SWarner Losh {
379ca987d46SWarner Losh     FICL_INT i;
380ca987d46SWarner Losh #if FICL_ROBUST > 1
381ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
382ca987d46SWarner Losh #endif
383ca987d46SWarner Losh     i = stackGetTop(pVM->pStack).i;
384ca987d46SWarner Losh     i -= 1;
385ca987d46SWarner Losh     stackSetTop(pVM->pStack, LVALUEtoCELL(i));
386ca987d46SWarner Losh     return;
387ca987d46SWarner Losh }
388ca987d46SWarner Losh 
twoMul(FICL_VM * pVM)389ca987d46SWarner Losh static void twoMul(FICL_VM *pVM)
390ca987d46SWarner Losh {
391ca987d46SWarner Losh     FICL_INT i;
392ca987d46SWarner Losh #if FICL_ROBUST > 1
393ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
394ca987d46SWarner Losh #endif
395ca987d46SWarner Losh     i = stackGetTop(pVM->pStack).i;
396ca987d46SWarner Losh     i *= 2;
397ca987d46SWarner Losh     stackSetTop(pVM->pStack, LVALUEtoCELL(i));
398ca987d46SWarner Losh     return;
399ca987d46SWarner Losh }
400ca987d46SWarner Losh 
twoDiv(FICL_VM * pVM)401ca987d46SWarner Losh static void twoDiv(FICL_VM *pVM)
402ca987d46SWarner Losh {
403ca987d46SWarner Losh     FICL_INT i;
404ca987d46SWarner Losh #if FICL_ROBUST > 1
405ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
406ca987d46SWarner Losh #endif
407ca987d46SWarner Losh     i = stackGetTop(pVM->pStack).i;
408ca987d46SWarner Losh     i >>= 1;
409ca987d46SWarner Losh     stackSetTop(pVM->pStack, LVALUEtoCELL(i));
410ca987d46SWarner Losh     return;
411ca987d46SWarner Losh }
412ca987d46SWarner Losh 
mulDiv(FICL_VM * pVM)413ca987d46SWarner Losh static void mulDiv(FICL_VM *pVM)
414ca987d46SWarner Losh {
415ca987d46SWarner Losh     FICL_INT x, y, z;
416ca987d46SWarner Losh     DPINT prod;
417ca987d46SWarner Losh #if FICL_ROBUST > 1
418ca987d46SWarner Losh     vmCheckStack(pVM, 3, 1);
419ca987d46SWarner Losh #endif
420ca987d46SWarner Losh     z = stackPopINT(pVM->pStack);
421ca987d46SWarner Losh     y = stackPopINT(pVM->pStack);
422ca987d46SWarner Losh     x = stackPopINT(pVM->pStack);
423ca987d46SWarner Losh 
424ca987d46SWarner Losh     prod = m64MulI(x,y);
425ca987d46SWarner Losh     x    = m64SymmetricDivI(prod, z).quot;
426ca987d46SWarner Losh 
427ca987d46SWarner Losh     PUSHINT(x);
428ca987d46SWarner Losh     return;
429ca987d46SWarner Losh }
430ca987d46SWarner Losh 
431ca987d46SWarner Losh 
mulDivRem(FICL_VM * pVM)432ca987d46SWarner Losh static void mulDivRem(FICL_VM *pVM)
433ca987d46SWarner Losh {
434ca987d46SWarner Losh     FICL_INT x, y, z;
435ca987d46SWarner Losh     DPINT prod;
436ca987d46SWarner Losh     INTQR qr;
437ca987d46SWarner Losh #if FICL_ROBUST > 1
438ca987d46SWarner Losh     vmCheckStack(pVM, 3, 2);
439ca987d46SWarner Losh #endif
440ca987d46SWarner Losh     z = stackPopINT(pVM->pStack);
441ca987d46SWarner Losh     y = stackPopINT(pVM->pStack);
442ca987d46SWarner Losh     x = stackPopINT(pVM->pStack);
443ca987d46SWarner Losh 
444ca987d46SWarner Losh     prod = m64MulI(x,y);
445ca987d46SWarner Losh     qr   = m64SymmetricDivI(prod, z);
446ca987d46SWarner Losh 
447ca987d46SWarner Losh     PUSHINT(qr.rem);
448ca987d46SWarner Losh     PUSHINT(qr.quot);
449ca987d46SWarner Losh     return;
450ca987d46SWarner Losh }
451ca987d46SWarner Losh 
452ca987d46SWarner Losh 
453ca987d46SWarner Losh /**************************************************************************
454ca987d46SWarner Losh                         c o l o n   d e f i n i t i o n s
455ca987d46SWarner Losh ** Code to begin compiling a colon definition
456ca987d46SWarner Losh ** This function sets the state to COMPILE, then creates a
457ca987d46SWarner Losh ** new word whose name is the next word in the input stream
458ca987d46SWarner Losh ** and whose code is colonParen.
459ca987d46SWarner Losh **************************************************************************/
460ca987d46SWarner Losh 
colon(FICL_VM * pVM)461ca987d46SWarner Losh static void colon(FICL_VM *pVM)
462ca987d46SWarner Losh {
463ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
464ca987d46SWarner Losh     STRINGINFO si = vmGetWord(pVM);
465ca987d46SWarner Losh 
466ca987d46SWarner Losh     dictCheckThreshold(dp);
467ca987d46SWarner Losh 
468ca987d46SWarner Losh     pVM->state = COMPILE;
469ca987d46SWarner Losh     markControlTag(pVM, colonTag);
470ca987d46SWarner Losh     dictAppendWord2(dp, si, colonParen, FW_DEFAULT | FW_SMUDGE);
471ca987d46SWarner Losh #if FICL_WANT_LOCALS
472ca987d46SWarner Losh     pVM->pSys->nLocals = 0;
473ca987d46SWarner Losh #endif
474ca987d46SWarner Losh     return;
475ca987d46SWarner Losh }
476ca987d46SWarner Losh 
477ca987d46SWarner Losh 
478ca987d46SWarner Losh /**************************************************************************
479ca987d46SWarner Losh                         c o l o n P a r e n
480ca987d46SWarner Losh ** This is the code that executes a colon definition. It assumes that the
481ca987d46SWarner Losh ** virtual machine is running a "next" loop (See the vm.c
482ca987d46SWarner Losh ** for its implementation of member function vmExecute()). The colon
483ca987d46SWarner Losh ** code simply copies the address of the first word in the list of words
484ca987d46SWarner Losh ** to interpret into IP after saving its old value. When we return to the
485ca987d46SWarner Losh ** "next" loop, the virtual machine will call the code for each word in
486ca987d46SWarner Losh ** turn.
487ca987d46SWarner Losh **
488ca987d46SWarner Losh **************************************************************************/
489ca987d46SWarner Losh 
colonParen(FICL_VM * pVM)490ca987d46SWarner Losh static void colonParen(FICL_VM *pVM)
491ca987d46SWarner Losh {
492ca987d46SWarner Losh     IPTYPE tempIP = (IPTYPE) (pVM->runningWord->param);
493ca987d46SWarner Losh     vmPushIP(pVM, tempIP);
494ca987d46SWarner Losh 
495ca987d46SWarner Losh     return;
496ca987d46SWarner Losh }
497ca987d46SWarner Losh 
498ca987d46SWarner Losh 
499ca987d46SWarner Losh /**************************************************************************
500ca987d46SWarner Losh                         s e m i c o l o n C o I m
501ca987d46SWarner Losh **
502ca987d46SWarner Losh ** IMMEDIATE code for ";". This function sets the state to INTERPRET and
503ca987d46SWarner Losh ** terminates a word under compilation by appending code for "(;)" to
504ca987d46SWarner Losh ** the definition. TO DO: checks for leftover branch target tags on the
505ca987d46SWarner Losh ** return stack and complains if any are found.
506ca987d46SWarner Losh **************************************************************************/
semiParen(FICL_VM * pVM)507ca987d46SWarner Losh static void semiParen(FICL_VM *pVM)
508ca987d46SWarner Losh {
509ca987d46SWarner Losh     vmPopIP(pVM);
510ca987d46SWarner Losh     return;
511ca987d46SWarner Losh }
512ca987d46SWarner Losh 
513ca987d46SWarner Losh 
semicolonCoIm(FICL_VM * pVM)514ca987d46SWarner Losh static void semicolonCoIm(FICL_VM *pVM)
515ca987d46SWarner Losh {
516ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
517ca987d46SWarner Losh 
518ca987d46SWarner Losh     assert(pVM->pSys->pSemiParen);
519ca987d46SWarner Losh     matchControlTag(pVM, colonTag);
520ca987d46SWarner Losh 
521ca987d46SWarner Losh #if FICL_WANT_LOCALS
522ca987d46SWarner Losh     assert(pVM->pSys->pUnLinkParen);
523ca987d46SWarner Losh     if (pVM->pSys->nLocals > 0)
524ca987d46SWarner Losh     {
525ca987d46SWarner Losh         FICL_DICT *pLoc = ficlGetLoc(pVM->pSys);
526ca987d46SWarner Losh         dictEmpty(pLoc, pLoc->pForthWords->size);
527ca987d46SWarner Losh         dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pUnLinkParen));
528ca987d46SWarner Losh     }
529ca987d46SWarner Losh     pVM->pSys->nLocals = 0;
530ca987d46SWarner Losh #endif
531ca987d46SWarner Losh 
532ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pSemiParen));
533ca987d46SWarner Losh     pVM->state = INTERPRET;
534ca987d46SWarner Losh     dictUnsmudge(dp);
535ca987d46SWarner Losh     return;
536ca987d46SWarner Losh }
537ca987d46SWarner Losh 
538ca987d46SWarner Losh 
539ca987d46SWarner Losh /**************************************************************************
540ca987d46SWarner Losh                         e x i t
541ca987d46SWarner Losh ** CORE
542ca987d46SWarner Losh ** This function simply pops the previous instruction
543ca987d46SWarner Losh ** pointer and returns to the "next" loop. Used for exiting from within
544ca987d46SWarner Losh ** a definition. Note that exitParen is identical to semiParen - they
545ca987d46SWarner Losh ** are in two different functions so that "see" can correctly identify
546ca987d46SWarner Losh ** the end of a colon definition, even if it uses "exit".
547ca987d46SWarner Losh **************************************************************************/
exitParen(FICL_VM * pVM)548ca987d46SWarner Losh static void exitParen(FICL_VM *pVM)
549ca987d46SWarner Losh {
550ca987d46SWarner Losh     vmPopIP(pVM);
551ca987d46SWarner Losh     return;
552ca987d46SWarner Losh }
553ca987d46SWarner Losh 
exitCoIm(FICL_VM * pVM)554ca987d46SWarner Losh static void exitCoIm(FICL_VM *pVM)
555ca987d46SWarner Losh {
556ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
557ca987d46SWarner Losh     assert(pVM->pSys->pExitParen);
558ca987d46SWarner Losh     IGNORE(pVM);
559ca987d46SWarner Losh 
560ca987d46SWarner Losh #if FICL_WANT_LOCALS
561ca987d46SWarner Losh     if (pVM->pSys->nLocals > 0)
562ca987d46SWarner Losh     {
563ca987d46SWarner Losh         dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pUnLinkParen));
564ca987d46SWarner Losh     }
565ca987d46SWarner Losh #endif
566ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pExitParen));
567ca987d46SWarner Losh     return;
568ca987d46SWarner Losh }
569ca987d46SWarner Losh 
570ca987d46SWarner Losh 
571ca987d46SWarner Losh /**************************************************************************
572ca987d46SWarner Losh                         c o n s t a n t P a r e n
573ca987d46SWarner Losh ** This is the run-time code for "constant". It simply returns the
574ca987d46SWarner Losh ** contents of its word's first data cell.
575ca987d46SWarner Losh **
576ca987d46SWarner Losh **************************************************************************/
577ca987d46SWarner Losh 
constantParen(FICL_VM * pVM)578ca987d46SWarner Losh void constantParen(FICL_VM *pVM)
579ca987d46SWarner Losh {
580ca987d46SWarner Losh     FICL_WORD *pFW = pVM->runningWord;
581ca987d46SWarner Losh #if FICL_ROBUST > 1
582ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
583ca987d46SWarner Losh #endif
584ca987d46SWarner Losh     stackPush(pVM->pStack, pFW->param[0]);
585ca987d46SWarner Losh     return;
586ca987d46SWarner Losh }
587ca987d46SWarner Losh 
twoConstParen(FICL_VM * pVM)588ca987d46SWarner Losh void twoConstParen(FICL_VM *pVM)
589ca987d46SWarner Losh {
590ca987d46SWarner Losh     FICL_WORD *pFW = pVM->runningWord;
591ca987d46SWarner Losh #if FICL_ROBUST > 1
592ca987d46SWarner Losh     vmCheckStack(pVM, 0, 2);
593ca987d46SWarner Losh #endif
594ca987d46SWarner Losh     stackPush(pVM->pStack, pFW->param[0]); /* lo */
595ca987d46SWarner Losh     stackPush(pVM->pStack, pFW->param[1]); /* hi */
596ca987d46SWarner Losh     return;
597ca987d46SWarner Losh }
598ca987d46SWarner Losh 
599ca987d46SWarner Losh 
600ca987d46SWarner Losh /**************************************************************************
601ca987d46SWarner Losh                         c o n s t a n t
602ca987d46SWarner Losh ** IMMEDIATE
603ca987d46SWarner Losh ** Compiles a constant into the dictionary. Constants return their
604ca987d46SWarner Losh ** value when invoked. Expects a value on top of the parm stack.
605ca987d46SWarner Losh **************************************************************************/
606ca987d46SWarner Losh 
constant(FICL_VM * pVM)607ca987d46SWarner Losh static void constant(FICL_VM *pVM)
608ca987d46SWarner Losh {
609ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
610ca987d46SWarner Losh     STRINGINFO si = vmGetWord(pVM);
611ca987d46SWarner Losh 
612ca987d46SWarner Losh #if FICL_ROBUST > 1
613ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
614ca987d46SWarner Losh #endif
615ca987d46SWarner Losh     dictAppendWord2(dp, si, constantParen, FW_DEFAULT);
616ca987d46SWarner Losh     dictAppendCell(dp, stackPop(pVM->pStack));
617ca987d46SWarner Losh     return;
618ca987d46SWarner Losh }
619ca987d46SWarner Losh 
620ca987d46SWarner Losh 
twoConstant(FICL_VM * pVM)621ca987d46SWarner Losh static void twoConstant(FICL_VM *pVM)
622ca987d46SWarner Losh {
623ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
624ca987d46SWarner Losh     STRINGINFO si = vmGetWord(pVM);
625ca987d46SWarner Losh     CELL c;
626ca987d46SWarner Losh 
627ca987d46SWarner Losh #if FICL_ROBUST > 1
628ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
629ca987d46SWarner Losh #endif
630ca987d46SWarner Losh     c = stackPop(pVM->pStack);
631ca987d46SWarner Losh     dictAppendWord2(dp, si, twoConstParen, FW_DEFAULT);
632ca987d46SWarner Losh     dictAppendCell(dp, stackPop(pVM->pStack));
633ca987d46SWarner Losh     dictAppendCell(dp, c);
634ca987d46SWarner Losh     return;
635ca987d46SWarner Losh }
636ca987d46SWarner Losh 
637ca987d46SWarner Losh 
638ca987d46SWarner Losh /**************************************************************************
639ca987d46SWarner Losh                         d i s p l a y C e l l
640ca987d46SWarner Losh ** Drop and print the contents of the cell at the top of the param
641ca987d46SWarner Losh ** stack
642ca987d46SWarner Losh **************************************************************************/
643ca987d46SWarner Losh 
displayCell(FICL_VM * pVM)644ca987d46SWarner Losh static void displayCell(FICL_VM *pVM)
645ca987d46SWarner Losh {
646ca987d46SWarner Losh     CELL c;
647ca987d46SWarner Losh #if FICL_ROBUST > 1
648ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
649ca987d46SWarner Losh #endif
650ca987d46SWarner Losh     c = stackPop(pVM->pStack);
651ca987d46SWarner Losh     ltoa((c).i, pVM->pad, pVM->base);
652ca987d46SWarner Losh     strcat(pVM->pad, " ");
653ca987d46SWarner Losh     vmTextOut(pVM, pVM->pad, 0);
654ca987d46SWarner Losh     return;
655ca987d46SWarner Losh }
656ca987d46SWarner Losh 
uDot(FICL_VM * pVM)657ca987d46SWarner Losh static void uDot(FICL_VM *pVM)
658ca987d46SWarner Losh {
659ca987d46SWarner Losh     FICL_UNS u;
660ca987d46SWarner Losh #if FICL_ROBUST > 1
661ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
662ca987d46SWarner Losh #endif
663ca987d46SWarner Losh     u = stackPopUNS(pVM->pStack);
664ca987d46SWarner Losh     ultoa(u, pVM->pad, pVM->base);
665ca987d46SWarner Losh     strcat(pVM->pad, " ");
666ca987d46SWarner Losh     vmTextOut(pVM, pVM->pad, 0);
667ca987d46SWarner Losh     return;
668ca987d46SWarner Losh }
669ca987d46SWarner Losh 
670ca987d46SWarner Losh 
hexDot(FICL_VM * pVM)671ca987d46SWarner Losh static void hexDot(FICL_VM *pVM)
672ca987d46SWarner Losh {
673ca987d46SWarner Losh     FICL_UNS u;
674ca987d46SWarner Losh #if FICL_ROBUST > 1
675ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
676ca987d46SWarner Losh #endif
677ca987d46SWarner Losh     u = stackPopUNS(pVM->pStack);
678ca987d46SWarner Losh     ultoa(u, pVM->pad, 16);
679ca987d46SWarner Losh     strcat(pVM->pad, " ");
680ca987d46SWarner Losh     vmTextOut(pVM, pVM->pad, 0);
681ca987d46SWarner Losh     return;
682ca987d46SWarner Losh }
683ca987d46SWarner Losh 
684ca987d46SWarner Losh 
685ca987d46SWarner Losh /**************************************************************************
686ca987d46SWarner Losh                         s t r l e n
687ca987d46SWarner Losh ** FICL   ( c-string -- length )
688ca987d46SWarner Losh **
689ca987d46SWarner Losh ** Returns the length of a C-style (zero-terminated) string.
690ca987d46SWarner Losh **
691ca987d46SWarner Losh ** --lch
692ca987d46SWarner Losh **/
ficlStrlen(FICL_VM * ficlVM)693ca987d46SWarner Losh static void ficlStrlen(FICL_VM *ficlVM)
694ca987d46SWarner Losh 	{
695ca987d46SWarner Losh 	char *address = (char *)stackPopPtr(ficlVM->pStack);
696ca987d46SWarner Losh 	stackPushINT(ficlVM->pStack, strlen(address));
697ca987d46SWarner Losh 	}
698ca987d46SWarner Losh 
699ca987d46SWarner Losh 
700ca987d46SWarner Losh /**************************************************************************
701ca987d46SWarner Losh                         s p r i n t f
702ca987d46SWarner Losh ** FICL   ( i*x c-addr-fmt u-fmt c-addr-buffer u-buffer -- c-addr-buffer u-written success-flag )
703ca987d46SWarner Losh ** Similar to the C sprintf() function.  It formats into a buffer based on
704ca987d46SWarner Losh ** a "format" string.  Each character in the format string is copied verbatim
705ca987d46SWarner Losh ** to the output buffer, until SPRINTF encounters a percent sign ("%").
706ca987d46SWarner Losh ** SPRINTF then skips the percent sign, and examines the next character
707ca987d46SWarner Losh ** (the "format character").  Here are the valid format characters:
708ca987d46SWarner Losh **    s - read a C-ADDR U-LENGTH string from the stack and copy it to
709ca987d46SWarner Losh **        the buffer
710ca987d46SWarner Losh **    d - read a cell from the stack, format it as a string (base-10,
711ca987d46SWarner Losh **        signed), and copy it to the buffer
712ca987d46SWarner Losh **    x - same as d, except in base-16
713ca987d46SWarner Losh **    u - same as d, but unsigned
714ca987d46SWarner Losh **    % - output a literal percent-sign to the buffer
715ca987d46SWarner Losh ** SPRINTF returns the c-addr-buffer argument unchanged, the number of bytes
716ca987d46SWarner Losh ** written, and a flag indicating whether or not it ran out of space while
717ca987d46SWarner Losh ** writing to the output buffer (TRUE if it ran out of space).
718ca987d46SWarner Losh **
719ca987d46SWarner Losh ** If SPRINTF runs out of space in the buffer to store the formatted string,
720ca987d46SWarner Losh ** it still continues parsing, in an effort to preserve your stack (otherwise
721ca987d46SWarner Losh ** it might leave uneaten arguments behind).
722ca987d46SWarner Losh **
723ca987d46SWarner Losh ** --lch
724ca987d46SWarner Losh **************************************************************************/
ficlSprintf(FICL_VM * pVM)725ca987d46SWarner Losh static void ficlSprintf(FICL_VM *pVM) /*  */
726ca987d46SWarner Losh {
727ca987d46SWarner Losh 	int bufferLength = stackPopINT(pVM->pStack);
728ca987d46SWarner Losh 	char *buffer = (char *)stackPopPtr(pVM->pStack);
729ca987d46SWarner Losh 	char *bufferStart = buffer;
730ca987d46SWarner Losh 
731ca987d46SWarner Losh 	int formatLength = stackPopINT(pVM->pStack);
732ca987d46SWarner Losh 	char *format = (char *)stackPopPtr(pVM->pStack);
733ca987d46SWarner Losh 	char *formatStop = format + formatLength;
734ca987d46SWarner Losh 
735ca987d46SWarner Losh 	int base = 10;
736ca987d46SWarner Losh 	int unsignedInteger = FALSE;
737ca987d46SWarner Losh 
738ca987d46SWarner Losh 	FICL_INT append = FICL_TRUE;
739ca987d46SWarner Losh 
740ca987d46SWarner Losh 	while (format < formatStop)
741ca987d46SWarner Losh 	{
742ca987d46SWarner Losh 		char scratch[64];
743ca987d46SWarner Losh 		char *source;
744ca987d46SWarner Losh 		int actualLength;
745ca987d46SWarner Losh 		int desiredLength;
746ca987d46SWarner Losh 		int leadingZeroes;
747ca987d46SWarner Losh 
748ca987d46SWarner Losh 
749ca987d46SWarner Losh 		if (*format != '%')
750ca987d46SWarner Losh 		{
751ca987d46SWarner Losh 			source = format;
752ca987d46SWarner Losh 			actualLength = desiredLength = 1;
753ca987d46SWarner Losh 			leadingZeroes = 0;
754ca987d46SWarner Losh 		}
755ca987d46SWarner Losh 		else
756ca987d46SWarner Losh 		{
757ca987d46SWarner Losh 			format++;
758ca987d46SWarner Losh 			if (format == formatStop)
759ca987d46SWarner Losh 				break;
760ca987d46SWarner Losh 
761ca987d46SWarner Losh 			leadingZeroes = (*format == '0');
762ca987d46SWarner Losh 			if (leadingZeroes)
763ca987d46SWarner Losh 				{
764ca987d46SWarner Losh 				format++;
765ca987d46SWarner Losh 				if (format == formatStop)
766ca987d46SWarner Losh 					break;
767ca987d46SWarner Losh 				}
768ca987d46SWarner Losh 
769ca987d46SWarner Losh 			desiredLength = isdigit(*format);
770ca987d46SWarner Losh 			if (desiredLength)
771ca987d46SWarner Losh 				{
772ca987d46SWarner Losh 				desiredLength = strtol(format, &format, 10);
773ca987d46SWarner Losh 				if (format == formatStop)
774ca987d46SWarner Losh 					break;
775ca987d46SWarner Losh 				}
776ca987d46SWarner Losh 			else if (*format == '*')
777ca987d46SWarner Losh 				{
778ca987d46SWarner Losh 				desiredLength = stackPopINT(pVM->pStack);
779ca987d46SWarner Losh 				format++;
780ca987d46SWarner Losh 				if (format == formatStop)
781ca987d46SWarner Losh 					break;
782ca987d46SWarner Losh 				}
783ca987d46SWarner Losh 
784ca987d46SWarner Losh 
785ca987d46SWarner Losh 			switch (*format)
786ca987d46SWarner Losh 			{
787ca987d46SWarner Losh 				case 's':
788ca987d46SWarner Losh 				case 'S':
789ca987d46SWarner Losh 				{
790ca987d46SWarner Losh 					actualLength = stackPopINT(pVM->pStack);
791ca987d46SWarner Losh 					source = (char *)stackPopPtr(pVM->pStack);
792ca987d46SWarner Losh 					break;
793ca987d46SWarner Losh 				}
794ca987d46SWarner Losh 				case 'x':
795ca987d46SWarner Losh 				case 'X':
796ca987d46SWarner Losh 					base = 16;
797ca987d46SWarner Losh 				case 'u':
798ca987d46SWarner Losh 				case 'U':
799ca987d46SWarner Losh 					unsignedInteger = TRUE;
800ca987d46SWarner Losh 				case 'd':
801ca987d46SWarner Losh 				case 'D':
802ca987d46SWarner Losh 				{
803ca987d46SWarner Losh 					int integer = stackPopINT(pVM->pStack);
804ca987d46SWarner Losh 					if (unsignedInteger)
805ca987d46SWarner Losh 						ultoa(integer, scratch, base);
806ca987d46SWarner Losh 					else
807ca987d46SWarner Losh 						ltoa(integer, scratch, base);
808ca987d46SWarner Losh 					base = 10;
809ca987d46SWarner Losh 					unsignedInteger = FALSE;
810ca987d46SWarner Losh 					source = scratch;
811ca987d46SWarner Losh 					actualLength = strlen(scratch);
812ca987d46SWarner Losh 					break;
813ca987d46SWarner Losh 				}
814ca987d46SWarner Losh 				case '%':
815ca987d46SWarner Losh 					source = format;
816ca987d46SWarner Losh 					actualLength = 1;
817ca987d46SWarner Losh 				default:
818ca987d46SWarner Losh 					continue;
819ca987d46SWarner Losh 			}
820ca987d46SWarner Losh 		}
821ca987d46SWarner Losh 
822ca987d46SWarner Losh 		if (append != FICL_FALSE)
823ca987d46SWarner Losh 		{
824ca987d46SWarner Losh 			if (!desiredLength)
825ca987d46SWarner Losh 				desiredLength = actualLength;
826ca987d46SWarner Losh 			if (desiredLength > bufferLength)
827ca987d46SWarner Losh 			{
828ca987d46SWarner Losh 				append = FICL_FALSE;
829ca987d46SWarner Losh 				desiredLength = bufferLength;
830ca987d46SWarner Losh 			}
831ca987d46SWarner Losh 			while (desiredLength > actualLength)
832ca987d46SWarner Losh 				{
833ca987d46SWarner Losh 				*buffer++ = (char)((leadingZeroes) ? '0' : ' ');
834ca987d46SWarner Losh 				bufferLength--;
835ca987d46SWarner Losh 				desiredLength--;
836ca987d46SWarner Losh 				}
837ca987d46SWarner Losh 			memcpy(buffer, source, actualLength);
838ca987d46SWarner Losh 			buffer += actualLength;
839ca987d46SWarner Losh 			bufferLength -= actualLength;
840ca987d46SWarner Losh 		}
841ca987d46SWarner Losh 
842ca987d46SWarner Losh 		format++;
843ca987d46SWarner Losh 	}
844ca987d46SWarner Losh 
845ca987d46SWarner Losh 	stackPushPtr(pVM->pStack, bufferStart);
846ca987d46SWarner Losh 	stackPushINT(pVM->pStack, buffer - bufferStart);
847ca987d46SWarner Losh 	stackPushINT(pVM->pStack, append);
848ca987d46SWarner Losh }
849ca987d46SWarner Losh 
850ca987d46SWarner Losh 
851ca987d46SWarner Losh /**************************************************************************
852ca987d46SWarner Losh                         d u p   &   f r i e n d s
853ca987d46SWarner Losh **
854ca987d46SWarner Losh **************************************************************************/
855ca987d46SWarner Losh 
depth(FICL_VM * pVM)856ca987d46SWarner Losh static void depth(FICL_VM *pVM)
857ca987d46SWarner Losh {
858ca987d46SWarner Losh     int i;
859ca987d46SWarner Losh #if FICL_ROBUST > 1
860ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
861ca987d46SWarner Losh #endif
862ca987d46SWarner Losh     i = stackDepth(pVM->pStack);
863ca987d46SWarner Losh     PUSHINT(i);
864ca987d46SWarner Losh     return;
865ca987d46SWarner Losh }
866ca987d46SWarner Losh 
867ca987d46SWarner Losh 
drop(FICL_VM * pVM)868ca987d46SWarner Losh static void drop(FICL_VM *pVM)
869ca987d46SWarner Losh {
870ca987d46SWarner Losh #if FICL_ROBUST > 1
871ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
872ca987d46SWarner Losh #endif
873ca987d46SWarner Losh     stackDrop(pVM->pStack, 1);
874ca987d46SWarner Losh     return;
875ca987d46SWarner Losh }
876ca987d46SWarner Losh 
877ca987d46SWarner Losh 
twoDrop(FICL_VM * pVM)878ca987d46SWarner Losh static void twoDrop(FICL_VM *pVM)
879ca987d46SWarner Losh {
880ca987d46SWarner Losh #if FICL_ROBUST > 1
881ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
882ca987d46SWarner Losh #endif
883ca987d46SWarner Losh     stackDrop(pVM->pStack, 2);
884ca987d46SWarner Losh     return;
885ca987d46SWarner Losh }
886ca987d46SWarner Losh 
887ca987d46SWarner Losh 
dup(FICL_VM * pVM)888ca987d46SWarner Losh static void dup(FICL_VM *pVM)
889ca987d46SWarner Losh {
890ca987d46SWarner Losh #if FICL_ROBUST > 1
891ca987d46SWarner Losh     vmCheckStack(pVM, 1, 2);
892ca987d46SWarner Losh #endif
893ca987d46SWarner Losh     stackPick(pVM->pStack, 0);
894ca987d46SWarner Losh     return;
895ca987d46SWarner Losh }
896ca987d46SWarner Losh 
897ca987d46SWarner Losh 
twoDup(FICL_VM * pVM)898ca987d46SWarner Losh static void twoDup(FICL_VM *pVM)
899ca987d46SWarner Losh {
900ca987d46SWarner Losh #if FICL_ROBUST > 1
901ca987d46SWarner Losh     vmCheckStack(pVM, 2, 4);
902ca987d46SWarner Losh #endif
903ca987d46SWarner Losh     stackPick(pVM->pStack, 1);
904ca987d46SWarner Losh     stackPick(pVM->pStack, 1);
905ca987d46SWarner Losh     return;
906ca987d46SWarner Losh }
907ca987d46SWarner Losh 
908ca987d46SWarner Losh 
over(FICL_VM * pVM)909ca987d46SWarner Losh static void over(FICL_VM *pVM)
910ca987d46SWarner Losh {
911ca987d46SWarner Losh #if FICL_ROBUST > 1
912ca987d46SWarner Losh     vmCheckStack(pVM, 2, 3);
913ca987d46SWarner Losh #endif
914ca987d46SWarner Losh     stackPick(pVM->pStack, 1);
915ca987d46SWarner Losh     return;
916ca987d46SWarner Losh }
917ca987d46SWarner Losh 
twoOver(FICL_VM * pVM)918ca987d46SWarner Losh static void twoOver(FICL_VM *pVM)
919ca987d46SWarner Losh {
920ca987d46SWarner Losh #if FICL_ROBUST > 1
921ca987d46SWarner Losh     vmCheckStack(pVM, 4, 6);
922ca987d46SWarner Losh #endif
923ca987d46SWarner Losh     stackPick(pVM->pStack, 3);
924ca987d46SWarner Losh     stackPick(pVM->pStack, 3);
925ca987d46SWarner Losh     return;
926ca987d46SWarner Losh }
927ca987d46SWarner Losh 
928ca987d46SWarner Losh 
pick(FICL_VM * pVM)929ca987d46SWarner Losh static void pick(FICL_VM *pVM)
930ca987d46SWarner Losh {
931ca987d46SWarner Losh     CELL c = stackPop(pVM->pStack);
932ca987d46SWarner Losh #if FICL_ROBUST > 1
933ca987d46SWarner Losh     vmCheckStack(pVM, c.i+1, c.i+2);
934ca987d46SWarner Losh #endif
935ca987d46SWarner Losh     stackPick(pVM->pStack, c.i);
936ca987d46SWarner Losh     return;
937ca987d46SWarner Losh }
938ca987d46SWarner Losh 
939ca987d46SWarner Losh 
questionDup(FICL_VM * pVM)940ca987d46SWarner Losh static void questionDup(FICL_VM *pVM)
941ca987d46SWarner Losh {
942ca987d46SWarner Losh     CELL c;
943ca987d46SWarner Losh #if FICL_ROBUST > 1
944ca987d46SWarner Losh     vmCheckStack(pVM, 1, 2);
945ca987d46SWarner Losh #endif
946ca987d46SWarner Losh     c = stackGetTop(pVM->pStack);
947ca987d46SWarner Losh 
948ca987d46SWarner Losh     if (c.i != 0)
949ca987d46SWarner Losh         stackPick(pVM->pStack, 0);
950ca987d46SWarner Losh 
951ca987d46SWarner Losh     return;
952ca987d46SWarner Losh }
953ca987d46SWarner Losh 
954ca987d46SWarner Losh 
roll(FICL_VM * pVM)955ca987d46SWarner Losh static void roll(FICL_VM *pVM)
956ca987d46SWarner Losh {
957ca987d46SWarner Losh     int i = stackPop(pVM->pStack).i;
958ca987d46SWarner Losh     i = (i > 0) ? i : 0;
959ca987d46SWarner Losh #if FICL_ROBUST > 1
960ca987d46SWarner Losh     vmCheckStack(pVM, i+1, i+1);
961ca987d46SWarner Losh #endif
962ca987d46SWarner Losh     stackRoll(pVM->pStack, i);
963ca987d46SWarner Losh     return;
964ca987d46SWarner Losh }
965ca987d46SWarner Losh 
966ca987d46SWarner Losh 
minusRoll(FICL_VM * pVM)967ca987d46SWarner Losh static void minusRoll(FICL_VM *pVM)
968ca987d46SWarner Losh {
969ca987d46SWarner Losh     int i = stackPop(pVM->pStack).i;
970ca987d46SWarner Losh     i = (i > 0) ? i : 0;
971ca987d46SWarner Losh #if FICL_ROBUST > 1
972ca987d46SWarner Losh     vmCheckStack(pVM, i+1, i+1);
973ca987d46SWarner Losh #endif
974ca987d46SWarner Losh     stackRoll(pVM->pStack, -i);
975ca987d46SWarner Losh     return;
976ca987d46SWarner Losh }
977ca987d46SWarner Losh 
978ca987d46SWarner Losh 
rot(FICL_VM * pVM)979ca987d46SWarner Losh static void rot(FICL_VM *pVM)
980ca987d46SWarner Losh {
981ca987d46SWarner Losh #if FICL_ROBUST > 1
982ca987d46SWarner Losh     vmCheckStack(pVM, 3, 3);
983ca987d46SWarner Losh #endif
984ca987d46SWarner Losh     stackRoll(pVM->pStack, 2);
985ca987d46SWarner Losh     return;
986ca987d46SWarner Losh }
987ca987d46SWarner Losh 
988ca987d46SWarner Losh 
swap(FICL_VM * pVM)989ca987d46SWarner Losh static void swap(FICL_VM *pVM)
990ca987d46SWarner Losh {
991ca987d46SWarner Losh #if FICL_ROBUST > 1
992ca987d46SWarner Losh     vmCheckStack(pVM, 2, 2);
993ca987d46SWarner Losh #endif
994ca987d46SWarner Losh     stackRoll(pVM->pStack, 1);
995ca987d46SWarner Losh     return;
996ca987d46SWarner Losh }
997ca987d46SWarner Losh 
998ca987d46SWarner Losh 
twoSwap(FICL_VM * pVM)999ca987d46SWarner Losh static void twoSwap(FICL_VM *pVM)
1000ca987d46SWarner Losh {
1001ca987d46SWarner Losh #if FICL_ROBUST > 1
1002ca987d46SWarner Losh     vmCheckStack(pVM, 4, 4);
1003ca987d46SWarner Losh #endif
1004ca987d46SWarner Losh     stackRoll(pVM->pStack, 3);
1005ca987d46SWarner Losh     stackRoll(pVM->pStack, 3);
1006ca987d46SWarner Losh     return;
1007ca987d46SWarner Losh }
1008ca987d46SWarner Losh 
1009ca987d46SWarner Losh 
1010ca987d46SWarner Losh /**************************************************************************
1011ca987d46SWarner Losh                         e m i t   &   f r i e n d s
1012ca987d46SWarner Losh **
1013ca987d46SWarner Losh **************************************************************************/
1014ca987d46SWarner Losh 
emit(FICL_VM * pVM)1015ca987d46SWarner Losh static void emit(FICL_VM *pVM)
1016ca987d46SWarner Losh {
1017*dba7640eSToomas Soome     char cp[2];
1018ca987d46SWarner Losh     int i;
1019ca987d46SWarner Losh 
1020ca987d46SWarner Losh #if FICL_ROBUST > 1
1021ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
1022ca987d46SWarner Losh #endif
1023ca987d46SWarner Losh     i = stackPopINT(pVM->pStack);
1024ca987d46SWarner Losh     cp[0] = (char)i;
1025ca987d46SWarner Losh     cp[1] = '\0';
1026ca987d46SWarner Losh     vmTextOut(pVM, cp, 0);
1027ca987d46SWarner Losh     return;
1028ca987d46SWarner Losh }
1029ca987d46SWarner Losh 
1030ca987d46SWarner Losh 
cr(FICL_VM * pVM)1031ca987d46SWarner Losh static void cr(FICL_VM *pVM)
1032ca987d46SWarner Losh {
1033ca987d46SWarner Losh     vmTextOut(pVM, "", 1);
1034ca987d46SWarner Losh     return;
1035ca987d46SWarner Losh }
1036ca987d46SWarner Losh 
1037ca987d46SWarner Losh 
commentLine(FICL_VM * pVM)1038ca987d46SWarner Losh static void commentLine(FICL_VM *pVM)
1039ca987d46SWarner Losh {
1040ca987d46SWarner Losh     char *cp        = vmGetInBuf(pVM);
1041ca987d46SWarner Losh     char *pEnd      = vmGetInBufEnd(pVM);
1042ca987d46SWarner Losh     char ch = *cp;
1043ca987d46SWarner Losh 
1044ca987d46SWarner Losh     while ((cp != pEnd) && (ch != '\r') && (ch != '\n'))
1045ca987d46SWarner Losh     {
1046ca987d46SWarner Losh         ch = *++cp;
1047ca987d46SWarner Losh     }
1048ca987d46SWarner Losh 
1049ca987d46SWarner Losh     /*
1050ca987d46SWarner Losh     ** Cope with DOS or UNIX-style EOLs -
1051ca987d46SWarner Losh     ** Check for /r, /n, /r/n, or /n/r end-of-line sequences,
1052ca987d46SWarner Losh     ** and point cp to next char. If EOL is \0, we're done.
1053ca987d46SWarner Losh     */
1054ca987d46SWarner Losh     if (cp != pEnd)
1055ca987d46SWarner Losh     {
1056ca987d46SWarner Losh         cp++;
1057ca987d46SWarner Losh 
1058ca987d46SWarner Losh         if ( (cp != pEnd) && (ch != *cp)
1059ca987d46SWarner Losh              && ((*cp == '\r') || (*cp == '\n')) )
1060ca987d46SWarner Losh             cp++;
1061ca987d46SWarner Losh     }
1062ca987d46SWarner Losh 
1063ca987d46SWarner Losh     vmUpdateTib(pVM, cp);
1064ca987d46SWarner Losh     return;
1065ca987d46SWarner Losh }
1066ca987d46SWarner Losh 
1067ca987d46SWarner Losh 
1068ca987d46SWarner Losh /*
1069ca987d46SWarner Losh ** paren CORE
1070ca987d46SWarner Losh ** Compilation: Perform the execution semantics given below.
1071ca987d46SWarner Losh ** Execution: ( "ccc<paren>" -- )
1072ca987d46SWarner Losh ** Parse ccc delimited by ) (right parenthesis). ( is an immediate word.
1073ca987d46SWarner Losh ** The number of characters in ccc may be zero to the number of characters
1074ca987d46SWarner Losh ** in the parse area.
1075ca987d46SWarner Losh **
1076ca987d46SWarner Losh */
commentHang(FICL_VM * pVM)1077ca987d46SWarner Losh static void commentHang(FICL_VM *pVM)
1078ca987d46SWarner Losh {
1079ca987d46SWarner Losh     vmParseStringEx(pVM, ')', 0);
1080ca987d46SWarner Losh     return;
1081ca987d46SWarner Losh }
1082ca987d46SWarner Losh 
1083ca987d46SWarner Losh 
1084ca987d46SWarner Losh /**************************************************************************
1085ca987d46SWarner Losh                         F E T C H   &   S T O R E
1086ca987d46SWarner Losh **
1087ca987d46SWarner Losh **************************************************************************/
1088ca987d46SWarner Losh 
fetch(FICL_VM * pVM)1089ca987d46SWarner Losh static void fetch(FICL_VM *pVM)
1090ca987d46SWarner Losh {
1091ca987d46SWarner Losh     CELL *pCell;
1092ca987d46SWarner Losh #if FICL_ROBUST > 1
1093ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
1094ca987d46SWarner Losh #endif
1095ca987d46SWarner Losh     pCell = (CELL *)stackPopPtr(pVM->pStack);
1096ca987d46SWarner Losh     stackPush(pVM->pStack, *pCell);
1097ca987d46SWarner Losh     return;
1098ca987d46SWarner Losh }
1099ca987d46SWarner Losh 
1100ca987d46SWarner Losh /*
1101ca987d46SWarner Losh ** two-fetch    CORE ( a-addr -- x1 x2 )
1102ca987d46SWarner Losh ** Fetch the cell pair x1 x2 stored at a-addr. x2 is stored at a-addr and
1103ca987d46SWarner Losh ** x1 at the next consecutive cell. It is equivalent to the sequence
1104ca987d46SWarner Losh ** DUP CELL+ @ SWAP @ .
1105ca987d46SWarner Losh */
twoFetch(FICL_VM * pVM)1106ca987d46SWarner Losh static void twoFetch(FICL_VM *pVM)
1107ca987d46SWarner Losh {
1108ca987d46SWarner Losh     CELL *pCell;
1109ca987d46SWarner Losh #if FICL_ROBUST > 1
1110ca987d46SWarner Losh     vmCheckStack(pVM, 1, 2);
1111ca987d46SWarner Losh #endif
1112ca987d46SWarner Losh     pCell = (CELL *)stackPopPtr(pVM->pStack);
1113ca987d46SWarner Losh     stackPush(pVM->pStack, *pCell++);
1114ca987d46SWarner Losh     stackPush(pVM->pStack, *pCell);
1115ca987d46SWarner Losh     swap(pVM);
1116ca987d46SWarner Losh     return;
1117ca987d46SWarner Losh }
1118ca987d46SWarner Losh 
1119ca987d46SWarner Losh /*
1120ca987d46SWarner Losh ** store        CORE ( x a-addr -- )
1121ca987d46SWarner Losh ** Store x at a-addr.
1122ca987d46SWarner Losh */
store(FICL_VM * pVM)1123ca987d46SWarner Losh static void store(FICL_VM *pVM)
1124ca987d46SWarner Losh {
1125ca987d46SWarner Losh     CELL *pCell;
1126ca987d46SWarner Losh #if FICL_ROBUST > 1
1127ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
1128ca987d46SWarner Losh #endif
1129ca987d46SWarner Losh     pCell = (CELL *)stackPopPtr(pVM->pStack);
1130ca987d46SWarner Losh     *pCell = stackPop(pVM->pStack);
1131ca987d46SWarner Losh }
1132ca987d46SWarner Losh 
1133ca987d46SWarner Losh /*
1134ca987d46SWarner Losh ** two-store    CORE ( x1 x2 a-addr -- )
1135ca987d46SWarner Losh ** Store the cell pair x1 x2 at a-addr, with x2 at a-addr and x1 at the
1136ca987d46SWarner Losh ** next consecutive cell. It is equivalent to the sequence
1137ca987d46SWarner Losh ** SWAP OVER ! CELL+ ! .
1138ca987d46SWarner Losh */
twoStore(FICL_VM * pVM)1139ca987d46SWarner Losh static void twoStore(FICL_VM *pVM)
1140ca987d46SWarner Losh {
1141ca987d46SWarner Losh     CELL *pCell;
1142ca987d46SWarner Losh #if FICL_ROBUST > 1
1143ca987d46SWarner Losh     vmCheckStack(pVM, 3, 0);
1144ca987d46SWarner Losh #endif
1145ca987d46SWarner Losh     pCell = (CELL *)stackPopPtr(pVM->pStack);
1146ca987d46SWarner Losh     *pCell++    = stackPop(pVM->pStack);
1147ca987d46SWarner Losh     *pCell      = stackPop(pVM->pStack);
1148ca987d46SWarner Losh }
1149ca987d46SWarner Losh 
plusStore(FICL_VM * pVM)1150ca987d46SWarner Losh static void plusStore(FICL_VM *pVM)
1151ca987d46SWarner Losh {
1152ca987d46SWarner Losh     CELL *pCell;
1153ca987d46SWarner Losh #if FICL_ROBUST > 1
1154ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
1155ca987d46SWarner Losh #endif
1156ca987d46SWarner Losh     pCell = (CELL *)stackPopPtr(pVM->pStack);
1157ca987d46SWarner Losh     pCell->i += stackPop(pVM->pStack).i;
1158ca987d46SWarner Losh }
1159ca987d46SWarner Losh 
1160ca987d46SWarner Losh 
quadFetch(FICL_VM * pVM)1161ca987d46SWarner Losh static void quadFetch(FICL_VM *pVM)
1162ca987d46SWarner Losh {
1163ca987d46SWarner Losh     UNS32 *pw;
1164ca987d46SWarner Losh #if FICL_ROBUST > 1
1165ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
1166ca987d46SWarner Losh #endif
1167ca987d46SWarner Losh     pw = (UNS32 *)stackPopPtr(pVM->pStack);
1168ca987d46SWarner Losh     PUSHUNS((FICL_UNS)*pw);
1169ca987d46SWarner Losh     return;
1170ca987d46SWarner Losh }
1171ca987d46SWarner Losh 
quadStore(FICL_VM * pVM)1172ca987d46SWarner Losh static void quadStore(FICL_VM *pVM)
1173ca987d46SWarner Losh {
1174ca987d46SWarner Losh     UNS32 *pw;
1175ca987d46SWarner Losh #if FICL_ROBUST > 1
1176ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
1177ca987d46SWarner Losh #endif
1178ca987d46SWarner Losh     pw = (UNS32 *)stackPopPtr(pVM->pStack);
1179ca987d46SWarner Losh     *pw = (UNS32)(stackPop(pVM->pStack).u);
1180ca987d46SWarner Losh }
1181ca987d46SWarner Losh 
wFetch(FICL_VM * pVM)1182ca987d46SWarner Losh static void wFetch(FICL_VM *pVM)
1183ca987d46SWarner Losh {
1184ca987d46SWarner Losh     UNS16 *pw;
1185ca987d46SWarner Losh #if FICL_ROBUST > 1
1186ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
1187ca987d46SWarner Losh #endif
1188ca987d46SWarner Losh     pw = (UNS16 *)stackPopPtr(pVM->pStack);
1189ca987d46SWarner Losh     PUSHUNS((FICL_UNS)*pw);
1190ca987d46SWarner Losh     return;
1191ca987d46SWarner Losh }
1192ca987d46SWarner Losh 
wStore(FICL_VM * pVM)1193ca987d46SWarner Losh static void wStore(FICL_VM *pVM)
1194ca987d46SWarner Losh {
1195ca987d46SWarner Losh     UNS16 *pw;
1196ca987d46SWarner Losh #if FICL_ROBUST > 1
1197ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
1198ca987d46SWarner Losh #endif
1199ca987d46SWarner Losh     pw = (UNS16 *)stackPopPtr(pVM->pStack);
1200ca987d46SWarner Losh     *pw = (UNS16)(stackPop(pVM->pStack).u);
1201ca987d46SWarner Losh }
1202ca987d46SWarner Losh 
cFetch(FICL_VM * pVM)1203ca987d46SWarner Losh static void cFetch(FICL_VM *pVM)
1204ca987d46SWarner Losh {
1205ca987d46SWarner Losh     UNS8 *pc;
1206ca987d46SWarner Losh #if FICL_ROBUST > 1
1207ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
1208ca987d46SWarner Losh #endif
1209ca987d46SWarner Losh     pc = (UNS8 *)stackPopPtr(pVM->pStack);
1210ca987d46SWarner Losh     PUSHUNS((FICL_UNS)*pc);
1211ca987d46SWarner Losh     return;
1212ca987d46SWarner Losh }
1213ca987d46SWarner Losh 
cStore(FICL_VM * pVM)1214ca987d46SWarner Losh static void cStore(FICL_VM *pVM)
1215ca987d46SWarner Losh {
1216ca987d46SWarner Losh     UNS8 *pc;
1217ca987d46SWarner Losh #if FICL_ROBUST > 1
1218ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
1219ca987d46SWarner Losh #endif
1220ca987d46SWarner Losh     pc = (UNS8 *)stackPopPtr(pVM->pStack);
1221ca987d46SWarner Losh     *pc = (UNS8)(stackPop(pVM->pStack).u);
1222ca987d46SWarner Losh }
1223ca987d46SWarner Losh 
1224ca987d46SWarner Losh 
1225ca987d46SWarner Losh /**************************************************************************
1226ca987d46SWarner Losh                         b r a n c h P a r e n
1227ca987d46SWarner Losh **
1228ca987d46SWarner Losh ** Runtime for "(branch)" -- expects a literal offset in the next
1229ca987d46SWarner Losh ** compilation address, and branches to that location.
1230ca987d46SWarner Losh **************************************************************************/
1231ca987d46SWarner Losh 
branchParen(FICL_VM * pVM)1232ca987d46SWarner Losh static void branchParen(FICL_VM *pVM)
1233ca987d46SWarner Losh {
1234ca987d46SWarner Losh     vmBranchRelative(pVM, (uintptr_t)*(pVM->ip));
1235ca987d46SWarner Losh     return;
1236ca987d46SWarner Losh }
1237ca987d46SWarner Losh 
1238ca987d46SWarner Losh 
1239ca987d46SWarner Losh /**************************************************************************
1240ca987d46SWarner Losh                         b r a n c h 0
1241ca987d46SWarner Losh ** Runtime code for "(branch0)"; pop a flag from the stack,
1242ca987d46SWarner Losh ** branch if 0. fall through otherwise.  The heart of "if" and "until".
1243ca987d46SWarner Losh **************************************************************************/
1244ca987d46SWarner Losh 
branch0(FICL_VM * pVM)1245ca987d46SWarner Losh static void branch0(FICL_VM *pVM)
1246ca987d46SWarner Losh {
1247ca987d46SWarner Losh     FICL_UNS flag;
1248ca987d46SWarner Losh 
1249ca987d46SWarner Losh #if FICL_ROBUST > 1
1250ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
1251ca987d46SWarner Losh #endif
1252ca987d46SWarner Losh     flag = stackPopUNS(pVM->pStack);
1253ca987d46SWarner Losh 
1254ca987d46SWarner Losh     if (flag)
1255ca987d46SWarner Losh     {                           /* fall through */
1256ca987d46SWarner Losh         vmBranchRelative(pVM, 1);
1257ca987d46SWarner Losh     }
1258ca987d46SWarner Losh     else
1259ca987d46SWarner Losh     {                           /* take branch (to else/endif/begin) */
1260ca987d46SWarner Losh         vmBranchRelative(pVM, (uintptr_t)*(pVM->ip));
1261ca987d46SWarner Losh     }
1262ca987d46SWarner Losh 
1263ca987d46SWarner Losh     return;
1264ca987d46SWarner Losh }
1265ca987d46SWarner Losh 
1266ca987d46SWarner Losh 
1267ca987d46SWarner Losh /**************************************************************************
1268ca987d46SWarner Losh                         i f C o I m
1269ca987d46SWarner Losh ** IMMEDIATE COMPILE-ONLY
1270ca987d46SWarner Losh ** Compiles code for a conditional branch into the dictionary
1271ca987d46SWarner Losh ** and pushes the branch patch address on the stack for later
1272ca987d46SWarner Losh ** patching by ELSE or THEN/ENDIF.
1273ca987d46SWarner Losh **************************************************************************/
1274ca987d46SWarner Losh 
ifCoIm(FICL_VM * pVM)1275ca987d46SWarner Losh static void ifCoIm(FICL_VM *pVM)
1276ca987d46SWarner Losh {
1277ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
1278ca987d46SWarner Losh 
1279ca987d46SWarner Losh     assert(pVM->pSys->pBranch0);
1280ca987d46SWarner Losh 
1281ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranch0));
1282ca987d46SWarner Losh     markBranch(dp, pVM, origTag);
1283ca987d46SWarner Losh     dictAppendUNS(dp, 1);
1284ca987d46SWarner Losh     return;
1285ca987d46SWarner Losh }
1286ca987d46SWarner Losh 
1287ca987d46SWarner Losh 
1288ca987d46SWarner Losh /**************************************************************************
1289ca987d46SWarner Losh                         e l s e C o I m
1290ca987d46SWarner Losh **
1291ca987d46SWarner Losh ** IMMEDIATE COMPILE-ONLY
1292ca987d46SWarner Losh ** compiles an "else"...
1293ca987d46SWarner Losh ** 1) Compile a branch and a patch address; the address gets patched
1294ca987d46SWarner Losh **    by "endif" to point past the "else" code.
1295ca987d46SWarner Losh ** 2) Pop the "if" patch address
1296ca987d46SWarner Losh ** 3) Patch the "if" branch to point to the current compile address.
1297ca987d46SWarner Losh ** 4) Push the "else" patch address. ("endif" patches this to jump past
1298ca987d46SWarner Losh **    the "else" code.
1299ca987d46SWarner Losh **************************************************************************/
1300ca987d46SWarner Losh 
elseCoIm(FICL_VM * pVM)1301ca987d46SWarner Losh static void elseCoIm(FICL_VM *pVM)
1302ca987d46SWarner Losh {
1303ca987d46SWarner Losh     CELL *patchAddr;
1304ca987d46SWarner Losh     FICL_INT offset;
1305ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
1306ca987d46SWarner Losh 
1307ca987d46SWarner Losh     assert(pVM->pSys->pBranchParen);
1308ca987d46SWarner Losh                                             /* (1) compile branch runtime */
1309ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen));
1310ca987d46SWarner Losh     matchControlTag(pVM, origTag);
1311ca987d46SWarner Losh     patchAddr =
1312ca987d46SWarner Losh         (CELL *)stackPopPtr(pVM->pStack);   /* (2) pop "if" patch addr */
1313ca987d46SWarner Losh     markBranch(dp, pVM, origTag);           /* (4) push "else" patch addr */
1314ca987d46SWarner Losh     dictAppendUNS(dp, 1);                 /* (1) compile patch placeholder */
1315ca987d46SWarner Losh     offset = dp->here - patchAddr;
1316ca987d46SWarner Losh     *patchAddr = LVALUEtoCELL(offset);      /* (3) Patch "if" */
1317ca987d46SWarner Losh 
1318ca987d46SWarner Losh     return;
1319ca987d46SWarner Losh }
1320ca987d46SWarner Losh 
1321ca987d46SWarner Losh 
1322ca987d46SWarner Losh /**************************************************************************
1323ca987d46SWarner Losh                         e n d i f C o I m
1324ca987d46SWarner Losh ** IMMEDIATE COMPILE-ONLY
1325ca987d46SWarner Losh **************************************************************************/
1326ca987d46SWarner Losh 
endifCoIm(FICL_VM * pVM)1327ca987d46SWarner Losh static void endifCoIm(FICL_VM *pVM)
1328ca987d46SWarner Losh {
1329ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
1330ca987d46SWarner Losh     resolveForwardBranch(dp, pVM, origTag);
1331ca987d46SWarner Losh     return;
1332ca987d46SWarner Losh }
1333ca987d46SWarner Losh 
1334ca987d46SWarner Losh 
1335ca987d46SWarner Losh /**************************************************************************
1336ca987d46SWarner Losh                         c a s e C o I m
1337ca987d46SWarner Losh ** IMMEDIATE COMPILE-ONLY
1338ca987d46SWarner Losh **
1339ca987d46SWarner Losh **
1340ca987d46SWarner Losh ** At compile-time, a CASE-SYS (see DPANS94 6.2.0873) looks like this:
1341ca987d46SWarner Losh **			i*addr i caseTag
1342ca987d46SWarner Losh ** and an OF-SYS (see DPANS94 6.2.1950) looks like this:
1343ca987d46SWarner Losh **			i*addr i caseTag addr ofTag
1344ca987d46SWarner Losh ** The integer under caseTag is the count of fixup addresses that branch
1345ca987d46SWarner Losh ** to ENDCASE.
1346ca987d46SWarner Losh **************************************************************************/
1347ca987d46SWarner Losh 
caseCoIm(FICL_VM * pVM)1348ca987d46SWarner Losh static void caseCoIm(FICL_VM *pVM)
1349ca987d46SWarner Losh {
1350ca987d46SWarner Losh #if FICL_ROBUST > 1
1351ca987d46SWarner Losh     vmCheckStack(pVM, 0, 2);
1352ca987d46SWarner Losh #endif
1353ca987d46SWarner Losh 
1354ca987d46SWarner Losh 	PUSHUNS(0);
1355ca987d46SWarner Losh 	markControlTag(pVM, caseTag);
1356ca987d46SWarner Losh     return;
1357ca987d46SWarner Losh }
1358ca987d46SWarner Losh 
1359ca987d46SWarner Losh 
1360ca987d46SWarner Losh /**************************************************************************
1361ca987d46SWarner Losh                         e n d c a s eC o I m
1362ca987d46SWarner Losh ** IMMEDIATE COMPILE-ONLY
1363ca987d46SWarner Losh **************************************************************************/
1364ca987d46SWarner Losh 
endcaseCoIm(FICL_VM * pVM)1365ca987d46SWarner Losh static void endcaseCoIm(FICL_VM *pVM)
1366ca987d46SWarner Losh {
1367ca987d46SWarner Losh 	FICL_UNS fixupCount;
1368ca987d46SWarner Losh     FICL_DICT *dp;
1369ca987d46SWarner Losh     CELL *patchAddr;
1370ca987d46SWarner Losh     FICL_INT offset;
1371ca987d46SWarner Losh 
1372ca987d46SWarner Losh     assert(pVM->pSys->pDrop);
1373ca987d46SWarner Losh 
1374ca987d46SWarner Losh 	/*
1375ca987d46SWarner Losh 	** if the last OF ended with FALLTHROUGH,
1376ca987d46SWarner Losh 	** just add the FALLTHROUGH fixup to the
1377ca987d46SWarner Losh 	** ENDOF fixups
1378ca987d46SWarner Losh 	*/
1379ca987d46SWarner Losh 	if (stackGetTop(pVM->pStack).p == fallthroughTag)
1380ca987d46SWarner Losh 	{
1381ca987d46SWarner Losh 		matchControlTag(pVM, fallthroughTag);
1382ca987d46SWarner Losh 		patchAddr = POPPTR();
1383ca987d46SWarner Losh 	    matchControlTag(pVM, caseTag);
1384ca987d46SWarner Losh 		fixupCount = POPUNS();
1385ca987d46SWarner Losh 		PUSHPTR(patchAddr);
1386ca987d46SWarner Losh 		PUSHUNS(fixupCount + 1);
1387ca987d46SWarner Losh 		markControlTag(pVM, caseTag);
1388ca987d46SWarner Losh 	}
1389ca987d46SWarner Losh 
1390ca987d46SWarner Losh     matchControlTag(pVM, caseTag);
1391ca987d46SWarner Losh 
1392ca987d46SWarner Losh #if FICL_ROBUST > 1
1393ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
1394ca987d46SWarner Losh #endif
1395ca987d46SWarner Losh 	fixupCount = POPUNS();
1396ca987d46SWarner Losh #if FICL_ROBUST > 1
1397ca987d46SWarner Losh     vmCheckStack(pVM, fixupCount, 0);
1398ca987d46SWarner Losh #endif
1399ca987d46SWarner Losh 
1400ca987d46SWarner Losh     dp = vmGetDict(pVM);
1401ca987d46SWarner Losh 
1402ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pDrop));
1403ca987d46SWarner Losh 
1404ca987d46SWarner Losh 	while (fixupCount--)
1405ca987d46SWarner Losh 	{
1406ca987d46SWarner Losh 		patchAddr = (CELL *)stackPopPtr(pVM->pStack);
1407ca987d46SWarner Losh 		offset = dp->here - patchAddr;
1408ca987d46SWarner Losh 		*patchAddr = LVALUEtoCELL(offset);
1409ca987d46SWarner Losh 	}
1410ca987d46SWarner Losh     return;
1411ca987d46SWarner Losh }
1412ca987d46SWarner Losh 
1413ca987d46SWarner Losh 
ofParen(FICL_VM * pVM)1414ca987d46SWarner Losh static void ofParen(FICL_VM *pVM)
1415ca987d46SWarner Losh {
1416ca987d46SWarner Losh 	FICL_UNS a, b;
1417ca987d46SWarner Losh 
1418ca987d46SWarner Losh #if FICL_ROBUST > 1
1419ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
1420ca987d46SWarner Losh #endif
1421ca987d46SWarner Losh 
1422ca987d46SWarner Losh 	a = POPUNS();
1423ca987d46SWarner Losh 	b = stackGetTop(pVM->pStack).u;
1424ca987d46SWarner Losh 
1425ca987d46SWarner Losh     if (a == b)
1426ca987d46SWarner Losh     {                           /* fall through */
1427ca987d46SWarner Losh 		stackDrop(pVM->pStack, 1);
1428ca987d46SWarner Losh         vmBranchRelative(pVM, 1);
1429ca987d46SWarner Losh     }
1430ca987d46SWarner Losh     else
1431ca987d46SWarner Losh     {                           /* take branch to next of or endswitch */
1432ca987d46SWarner Losh         vmBranchRelative(pVM, *(int *)(pVM->ip));
1433ca987d46SWarner Losh     }
1434ca987d46SWarner Losh 
1435ca987d46SWarner Losh     return;
1436ca987d46SWarner Losh }
1437ca987d46SWarner Losh 
1438ca987d46SWarner Losh 
1439ca987d46SWarner Losh /**************************************************************************
1440ca987d46SWarner Losh                         o f C o I m
1441ca987d46SWarner Losh ** IMMEDIATE COMPILE-ONLY
1442ca987d46SWarner Losh **************************************************************************/
1443ca987d46SWarner Losh 
ofCoIm(FICL_VM * pVM)1444ca987d46SWarner Losh static void ofCoIm(FICL_VM *pVM)
1445ca987d46SWarner Losh {
1446ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
1447ca987d46SWarner Losh 	CELL *fallthroughFixup = NULL;
1448ca987d46SWarner Losh 
1449ca987d46SWarner Losh     assert(pVM->pSys->pBranch0);
1450ca987d46SWarner Losh 
1451ca987d46SWarner Losh #if FICL_ROBUST > 1
1452ca987d46SWarner Losh     vmCheckStack(pVM, 1, 3);
1453ca987d46SWarner Losh #endif
1454ca987d46SWarner Losh 
1455ca987d46SWarner Losh 	if (stackGetTop(pVM->pStack).p == fallthroughTag)
1456ca987d46SWarner Losh 	{
1457ca987d46SWarner Losh 		matchControlTag(pVM, fallthroughTag);
1458ca987d46SWarner Losh 		fallthroughFixup = POPPTR();
1459ca987d46SWarner Losh 	}
1460ca987d46SWarner Losh 
1461ca987d46SWarner Losh 	matchControlTag(pVM, caseTag);
1462ca987d46SWarner Losh 
1463ca987d46SWarner Losh 	markControlTag(pVM, caseTag);
1464ca987d46SWarner Losh 
1465ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pOfParen));
1466ca987d46SWarner Losh     markBranch(dp, pVM, ofTag);
1467ca987d46SWarner Losh     dictAppendUNS(dp, 2);
1468ca987d46SWarner Losh 
1469ca987d46SWarner Losh 	if (fallthroughFixup != NULL)
1470ca987d46SWarner Losh 	{
1471ca987d46SWarner Losh 		FICL_INT offset = dp->here - fallthroughFixup;
1472ca987d46SWarner Losh 		*fallthroughFixup = LVALUEtoCELL(offset);
1473ca987d46SWarner Losh 	}
1474ca987d46SWarner Losh 
1475ca987d46SWarner Losh     return;
1476ca987d46SWarner Losh }
1477ca987d46SWarner Losh 
1478ca987d46SWarner Losh 
1479ca987d46SWarner Losh /**************************************************************************
1480ca987d46SWarner Losh                     e n d o f C o I m
1481ca987d46SWarner Losh ** IMMEDIATE COMPILE-ONLY
1482ca987d46SWarner Losh **************************************************************************/
1483ca987d46SWarner Losh 
endofCoIm(FICL_VM * pVM)1484ca987d46SWarner Losh static void endofCoIm(FICL_VM *pVM)
1485ca987d46SWarner Losh {
1486ca987d46SWarner Losh     CELL *patchAddr;
1487ca987d46SWarner Losh     FICL_UNS fixupCount;
1488ca987d46SWarner Losh     FICL_INT offset;
1489ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
1490ca987d46SWarner Losh 
1491ca987d46SWarner Losh #if FICL_ROBUST > 1
1492ca987d46SWarner Losh     vmCheckStack(pVM, 4, 3);
1493ca987d46SWarner Losh #endif
1494ca987d46SWarner Losh 
1495ca987d46SWarner Losh     assert(pVM->pSys->pBranchParen);
1496ca987d46SWarner Losh 
1497ca987d46SWarner Losh 	/* ensure we're in an OF, */
1498ca987d46SWarner Losh     matchControlTag(pVM, ofTag);
1499ca987d46SWarner Losh 	/* grab the address of the branch location after the OF */
1500ca987d46SWarner Losh     patchAddr = (CELL *)stackPopPtr(pVM->pStack);
1501ca987d46SWarner Losh 	/* ensure we're also in a "case" */
1502ca987d46SWarner Losh     matchControlTag(pVM, caseTag);
1503ca987d46SWarner Losh 	/* grab the current number of ENDOF fixups */
1504ca987d46SWarner Losh 	fixupCount = POPUNS();
1505ca987d46SWarner Losh 
1506ca987d46SWarner Losh     /* compile branch runtime */
1507ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen));
1508ca987d46SWarner Losh 
1509ca987d46SWarner Losh 	/* push a new ENDOF fixup, the updated count of ENDOF fixups, and the caseTag */
1510ca987d46SWarner Losh     PUSHPTR(dp->here);
1511ca987d46SWarner Losh     PUSHUNS(fixupCount + 1);
1512ca987d46SWarner Losh 	markControlTag(pVM, caseTag);
1513ca987d46SWarner Losh 
1514ca987d46SWarner Losh 	/* reserve space for the ENDOF fixup */
1515ca987d46SWarner Losh     dictAppendUNS(dp, 2);
1516ca987d46SWarner Losh 
1517ca987d46SWarner Losh 	/* and patch the original OF */
1518ca987d46SWarner Losh     offset = dp->here - patchAddr;
1519ca987d46SWarner Losh     *patchAddr = LVALUEtoCELL(offset);
1520ca987d46SWarner Losh }
1521ca987d46SWarner Losh 
1522ca987d46SWarner Losh 
1523ca987d46SWarner Losh /**************************************************************************
1524ca987d46SWarner Losh                     f a l l t h r o u g h C o I m
1525ca987d46SWarner Losh ** IMMEDIATE COMPILE-ONLY
1526ca987d46SWarner Losh **************************************************************************/
1527ca987d46SWarner Losh 
fallthroughCoIm(FICL_VM * pVM)1528ca987d46SWarner Losh static void fallthroughCoIm(FICL_VM *pVM)
1529ca987d46SWarner Losh {
1530ca987d46SWarner Losh     CELL *patchAddr;
1531ca987d46SWarner Losh     FICL_INT offset;
1532ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
1533ca987d46SWarner Losh 
1534ca987d46SWarner Losh #if FICL_ROBUST > 1
1535ca987d46SWarner Losh     vmCheckStack(pVM, 4, 3);
1536ca987d46SWarner Losh #endif
1537ca987d46SWarner Losh 
1538ca987d46SWarner Losh 	/* ensure we're in an OF, */
1539ca987d46SWarner Losh     matchControlTag(pVM, ofTag);
1540ca987d46SWarner Losh 	/* grab the address of the branch location after the OF */
1541ca987d46SWarner Losh     patchAddr = (CELL *)stackPopPtr(pVM->pStack);
1542ca987d46SWarner Losh 	/* ensure we're also in a "case" */
1543ca987d46SWarner Losh     matchControlTag(pVM, caseTag);
1544ca987d46SWarner Losh 
1545ca987d46SWarner Losh 	/* okay, here we go.  put the case tag back. */
1546ca987d46SWarner Losh 	markControlTag(pVM, caseTag);
1547ca987d46SWarner Losh 
1548ca987d46SWarner Losh     /* compile branch runtime */
1549ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen));
1550ca987d46SWarner Losh 
1551ca987d46SWarner Losh 	/* push a new FALLTHROUGH fixup and the fallthroughTag */
1552ca987d46SWarner Losh     PUSHPTR(dp->here);
1553ca987d46SWarner Losh 	markControlTag(pVM, fallthroughTag);
1554ca987d46SWarner Losh 
1555ca987d46SWarner Losh 	/* reserve space for the FALLTHROUGH fixup */
1556ca987d46SWarner Losh     dictAppendUNS(dp, 2);
1557ca987d46SWarner Losh 
1558ca987d46SWarner Losh 	/* and patch the original OF */
1559ca987d46SWarner Losh     offset = dp->here - patchAddr;
1560ca987d46SWarner Losh     *patchAddr = LVALUEtoCELL(offset);
1561ca987d46SWarner Losh }
1562ca987d46SWarner Losh 
1563ca987d46SWarner Losh /**************************************************************************
1564ca987d46SWarner Losh                         h a s h
1565ca987d46SWarner Losh ** hash ( c-addr u -- code)
1566ca987d46SWarner Losh ** calculates hashcode of specified string and leaves it on the stack
1567ca987d46SWarner Losh **************************************************************************/
1568ca987d46SWarner Losh 
hash(FICL_VM * pVM)1569ca987d46SWarner Losh static void hash(FICL_VM *pVM)
1570ca987d46SWarner Losh {
1571ca987d46SWarner Losh     STRINGINFO si;
1572ca987d46SWarner Losh     SI_SETLEN(si, stackPopUNS(pVM->pStack));
1573ca987d46SWarner Losh     SI_SETPTR(si, stackPopPtr(pVM->pStack));
1574ca987d46SWarner Losh     PUSHUNS(hashHashCode(si));
1575ca987d46SWarner Losh     return;
1576ca987d46SWarner Losh }
1577ca987d46SWarner Losh 
1578ca987d46SWarner Losh 
1579ca987d46SWarner Losh /**************************************************************************
1580ca987d46SWarner Losh                         i n t e r p r e t
1581ca987d46SWarner Losh ** This is the "user interface" of a Forth. It does the following:
1582ca987d46SWarner Losh **   while there are words in the VM's Text Input Buffer
1583ca987d46SWarner Losh **     Copy next word into the pad (vmGetWord)
1584ca987d46SWarner Losh **     Attempt to find the word in the dictionary (dictLookup)
1585ca987d46SWarner Losh **     If successful, execute the word.
1586ca987d46SWarner Losh **     Otherwise, attempt to convert the word to a number (isNumber)
1587ca987d46SWarner Losh **     If successful, push the number onto the parameter stack.
1588ca987d46SWarner Losh **     Otherwise, print an error message and exit loop...
1589ca987d46SWarner Losh **   End Loop
1590ca987d46SWarner Losh **
1591ca987d46SWarner Losh ** From the standard, section 3.4
1592ca987d46SWarner Losh ** Text interpretation (see 6.1.1360 EVALUATE and 6.1.2050 QUIT) shall
1593ca987d46SWarner Losh ** repeat the following steps until either the parse area is empty or an
1594ca987d46SWarner Losh ** ambiguous condition exists:
1595ca987d46SWarner Losh ** a) Skip leading spaces and parse a name (see 3.4.1);
1596ca987d46SWarner Losh **************************************************************************/
1597ca987d46SWarner Losh 
interpret(FICL_VM * pVM)1598ca987d46SWarner Losh static void interpret(FICL_VM *pVM)
1599ca987d46SWarner Losh {
1600ca987d46SWarner Losh     STRINGINFO si;
1601ca987d46SWarner Losh     int i;
1602ca987d46SWarner Losh     FICL_SYSTEM *pSys;
1603ca987d46SWarner Losh 
1604ca987d46SWarner Losh     assert(pVM);
1605ca987d46SWarner Losh 
1606ca987d46SWarner Losh     pSys = pVM->pSys;
1607ca987d46SWarner Losh     si   = vmGetWord0(pVM);
1608ca987d46SWarner Losh 
1609ca987d46SWarner Losh     /*
1610ca987d46SWarner Losh     ** Get next word...if out of text, we're done.
1611ca987d46SWarner Losh     */
1612ca987d46SWarner Losh     if (si.count == 0)
1613ca987d46SWarner Losh     {
1614ca987d46SWarner Losh         vmThrow(pVM, VM_OUTOFTEXT);
1615ca987d46SWarner Losh     }
1616ca987d46SWarner Losh 
1617ca987d46SWarner Losh     /*
1618ca987d46SWarner Losh     ** Attempt to find the incoming token in the dictionary. If that fails...
1619ca987d46SWarner Losh     ** run the parse chain against the incoming token until somebody eats it.
1620ca987d46SWarner Losh     ** Otherwise emit an error message and give up.
1621ca987d46SWarner Losh     ** Although ficlParseWord could be part of the parse list, I've hard coded it
1622ca987d46SWarner Losh     ** in for robustness. ficlInitSystem adds the other default steps to the list.
1623ca987d46SWarner Losh     */
1624ca987d46SWarner Losh     if (ficlParseWord(pVM, si))
1625ca987d46SWarner Losh         return;
1626ca987d46SWarner Losh 
1627ca987d46SWarner Losh     for (i=0; i < FICL_MAX_PARSE_STEPS; i++)
1628ca987d46SWarner Losh     {
1629ca987d46SWarner Losh         FICL_WORD *pFW = pSys->parseList[i];
1630ca987d46SWarner Losh 
1631ca987d46SWarner Losh         if (pFW == NULL)
1632ca987d46SWarner Losh             break;
1633ca987d46SWarner Losh 
1634ca987d46SWarner Losh         if (pFW->code == parseStepParen)
1635ca987d46SWarner Losh         {
1636ca987d46SWarner Losh             FICL_PARSE_STEP pStep;
1637ca987d46SWarner Losh             pStep = (FICL_PARSE_STEP)(pFW->param->fn);
1638ca987d46SWarner Losh             if ((*pStep)(pVM, si))
1639ca987d46SWarner Losh                 return;
1640ca987d46SWarner Losh         }
1641ca987d46SWarner Losh         else
1642ca987d46SWarner Losh         {
1643ca987d46SWarner Losh             stackPushPtr(pVM->pStack, SI_PTR(si));
1644ca987d46SWarner Losh             stackPushUNS(pVM->pStack, SI_COUNT(si));
1645ca987d46SWarner Losh             ficlExecXT(pVM, pFW);
1646ca987d46SWarner Losh             if (stackPopINT(pVM->pStack))
1647ca987d46SWarner Losh                 return;
1648ca987d46SWarner Losh         }
1649ca987d46SWarner Losh     }
1650ca987d46SWarner Losh 
1651ca987d46SWarner Losh     i = SI_COUNT(si);
1652ca987d46SWarner Losh     vmThrowErr(pVM, "%.*s not found", i, SI_PTR(si));
1653ca987d46SWarner Losh 
1654ca987d46SWarner Losh     return;                 /* back to inner interpreter */
1655ca987d46SWarner Losh }
1656ca987d46SWarner Losh 
1657ca987d46SWarner Losh 
1658ca987d46SWarner Losh /**************************************************************************
1659ca987d46SWarner Losh                         f i c l P a r s e W o r d
1660ca987d46SWarner Losh ** From the standard, section 3.4
1661ca987d46SWarner Losh ** b) Search the dictionary name space (see 3.4.2). If a definition name
1662ca987d46SWarner Losh ** matching the string is found:
1663ca987d46SWarner Losh **  1.if interpreting, perform the interpretation semantics of the definition
1664ca987d46SWarner Losh **  (see 3.4.3.2), and continue at a);
1665ca987d46SWarner Losh **  2.if compiling, perform the compilation semantics of the definition
1666ca987d46SWarner Losh **  (see 3.4.3.3), and continue at a).
1667ca987d46SWarner Losh **
1668ca987d46SWarner Losh ** c) If a definition name matching the string is not found, attempt to
1669ca987d46SWarner Losh ** convert the string to a number (see 3.4.1.3). If successful:
1670ca987d46SWarner Losh **  1.if interpreting, place the number on the data stack, and continue at a);
1671ca987d46SWarner Losh **  2.if compiling, compile code that when executed will place the number on
1672ca987d46SWarner Losh **  the stack (see 6.1.1780 LITERAL), and continue at a);
1673ca987d46SWarner Losh **
1674ca987d46SWarner Losh ** d) If unsuccessful, an ambiguous condition exists (see 3.4.4).
1675ca987d46SWarner Losh **
1676ca987d46SWarner Losh ** (jws 4/01) Modified to be a FICL_PARSE_STEP
1677ca987d46SWarner Losh **************************************************************************/
ficlParseWord(FICL_VM * pVM,STRINGINFO si)1678ca987d46SWarner Losh static int ficlParseWord(FICL_VM *pVM, STRINGINFO si)
1679ca987d46SWarner Losh {
1680ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
1681ca987d46SWarner Losh     FICL_WORD *tempFW;
1682ca987d46SWarner Losh 
1683ca987d46SWarner Losh #if FICL_ROBUST
1684ca987d46SWarner Losh     dictCheck(dp, pVM, 0);
1685ca987d46SWarner Losh     vmCheckStack(pVM, 0, 0);
1686ca987d46SWarner Losh #endif
1687ca987d46SWarner Losh 
1688ca987d46SWarner Losh #if FICL_WANT_LOCALS
1689ca987d46SWarner Losh     if (pVM->pSys->nLocals > 0)
1690ca987d46SWarner Losh     {
1691ca987d46SWarner Losh         tempFW = ficlLookupLoc(pVM->pSys, si);
1692ca987d46SWarner Losh     }
1693ca987d46SWarner Losh     else
1694ca987d46SWarner Losh #endif
1695ca987d46SWarner Losh     tempFW = dictLookup(dp, si);
1696ca987d46SWarner Losh 
1697ca987d46SWarner Losh     if (pVM->state == INTERPRET)
1698ca987d46SWarner Losh     {
1699ca987d46SWarner Losh         if (tempFW != NULL)
1700ca987d46SWarner Losh         {
1701ca987d46SWarner Losh             if (wordIsCompileOnly(tempFW))
1702ca987d46SWarner Losh             {
1703ca987d46SWarner Losh                 vmThrowErr(pVM, "Error: Compile only!");
1704ca987d46SWarner Losh             }
1705ca987d46SWarner Losh 
1706ca987d46SWarner Losh             vmExecute(pVM, tempFW);
1707ca987d46SWarner Losh             return (int)FICL_TRUE;
1708ca987d46SWarner Losh         }
1709ca987d46SWarner Losh     }
1710ca987d46SWarner Losh 
1711ca987d46SWarner Losh     else /* (pVM->state == COMPILE) */
1712ca987d46SWarner Losh     {
1713ca987d46SWarner Losh         if (tempFW != NULL)
1714ca987d46SWarner Losh         {
1715ca987d46SWarner Losh             if (wordIsImmediate(tempFW))
1716ca987d46SWarner Losh             {
1717ca987d46SWarner Losh                 vmExecute(pVM, tempFW);
1718ca987d46SWarner Losh             }
1719ca987d46SWarner Losh             else
1720ca987d46SWarner Losh             {
1721ca987d46SWarner Losh                 dictAppendCell(dp, LVALUEtoCELL(tempFW));
1722ca987d46SWarner Losh             }
1723ca987d46SWarner Losh             return (int)FICL_TRUE;
1724ca987d46SWarner Losh         }
1725ca987d46SWarner Losh     }
1726ca987d46SWarner Losh 
1727ca987d46SWarner Losh     return FICL_FALSE;
1728ca987d46SWarner Losh }
1729ca987d46SWarner Losh 
1730ca987d46SWarner Losh 
1731ca987d46SWarner Losh /*
1732ca987d46SWarner Losh ** Surrogate precompiled parse step for ficlParseWord (this step is hard coded in
1733ca987d46SWarner Losh ** INTERPRET)
1734ca987d46SWarner Losh */
lookup(FICL_VM * pVM)1735ca987d46SWarner Losh static void lookup(FICL_VM *pVM)
1736ca987d46SWarner Losh {
1737ca987d46SWarner Losh     STRINGINFO si;
1738ca987d46SWarner Losh     SI_SETLEN(si, stackPopUNS(pVM->pStack));
1739ca987d46SWarner Losh     SI_SETPTR(si, stackPopPtr(pVM->pStack));
1740ca987d46SWarner Losh     stackPushINT(pVM->pStack, ficlParseWord(pVM, si));
1741ca987d46SWarner Losh     return;
1742ca987d46SWarner Losh }
1743ca987d46SWarner Losh 
1744ca987d46SWarner Losh 
1745ca987d46SWarner Losh /**************************************************************************
1746ca987d46SWarner Losh                         p a r e n P a r s e S t e p
1747ca987d46SWarner Losh ** (parse-step)  ( c-addr u -- flag )
1748ca987d46SWarner Losh ** runtime for a precompiled parse step - pop a counted string off the
1749ca987d46SWarner Losh ** stack, run the parse step against it, and push the result flag (FICL_TRUE
1750ca987d46SWarner Losh ** if success, FICL_FALSE otherwise).
1751ca987d46SWarner Losh **************************************************************************/
1752ca987d46SWarner Losh 
parseStepParen(FICL_VM * pVM)1753ca987d46SWarner Losh void parseStepParen(FICL_VM *pVM)
1754ca987d46SWarner Losh {
1755ca987d46SWarner Losh     STRINGINFO si;
1756ca987d46SWarner Losh     FICL_WORD *pFW = pVM->runningWord;
1757ca987d46SWarner Losh     FICL_PARSE_STEP pStep = (FICL_PARSE_STEP)(pFW->param->fn);
1758ca987d46SWarner Losh 
1759ca987d46SWarner Losh     SI_SETLEN(si, stackPopINT(pVM->pStack));
1760ca987d46SWarner Losh     SI_SETPTR(si, stackPopPtr(pVM->pStack));
1761ca987d46SWarner Losh 
1762ca987d46SWarner Losh     PUSHINT((*pStep)(pVM, si));
1763ca987d46SWarner Losh 
1764ca987d46SWarner Losh     return;
1765ca987d46SWarner Losh }
1766ca987d46SWarner Losh 
1767ca987d46SWarner Losh 
addParseStep(FICL_VM * pVM)1768ca987d46SWarner Losh static void addParseStep(FICL_VM *pVM)
1769ca987d46SWarner Losh {
1770ca987d46SWarner Losh     FICL_WORD *pStep;
1771ca987d46SWarner Losh     FICL_DICT *pd = vmGetDict(pVM);
1772ca987d46SWarner Losh #if FICL_ROBUST > 1
1773ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
1774ca987d46SWarner Losh #endif
1775ca987d46SWarner Losh     pStep = (FICL_WORD *)(stackPop(pVM->pStack).p);
1776ca987d46SWarner Losh     if ((pStep != NULL) && isAFiclWord(pd, pStep))
1777ca987d46SWarner Losh         ficlAddParseStep(pVM->pSys, pStep);
1778ca987d46SWarner Losh     return;
1779ca987d46SWarner Losh }
1780ca987d46SWarner Losh 
1781ca987d46SWarner Losh 
1782ca987d46SWarner Losh /**************************************************************************
1783ca987d46SWarner Losh                         l i t e r a l P a r e n
1784ca987d46SWarner Losh **
1785ca987d46SWarner Losh ** This is the runtime for (literal). It assumes that it is part of a colon
1786ca987d46SWarner Losh ** definition, and that the next CELL contains a value to be pushed on the
1787ca987d46SWarner Losh ** parameter stack at runtime. This code is compiled by "literal".
1788ca987d46SWarner Losh **
1789ca987d46SWarner Losh **************************************************************************/
1790ca987d46SWarner Losh 
literalParen(FICL_VM * pVM)1791ca987d46SWarner Losh static void literalParen(FICL_VM *pVM)
1792ca987d46SWarner Losh {
1793ca987d46SWarner Losh #if FICL_ROBUST > 1
1794ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
1795ca987d46SWarner Losh #endif
1796ca987d46SWarner Losh     PUSHINT(*(FICL_INT *)(pVM->ip));
1797ca987d46SWarner Losh     vmBranchRelative(pVM, 1);
1798ca987d46SWarner Losh     return;
1799ca987d46SWarner Losh }
1800ca987d46SWarner Losh 
twoLitParen(FICL_VM * pVM)1801ca987d46SWarner Losh static void twoLitParen(FICL_VM *pVM)
1802ca987d46SWarner Losh {
1803ca987d46SWarner Losh #if FICL_ROBUST > 1
1804ca987d46SWarner Losh     vmCheckStack(pVM, 0, 2);
1805ca987d46SWarner Losh #endif
1806ca987d46SWarner Losh     PUSHINT(*((FICL_INT *)(pVM->ip)+1));
1807ca987d46SWarner Losh     PUSHINT(*(FICL_INT *)(pVM->ip));
1808ca987d46SWarner Losh     vmBranchRelative(pVM, 2);
1809ca987d46SWarner Losh     return;
1810ca987d46SWarner Losh }
1811ca987d46SWarner Losh 
1812ca987d46SWarner Losh 
1813ca987d46SWarner Losh /**************************************************************************
1814ca987d46SWarner Losh                         l i t e r a l I m
1815ca987d46SWarner Losh **
1816ca987d46SWarner Losh ** IMMEDIATE code for "literal". This function gets a value from the stack
1817ca987d46SWarner Losh ** and compiles it into the dictionary preceded by the code for "(literal)".
1818ca987d46SWarner Losh ** IMMEDIATE
1819ca987d46SWarner Losh **************************************************************************/
1820ca987d46SWarner Losh 
literalIm(FICL_VM * pVM)1821ca987d46SWarner Losh static void literalIm(FICL_VM *pVM)
1822ca987d46SWarner Losh {
1823ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
1824ca987d46SWarner Losh     assert(pVM->pSys->pLitParen);
1825ca987d46SWarner Losh 
1826ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pLitParen));
1827ca987d46SWarner Losh     dictAppendCell(dp, stackPop(pVM->pStack));
1828ca987d46SWarner Losh 
1829ca987d46SWarner Losh     return;
1830ca987d46SWarner Losh }
1831ca987d46SWarner Losh 
1832ca987d46SWarner Losh 
twoLiteralIm(FICL_VM * pVM)1833ca987d46SWarner Losh static void twoLiteralIm(FICL_VM *pVM)
1834ca987d46SWarner Losh {
1835ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
1836ca987d46SWarner Losh     assert(pVM->pSys->pTwoLitParen);
1837ca987d46SWarner Losh 
1838ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pTwoLitParen));
1839ca987d46SWarner Losh     dictAppendCell(dp, stackPop(pVM->pStack));
1840ca987d46SWarner Losh     dictAppendCell(dp, stackPop(pVM->pStack));
1841ca987d46SWarner Losh 
1842ca987d46SWarner Losh     return;
1843ca987d46SWarner Losh }
1844ca987d46SWarner Losh 
1845ca987d46SWarner Losh /**************************************************************************
1846ca987d46SWarner Losh                         l o g i c   a n d   c o m p a r i s o n s
1847ca987d46SWarner Losh **
1848ca987d46SWarner Losh **************************************************************************/
1849ca987d46SWarner Losh 
zeroEquals(FICL_VM * pVM)1850ca987d46SWarner Losh static void zeroEquals(FICL_VM *pVM)
1851ca987d46SWarner Losh {
1852ca987d46SWarner Losh     CELL c;
1853ca987d46SWarner Losh #if FICL_ROBUST > 1
1854ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
1855ca987d46SWarner Losh #endif
1856ca987d46SWarner Losh     c.i = FICL_BOOL(stackPopINT(pVM->pStack) == 0);
1857ca987d46SWarner Losh     stackPush(pVM->pStack, c);
1858ca987d46SWarner Losh     return;
1859ca987d46SWarner Losh }
1860ca987d46SWarner Losh 
zeroLess(FICL_VM * pVM)1861ca987d46SWarner Losh static void zeroLess(FICL_VM *pVM)
1862ca987d46SWarner Losh {
1863ca987d46SWarner Losh     CELL c;
1864ca987d46SWarner Losh #if FICL_ROBUST > 1
1865ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
1866ca987d46SWarner Losh #endif
1867ca987d46SWarner Losh     c.i = FICL_BOOL(stackPopINT(pVM->pStack) < 0);
1868ca987d46SWarner Losh     stackPush(pVM->pStack, c);
1869ca987d46SWarner Losh     return;
1870ca987d46SWarner Losh }
1871ca987d46SWarner Losh 
zeroGreater(FICL_VM * pVM)1872ca987d46SWarner Losh static void zeroGreater(FICL_VM *pVM)
1873ca987d46SWarner Losh {
1874ca987d46SWarner Losh     CELL c;
1875ca987d46SWarner Losh #if FICL_ROBUST > 1
1876ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
1877ca987d46SWarner Losh #endif
1878ca987d46SWarner Losh     c.i = FICL_BOOL(stackPopINT(pVM->pStack) > 0);
1879ca987d46SWarner Losh     stackPush(pVM->pStack, c);
1880ca987d46SWarner Losh     return;
1881ca987d46SWarner Losh }
1882ca987d46SWarner Losh 
isEqual(FICL_VM * pVM)1883ca987d46SWarner Losh static void isEqual(FICL_VM *pVM)
1884ca987d46SWarner Losh {
1885ca987d46SWarner Losh     CELL x, y;
1886ca987d46SWarner Losh 
1887ca987d46SWarner Losh #if FICL_ROBUST > 1
1888ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
1889ca987d46SWarner Losh #endif
1890ca987d46SWarner Losh     x = stackPop(pVM->pStack);
1891ca987d46SWarner Losh     y = stackPop(pVM->pStack);
1892ca987d46SWarner Losh     PUSHINT(FICL_BOOL(x.i == y.i));
1893ca987d46SWarner Losh     return;
1894ca987d46SWarner Losh }
1895ca987d46SWarner Losh 
isLess(FICL_VM * pVM)1896ca987d46SWarner Losh static void isLess(FICL_VM *pVM)
1897ca987d46SWarner Losh {
1898ca987d46SWarner Losh     CELL x, y;
1899ca987d46SWarner Losh #if FICL_ROBUST > 1
1900ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
1901ca987d46SWarner Losh #endif
1902ca987d46SWarner Losh     y = stackPop(pVM->pStack);
1903ca987d46SWarner Losh     x = stackPop(pVM->pStack);
1904ca987d46SWarner Losh     PUSHINT(FICL_BOOL(x.i < y.i));
1905ca987d46SWarner Losh     return;
1906ca987d46SWarner Losh }
1907ca987d46SWarner Losh 
uIsLess(FICL_VM * pVM)1908ca987d46SWarner Losh static void uIsLess(FICL_VM *pVM)
1909ca987d46SWarner Losh {
1910ca987d46SWarner Losh     FICL_UNS u1, u2;
1911ca987d46SWarner Losh #if FICL_ROBUST > 1
1912ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
1913ca987d46SWarner Losh #endif
1914ca987d46SWarner Losh     u2 = stackPopUNS(pVM->pStack);
1915ca987d46SWarner Losh     u1 = stackPopUNS(pVM->pStack);
1916ca987d46SWarner Losh     PUSHINT(FICL_BOOL(u1 < u2));
1917ca987d46SWarner Losh     return;
1918ca987d46SWarner Losh }
1919ca987d46SWarner Losh 
isGreater(FICL_VM * pVM)1920ca987d46SWarner Losh static void isGreater(FICL_VM *pVM)
1921ca987d46SWarner Losh {
1922ca987d46SWarner Losh     CELL x, y;
1923ca987d46SWarner Losh #if FICL_ROBUST > 1
1924ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
1925ca987d46SWarner Losh #endif
1926ca987d46SWarner Losh     y = stackPop(pVM->pStack);
1927ca987d46SWarner Losh     x = stackPop(pVM->pStack);
1928ca987d46SWarner Losh     PUSHINT(FICL_BOOL(x.i > y.i));
1929ca987d46SWarner Losh     return;
1930ca987d46SWarner Losh }
1931ca987d46SWarner Losh 
uIsGreater(FICL_VM * pVM)19320bd5d367SToomas Soome static void uIsGreater(FICL_VM *pVM)
19330bd5d367SToomas Soome {
19340bd5d367SToomas Soome     FICL_UNS u1, u2;
19350bd5d367SToomas Soome #if FICL_ROBUST > 1
19360bd5d367SToomas Soome     vmCheckStack(pVM, 2, 1);
19370bd5d367SToomas Soome #endif
19380bd5d367SToomas Soome     u2 = stackPopUNS(pVM->pStack);
19390bd5d367SToomas Soome     u1 = stackPopUNS(pVM->pStack);
19400bd5d367SToomas Soome     PUSHINT(FICL_BOOL(u1 > u2));
19410bd5d367SToomas Soome     return;
19420bd5d367SToomas Soome }
19430bd5d367SToomas Soome 
bitwiseAnd(FICL_VM * pVM)1944ca987d46SWarner Losh static void bitwiseAnd(FICL_VM *pVM)
1945ca987d46SWarner Losh {
1946ca987d46SWarner Losh     CELL x, y;
1947ca987d46SWarner Losh #if FICL_ROBUST > 1
1948ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
1949ca987d46SWarner Losh #endif
1950ca987d46SWarner Losh     x = stackPop(pVM->pStack);
1951ca987d46SWarner Losh     y = stackPop(pVM->pStack);
1952ca987d46SWarner Losh     PUSHINT(x.i & y.i);
1953ca987d46SWarner Losh     return;
1954ca987d46SWarner Losh }
1955ca987d46SWarner Losh 
bitwiseOr(FICL_VM * pVM)1956ca987d46SWarner Losh static void bitwiseOr(FICL_VM *pVM)
1957ca987d46SWarner Losh {
1958ca987d46SWarner Losh     CELL x, y;
1959ca987d46SWarner Losh #if FICL_ROBUST > 1
1960ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
1961ca987d46SWarner Losh #endif
1962ca987d46SWarner Losh     x = stackPop(pVM->pStack);
1963ca987d46SWarner Losh     y = stackPop(pVM->pStack);
1964ca987d46SWarner Losh     PUSHINT(x.i | y.i);
1965ca987d46SWarner Losh     return;
1966ca987d46SWarner Losh }
1967ca987d46SWarner Losh 
bitwiseXor(FICL_VM * pVM)1968ca987d46SWarner Losh static void bitwiseXor(FICL_VM *pVM)
1969ca987d46SWarner Losh {
1970ca987d46SWarner Losh     CELL x, y;
1971ca987d46SWarner Losh #if FICL_ROBUST > 1
1972ca987d46SWarner Losh     vmCheckStack(pVM, 2, 1);
1973ca987d46SWarner Losh #endif
1974ca987d46SWarner Losh     x = stackPop(pVM->pStack);
1975ca987d46SWarner Losh     y = stackPop(pVM->pStack);
1976ca987d46SWarner Losh     PUSHINT(x.i ^ y.i);
1977ca987d46SWarner Losh     return;
1978ca987d46SWarner Losh }
1979ca987d46SWarner Losh 
bitwiseNot(FICL_VM * pVM)1980ca987d46SWarner Losh static void bitwiseNot(FICL_VM *pVM)
1981ca987d46SWarner Losh {
1982ca987d46SWarner Losh     CELL x;
1983ca987d46SWarner Losh #if FICL_ROBUST > 1
1984ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
1985ca987d46SWarner Losh #endif
1986ca987d46SWarner Losh     x = stackPop(pVM->pStack);
1987ca987d46SWarner Losh     PUSHINT(~x.i);
1988ca987d46SWarner Losh     return;
1989ca987d46SWarner Losh }
1990ca987d46SWarner Losh 
1991ca987d46SWarner Losh 
1992ca987d46SWarner Losh /**************************************************************************
1993ca987d46SWarner Losh                                D o  /  L o o p
1994ca987d46SWarner Losh ** do -- IMMEDIATE COMPILE ONLY
1995ca987d46SWarner Losh **    Compiles code to initialize a loop: compile (do),
1996ca987d46SWarner Losh **    allot space to hold the "leave" address, push a branch
1997ca987d46SWarner Losh **    target address for the loop.
1998ca987d46SWarner Losh ** (do) -- runtime for "do"
1999ca987d46SWarner Losh **    pops index and limit from the p stack and moves them
2000ca987d46SWarner Losh **    to the r stack, then skips to the loop body.
2001ca987d46SWarner Losh ** loop -- IMMEDIATE COMPILE ONLY
2002ca987d46SWarner Losh ** +loop
2003ca987d46SWarner Losh **    Compiles code for the test part of a loop:
2004ca987d46SWarner Losh **    compile (loop), resolve forward branch from "do", and
2005ca987d46SWarner Losh **    copy "here" address to the "leave" address allotted by "do"
2006ca987d46SWarner Losh ** i,j,k -- COMPILE ONLY
2007ca987d46SWarner Losh **    Runtime: Push loop indices on param stack (i is innermost loop...)
2008ca987d46SWarner Losh **    Note: each loop has three values on the return stack:
2009ca987d46SWarner Losh **    ( R: leave limit index )
2010ca987d46SWarner Losh **    "leave" is the absolute address of the next cell after the loop
2011ca987d46SWarner Losh **    limit and index are the loop control variables.
2012ca987d46SWarner Losh ** leave -- COMPILE ONLY
2013ca987d46SWarner Losh **    Runtime: pop the loop control variables, then pop the
2014ca987d46SWarner Losh **    "leave" address and jump (absolute) there.
2015ca987d46SWarner Losh **************************************************************************/
2016ca987d46SWarner Losh 
doCoIm(FICL_VM * pVM)2017ca987d46SWarner Losh static void doCoIm(FICL_VM *pVM)
2018ca987d46SWarner Losh {
2019ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
2020ca987d46SWarner Losh 
2021ca987d46SWarner Losh     assert(pVM->pSys->pDoParen);
2022ca987d46SWarner Losh 
2023ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pDoParen));
2024ca987d46SWarner Losh     /*
2025ca987d46SWarner Losh     ** Allot space for a pointer to the end
2026ca987d46SWarner Losh     ** of the loop - "leave" uses this...
2027ca987d46SWarner Losh     */
2028ca987d46SWarner Losh     markBranch(dp, pVM, leaveTag);
2029ca987d46SWarner Losh     dictAppendUNS(dp, 0);
2030ca987d46SWarner Losh     /*
2031ca987d46SWarner Losh     ** Mark location of head of loop...
2032ca987d46SWarner Losh     */
2033ca987d46SWarner Losh     markBranch(dp, pVM, doTag);
2034ca987d46SWarner Losh 
2035ca987d46SWarner Losh     return;
2036ca987d46SWarner Losh }
2037ca987d46SWarner Losh 
2038ca987d46SWarner Losh 
doParen(FICL_VM * pVM)2039ca987d46SWarner Losh static void doParen(FICL_VM *pVM)
2040ca987d46SWarner Losh {
2041ca987d46SWarner Losh     CELL index, limit;
2042ca987d46SWarner Losh #if FICL_ROBUST > 1
2043ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
2044ca987d46SWarner Losh #endif
2045ca987d46SWarner Losh     index = stackPop(pVM->pStack);
2046ca987d46SWarner Losh     limit = stackPop(pVM->pStack);
2047ca987d46SWarner Losh 
2048ca987d46SWarner Losh     /* copy "leave" target addr to stack */
2049ca987d46SWarner Losh     stackPushPtr(pVM->rStack, *(pVM->ip++));
2050ca987d46SWarner Losh     stackPush(pVM->rStack, limit);
2051ca987d46SWarner Losh     stackPush(pVM->rStack, index);
2052ca987d46SWarner Losh 
2053ca987d46SWarner Losh     return;
2054ca987d46SWarner Losh }
2055ca987d46SWarner Losh 
2056ca987d46SWarner Losh 
qDoCoIm(FICL_VM * pVM)2057ca987d46SWarner Losh static void qDoCoIm(FICL_VM *pVM)
2058ca987d46SWarner Losh {
2059ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
2060ca987d46SWarner Losh 
2061ca987d46SWarner Losh     assert(pVM->pSys->pQDoParen);
2062ca987d46SWarner Losh 
2063ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pQDoParen));
2064ca987d46SWarner Losh     /*
2065ca987d46SWarner Losh     ** Allot space for a pointer to the end
2066ca987d46SWarner Losh     ** of the loop - "leave" uses this...
2067ca987d46SWarner Losh     */
2068ca987d46SWarner Losh     markBranch(dp, pVM, leaveTag);
2069ca987d46SWarner Losh     dictAppendUNS(dp, 0);
2070ca987d46SWarner Losh     /*
2071ca987d46SWarner Losh     ** Mark location of head of loop...
2072ca987d46SWarner Losh     */
2073ca987d46SWarner Losh     markBranch(dp, pVM, doTag);
2074ca987d46SWarner Losh 
2075ca987d46SWarner Losh     return;
2076ca987d46SWarner Losh }
2077ca987d46SWarner Losh 
2078ca987d46SWarner Losh 
qDoParen(FICL_VM * pVM)2079ca987d46SWarner Losh static void qDoParen(FICL_VM *pVM)
2080ca987d46SWarner Losh {
2081ca987d46SWarner Losh     CELL index, limit;
2082ca987d46SWarner Losh #if FICL_ROBUST > 1
2083ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
2084ca987d46SWarner Losh #endif
2085ca987d46SWarner Losh     index = stackPop(pVM->pStack);
2086ca987d46SWarner Losh     limit = stackPop(pVM->pStack);
2087ca987d46SWarner Losh 
2088ca987d46SWarner Losh     /* copy "leave" target addr to stack */
2089ca987d46SWarner Losh     stackPushPtr(pVM->rStack, *(pVM->ip++));
2090ca987d46SWarner Losh 
2091ca987d46SWarner Losh     if (limit.u == index.u)
2092ca987d46SWarner Losh     {
2093ca987d46SWarner Losh         vmPopIP(pVM);
2094ca987d46SWarner Losh     }
2095ca987d46SWarner Losh     else
2096ca987d46SWarner Losh     {
2097ca987d46SWarner Losh         stackPush(pVM->rStack, limit);
2098ca987d46SWarner Losh         stackPush(pVM->rStack, index);
2099ca987d46SWarner Losh     }
2100ca987d46SWarner Losh 
2101ca987d46SWarner Losh     return;
2102ca987d46SWarner Losh }
2103ca987d46SWarner Losh 
2104ca987d46SWarner Losh 
2105ca987d46SWarner Losh /*
2106ca987d46SWarner Losh ** Runtime code to break out of a do..loop construct
2107ca987d46SWarner Losh ** Drop the loop control variables; the branch address
2108ca987d46SWarner Losh ** past "loop" is next on the return stack.
2109ca987d46SWarner Losh */
leaveCo(FICL_VM * pVM)2110ca987d46SWarner Losh static void leaveCo(FICL_VM *pVM)
2111ca987d46SWarner Losh {
2112ca987d46SWarner Losh     /* almost unloop */
2113ca987d46SWarner Losh     stackDrop(pVM->rStack, 2);
2114ca987d46SWarner Losh     /* exit */
2115ca987d46SWarner Losh     vmPopIP(pVM);
2116ca987d46SWarner Losh     return;
2117ca987d46SWarner Losh }
2118ca987d46SWarner Losh 
2119ca987d46SWarner Losh 
unloopCo(FICL_VM * pVM)2120ca987d46SWarner Losh static void unloopCo(FICL_VM *pVM)
2121ca987d46SWarner Losh {
2122ca987d46SWarner Losh     stackDrop(pVM->rStack, 3);
2123ca987d46SWarner Losh     return;
2124ca987d46SWarner Losh }
2125ca987d46SWarner Losh 
2126ca987d46SWarner Losh 
loopCoIm(FICL_VM * pVM)2127ca987d46SWarner Losh static void loopCoIm(FICL_VM *pVM)
2128ca987d46SWarner Losh {
2129ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
2130ca987d46SWarner Losh 
2131ca987d46SWarner Losh     assert(pVM->pSys->pLoopParen);
2132ca987d46SWarner Losh 
2133ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pLoopParen));
2134ca987d46SWarner Losh     resolveBackBranch(dp, pVM, doTag);
2135ca987d46SWarner Losh     resolveAbsBranch(dp, pVM, leaveTag);
2136ca987d46SWarner Losh     return;
2137ca987d46SWarner Losh }
2138ca987d46SWarner Losh 
2139ca987d46SWarner Losh 
plusLoopCoIm(FICL_VM * pVM)2140ca987d46SWarner Losh static void plusLoopCoIm(FICL_VM *pVM)
2141ca987d46SWarner Losh {
2142ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
2143ca987d46SWarner Losh 
2144ca987d46SWarner Losh     assert(pVM->pSys->pPLoopParen);
2145ca987d46SWarner Losh 
2146ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pPLoopParen));
2147ca987d46SWarner Losh     resolveBackBranch(dp, pVM, doTag);
2148ca987d46SWarner Losh     resolveAbsBranch(dp, pVM, leaveTag);
2149ca987d46SWarner Losh     return;
2150ca987d46SWarner Losh }
2151ca987d46SWarner Losh 
2152ca987d46SWarner Losh 
loopParen(FICL_VM * pVM)2153ca987d46SWarner Losh static void loopParen(FICL_VM *pVM)
2154ca987d46SWarner Losh {
2155ca987d46SWarner Losh     FICL_INT index = stackGetTop(pVM->rStack).i;
2156ca987d46SWarner Losh     FICL_INT limit = stackFetch(pVM->rStack, 1).i;
2157ca987d46SWarner Losh 
2158ca987d46SWarner Losh     index++;
2159ca987d46SWarner Losh 
2160ca987d46SWarner Losh     if (index >= limit)
2161ca987d46SWarner Losh     {
2162ca987d46SWarner Losh         stackDrop(pVM->rStack, 3); /* nuke the loop indices & "leave" addr */
2163ca987d46SWarner Losh         vmBranchRelative(pVM, 1);  /* fall through the loop */
2164ca987d46SWarner Losh     }
2165ca987d46SWarner Losh     else
2166ca987d46SWarner Losh     {                       /* update index, branch to loop head */
2167ca987d46SWarner Losh         stackSetTop(pVM->rStack, LVALUEtoCELL(index));
2168ca987d46SWarner Losh         vmBranchRelative(pVM, (uintptr_t)*(pVM->ip));
2169ca987d46SWarner Losh     }
2170ca987d46SWarner Losh 
2171ca987d46SWarner Losh     return;
2172ca987d46SWarner Losh }
2173ca987d46SWarner Losh 
2174ca987d46SWarner Losh 
plusLoopParen(FICL_VM * pVM)2175ca987d46SWarner Losh static void plusLoopParen(FICL_VM *pVM)
2176ca987d46SWarner Losh {
2177ca987d46SWarner Losh     FICL_INT index,limit,increment;
2178ca987d46SWarner Losh     int flag;
2179ca987d46SWarner Losh 
2180ca987d46SWarner Losh #if FICL_ROBUST > 1
2181ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
2182ca987d46SWarner Losh #endif
2183ca987d46SWarner Losh 
2184ca987d46SWarner Losh     index = stackGetTop(pVM->rStack).i;
2185ca987d46SWarner Losh     limit = stackFetch(pVM->rStack, 1).i;
2186ca987d46SWarner Losh     increment = POP().i;
2187ca987d46SWarner Losh 
2188ca987d46SWarner Losh     index += increment;
2189ca987d46SWarner Losh 
2190ca987d46SWarner Losh     if (increment < 0)
2191ca987d46SWarner Losh         flag = (index < limit);
2192ca987d46SWarner Losh     else
2193ca987d46SWarner Losh         flag = (index >= limit);
2194ca987d46SWarner Losh 
2195ca987d46SWarner Losh     if (flag)
2196ca987d46SWarner Losh     {
2197ca987d46SWarner Losh         stackDrop(pVM->rStack, 3); /* nuke the loop indices & "leave" addr */
2198ca987d46SWarner Losh         vmBranchRelative(pVM, 1);  /* fall through the loop */
2199ca987d46SWarner Losh     }
2200ca987d46SWarner Losh     else
2201ca987d46SWarner Losh     {                       /* update index, branch to loop head */
2202ca987d46SWarner Losh         stackSetTop(pVM->rStack, LVALUEtoCELL(index));
2203ca987d46SWarner Losh         vmBranchRelative(pVM, (uintptr_t)*(pVM->ip));
2204ca987d46SWarner Losh     }
2205ca987d46SWarner Losh 
2206ca987d46SWarner Losh     return;
2207ca987d46SWarner Losh }
2208ca987d46SWarner Losh 
2209ca987d46SWarner Losh 
loopICo(FICL_VM * pVM)2210ca987d46SWarner Losh static void loopICo(FICL_VM *pVM)
2211ca987d46SWarner Losh {
2212ca987d46SWarner Losh     CELL index = stackGetTop(pVM->rStack);
2213ca987d46SWarner Losh     stackPush(pVM->pStack, index);
2214ca987d46SWarner Losh 
2215ca987d46SWarner Losh     return;
2216ca987d46SWarner Losh }
2217ca987d46SWarner Losh 
2218ca987d46SWarner Losh 
loopJCo(FICL_VM * pVM)2219ca987d46SWarner Losh static void loopJCo(FICL_VM *pVM)
2220ca987d46SWarner Losh {
2221ca987d46SWarner Losh     CELL index = stackFetch(pVM->rStack, 3);
2222ca987d46SWarner Losh     stackPush(pVM->pStack, index);
2223ca987d46SWarner Losh 
2224ca987d46SWarner Losh     return;
2225ca987d46SWarner Losh }
2226ca987d46SWarner Losh 
2227ca987d46SWarner Losh 
loopKCo(FICL_VM * pVM)2228ca987d46SWarner Losh static void loopKCo(FICL_VM *pVM)
2229ca987d46SWarner Losh {
2230ca987d46SWarner Losh     CELL index = stackFetch(pVM->rStack, 6);
2231ca987d46SWarner Losh     stackPush(pVM->pStack, index);
2232ca987d46SWarner Losh 
2233ca987d46SWarner Losh     return;
2234ca987d46SWarner Losh }
2235ca987d46SWarner Losh 
2236ca987d46SWarner Losh 
2237ca987d46SWarner Losh /**************************************************************************
2238ca987d46SWarner Losh                         r e t u r n   s t a c k
2239ca987d46SWarner Losh **
2240ca987d46SWarner Losh **************************************************************************/
toRStack(FICL_VM * pVM)2241ca987d46SWarner Losh static void toRStack(FICL_VM *pVM)
2242ca987d46SWarner Losh {
2243ca987d46SWarner Losh #if FICL_ROBUST > 1
2244ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
2245ca987d46SWarner Losh #endif
2246ca987d46SWarner Losh 
2247ca987d46SWarner Losh     stackPush(pVM->rStack, POP());
2248ca987d46SWarner Losh }
2249ca987d46SWarner Losh 
fromRStack(FICL_VM * pVM)2250ca987d46SWarner Losh static void fromRStack(FICL_VM *pVM)
2251ca987d46SWarner Losh {
2252ca987d46SWarner Losh #if FICL_ROBUST > 1
2253ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
2254ca987d46SWarner Losh #endif
2255ca987d46SWarner Losh 
2256ca987d46SWarner Losh     PUSH(stackPop(pVM->rStack));
2257ca987d46SWarner Losh }
2258ca987d46SWarner Losh 
fetchRStack(FICL_VM * pVM)2259ca987d46SWarner Losh static void fetchRStack(FICL_VM *pVM)
2260ca987d46SWarner Losh {
2261ca987d46SWarner Losh #if FICL_ROBUST > 1
2262ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
2263ca987d46SWarner Losh #endif
2264ca987d46SWarner Losh 
2265ca987d46SWarner Losh     PUSH(stackGetTop(pVM->rStack));
2266ca987d46SWarner Losh }
2267ca987d46SWarner Losh 
twoToR(FICL_VM * pVM)2268ca987d46SWarner Losh static void twoToR(FICL_VM *pVM)
2269ca987d46SWarner Losh {
2270ca987d46SWarner Losh #if FICL_ROBUST > 1
2271ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
2272ca987d46SWarner Losh #endif
2273ca987d46SWarner Losh     stackRoll(pVM->pStack, 1);
2274ca987d46SWarner Losh     stackPush(pVM->rStack, stackPop(pVM->pStack));
2275ca987d46SWarner Losh     stackPush(pVM->rStack, stackPop(pVM->pStack));
2276ca987d46SWarner Losh     return;
2277ca987d46SWarner Losh }
2278ca987d46SWarner Losh 
twoRFrom(FICL_VM * pVM)2279ca987d46SWarner Losh static void twoRFrom(FICL_VM *pVM)
2280ca987d46SWarner Losh {
2281ca987d46SWarner Losh #if FICL_ROBUST > 1
2282ca987d46SWarner Losh     vmCheckStack(pVM, 0, 2);
2283ca987d46SWarner Losh #endif
2284ca987d46SWarner Losh     stackPush(pVM->pStack, stackPop(pVM->rStack));
2285ca987d46SWarner Losh     stackPush(pVM->pStack, stackPop(pVM->rStack));
2286ca987d46SWarner Losh     stackRoll(pVM->pStack, 1);
2287ca987d46SWarner Losh     return;
2288ca987d46SWarner Losh }
2289ca987d46SWarner Losh 
twoRFetch(FICL_VM * pVM)2290ca987d46SWarner Losh static void twoRFetch(FICL_VM *pVM)
2291ca987d46SWarner Losh {
2292ca987d46SWarner Losh #if FICL_ROBUST > 1
2293ca987d46SWarner Losh     vmCheckStack(pVM, 0, 2);
2294ca987d46SWarner Losh #endif
2295ca987d46SWarner Losh     stackPush(pVM->pStack, stackFetch(pVM->rStack, 1));
2296ca987d46SWarner Losh     stackPush(pVM->pStack, stackFetch(pVM->rStack, 0));
2297ca987d46SWarner Losh     return;
2298ca987d46SWarner Losh }
2299ca987d46SWarner Losh 
2300ca987d46SWarner Losh 
2301ca987d46SWarner Losh /**************************************************************************
2302ca987d46SWarner Losh                         v a r i a b l e
2303ca987d46SWarner Losh **
2304ca987d46SWarner Losh **************************************************************************/
2305ca987d46SWarner Losh 
variableParen(FICL_VM * pVM)2306ca987d46SWarner Losh static void variableParen(FICL_VM *pVM)
2307ca987d46SWarner Losh {
2308ca987d46SWarner Losh     FICL_WORD *fw;
2309ca987d46SWarner Losh #if FICL_ROBUST > 1
2310ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
2311ca987d46SWarner Losh #endif
2312ca987d46SWarner Losh 
2313ca987d46SWarner Losh     fw = pVM->runningWord;
2314ca987d46SWarner Losh     PUSHPTR(fw->param);
2315ca987d46SWarner Losh }
2316ca987d46SWarner Losh 
2317ca987d46SWarner Losh 
variable(FICL_VM * pVM)2318ca987d46SWarner Losh static void variable(FICL_VM *pVM)
2319ca987d46SWarner Losh {
2320ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
2321ca987d46SWarner Losh     STRINGINFO si = vmGetWord(pVM);
2322ca987d46SWarner Losh 
2323ca987d46SWarner Losh     dictAppendWord2(dp, si, variableParen, FW_DEFAULT);
2324ca987d46SWarner Losh     dictAllotCells(dp, 1);
2325ca987d46SWarner Losh     return;
2326ca987d46SWarner Losh }
2327ca987d46SWarner Losh 
2328ca987d46SWarner Losh 
twoVariable(FICL_VM * pVM)2329ca987d46SWarner Losh static void twoVariable(FICL_VM *pVM)
2330ca987d46SWarner Losh {
2331ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
2332ca987d46SWarner Losh     STRINGINFO si = vmGetWord(pVM);
2333ca987d46SWarner Losh 
2334ca987d46SWarner Losh     dictAppendWord2(dp, si, variableParen, FW_DEFAULT);
2335ca987d46SWarner Losh     dictAllotCells(dp, 2);
2336ca987d46SWarner Losh     return;
2337ca987d46SWarner Losh }
2338ca987d46SWarner Losh 
2339ca987d46SWarner Losh 
2340ca987d46SWarner Losh /**************************************************************************
2341ca987d46SWarner Losh                         b a s e   &   f r i e n d s
2342ca987d46SWarner Losh **
2343ca987d46SWarner Losh **************************************************************************/
2344ca987d46SWarner Losh 
base(FICL_VM * pVM)2345ca987d46SWarner Losh static void base(FICL_VM *pVM)
2346ca987d46SWarner Losh {
2347ca987d46SWarner Losh     CELL *pBase;
2348ca987d46SWarner Losh #if FICL_ROBUST > 1
2349ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
2350ca987d46SWarner Losh #endif
2351ca987d46SWarner Losh 
2352ca987d46SWarner Losh     pBase = (CELL *)(&pVM->base);
2353ca987d46SWarner Losh     stackPush(pVM->pStack, LVALUEtoCELL(pBase));
2354ca987d46SWarner Losh     return;
2355ca987d46SWarner Losh }
2356ca987d46SWarner Losh 
2357ca987d46SWarner Losh 
decimal(FICL_VM * pVM)2358ca987d46SWarner Losh static void decimal(FICL_VM *pVM)
2359ca987d46SWarner Losh {
2360ca987d46SWarner Losh     pVM->base = 10;
2361ca987d46SWarner Losh     return;
2362ca987d46SWarner Losh }
2363ca987d46SWarner Losh 
2364ca987d46SWarner Losh 
hex(FICL_VM * pVM)2365ca987d46SWarner Losh static void hex(FICL_VM *pVM)
2366ca987d46SWarner Losh {
2367ca987d46SWarner Losh     pVM->base = 16;
2368ca987d46SWarner Losh     return;
2369ca987d46SWarner Losh }
2370ca987d46SWarner Losh 
2371ca987d46SWarner Losh 
2372ca987d46SWarner Losh /**************************************************************************
2373ca987d46SWarner Losh                         a l l o t   &   f r i e n d s
2374ca987d46SWarner Losh **
2375ca987d46SWarner Losh **************************************************************************/
2376ca987d46SWarner Losh 
allot(FICL_VM * pVM)2377ca987d46SWarner Losh static void allot(FICL_VM *pVM)
2378ca987d46SWarner Losh {
2379ca987d46SWarner Losh     FICL_DICT *dp;
2380ca987d46SWarner Losh     FICL_INT i;
2381ca987d46SWarner Losh #if FICL_ROBUST > 1
2382ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
2383ca987d46SWarner Losh #endif
2384ca987d46SWarner Losh 
2385ca987d46SWarner Losh     dp = vmGetDict(pVM);
2386ca987d46SWarner Losh     i = POPINT();
2387ca987d46SWarner Losh 
2388ca987d46SWarner Losh #if FICL_ROBUST
2389ca987d46SWarner Losh     dictCheck(dp, pVM, i);
2390ca987d46SWarner Losh #endif
2391ca987d46SWarner Losh 
2392ca987d46SWarner Losh     dictAllot(dp, i);
2393ca987d46SWarner Losh     return;
2394ca987d46SWarner Losh }
2395ca987d46SWarner Losh 
2396ca987d46SWarner Losh 
here(FICL_VM * pVM)2397ca987d46SWarner Losh static void here(FICL_VM *pVM)
2398ca987d46SWarner Losh {
2399ca987d46SWarner Losh     FICL_DICT *dp;
2400ca987d46SWarner Losh #if FICL_ROBUST > 1
2401ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
2402ca987d46SWarner Losh #endif
2403ca987d46SWarner Losh 
2404ca987d46SWarner Losh     dp = vmGetDict(pVM);
2405ca987d46SWarner Losh     PUSHPTR(dp->here);
2406ca987d46SWarner Losh     return;
2407ca987d46SWarner Losh }
2408ca987d46SWarner Losh 
comma(FICL_VM * pVM)2409ca987d46SWarner Losh static void comma(FICL_VM *pVM)
2410ca987d46SWarner Losh {
2411ca987d46SWarner Losh     FICL_DICT *dp;
2412ca987d46SWarner Losh     CELL c;
2413ca987d46SWarner Losh #if FICL_ROBUST > 1
2414ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
2415ca987d46SWarner Losh #endif
2416ca987d46SWarner Losh 
2417ca987d46SWarner Losh     dp = vmGetDict(pVM);
2418ca987d46SWarner Losh     c = POP();
2419ca987d46SWarner Losh     dictAppendCell(dp, c);
2420ca987d46SWarner Losh     return;
2421ca987d46SWarner Losh }
2422ca987d46SWarner Losh 
cComma(FICL_VM * pVM)2423ca987d46SWarner Losh static void cComma(FICL_VM *pVM)
2424ca987d46SWarner Losh {
2425ca987d46SWarner Losh     FICL_DICT *dp;
2426ca987d46SWarner Losh     char c;
2427ca987d46SWarner Losh #if FICL_ROBUST > 1
2428ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
2429ca987d46SWarner Losh #endif
2430ca987d46SWarner Losh 
2431ca987d46SWarner Losh     dp = vmGetDict(pVM);
2432ca987d46SWarner Losh     c = (char)POPINT();
2433ca987d46SWarner Losh     dictAppendChar(dp, c);
2434ca987d46SWarner Losh     return;
2435ca987d46SWarner Losh }
2436ca987d46SWarner Losh 
cells(FICL_VM * pVM)2437ca987d46SWarner Losh static void cells(FICL_VM *pVM)
2438ca987d46SWarner Losh {
2439ca987d46SWarner Losh     FICL_INT i;
2440ca987d46SWarner Losh #if FICL_ROBUST > 1
2441ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
2442ca987d46SWarner Losh #endif
2443ca987d46SWarner Losh 
2444ca987d46SWarner Losh     i = POPINT();
2445ca987d46SWarner Losh     PUSHINT(i * (FICL_INT)sizeof (CELL));
2446ca987d46SWarner Losh     return;
2447ca987d46SWarner Losh }
2448ca987d46SWarner Losh 
cellPlus(FICL_VM * pVM)2449ca987d46SWarner Losh static void cellPlus(FICL_VM *pVM)
2450ca987d46SWarner Losh {
2451ca987d46SWarner Losh     char *cp;
2452ca987d46SWarner Losh #if FICL_ROBUST > 1
2453ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
2454ca987d46SWarner Losh #endif
2455ca987d46SWarner Losh 
2456ca987d46SWarner Losh     cp = POPPTR();
2457ca987d46SWarner Losh     PUSHPTR(cp + sizeof (CELL));
2458ca987d46SWarner Losh     return;
2459ca987d46SWarner Losh }
2460ca987d46SWarner Losh 
2461ca987d46SWarner Losh 
2462ca987d46SWarner Losh 
2463ca987d46SWarner Losh /**************************************************************************
2464ca987d46SWarner Losh                         t i c k
2465ca987d46SWarner Losh ** tick         CORE ( "<spaces>name" -- xt )
2466ca987d46SWarner Losh ** Skip leading space delimiters. Parse name delimited by a space. Find
2467ca987d46SWarner Losh ** name and return xt, the execution token for name. An ambiguous condition
2468ca987d46SWarner Losh ** exists if name is not found.
2469ca987d46SWarner Losh **************************************************************************/
ficlTick(FICL_VM * pVM)2470ca987d46SWarner Losh void ficlTick(FICL_VM *pVM)
2471ca987d46SWarner Losh {
2472ca987d46SWarner Losh     FICL_WORD *pFW = NULL;
2473ca987d46SWarner Losh     STRINGINFO si = vmGetWord(pVM);
2474ca987d46SWarner Losh #if FICL_ROBUST > 1
2475ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
2476ca987d46SWarner Losh #endif
2477ca987d46SWarner Losh 
2478ca987d46SWarner Losh     pFW = dictLookup(vmGetDict(pVM), si);
2479ca987d46SWarner Losh     if (!pFW)
2480ca987d46SWarner Losh     {
2481ca987d46SWarner Losh         int i = SI_COUNT(si);
2482ca987d46SWarner Losh         vmThrowErr(pVM, "%.*s not found", i, SI_PTR(si));
2483ca987d46SWarner Losh     }
2484ca987d46SWarner Losh     PUSHPTR(pFW);
2485ca987d46SWarner Losh     return;
2486ca987d46SWarner Losh }
2487ca987d46SWarner Losh 
2488ca987d46SWarner Losh 
bracketTickCoIm(FICL_VM * pVM)2489ca987d46SWarner Losh static void bracketTickCoIm(FICL_VM *pVM)
2490ca987d46SWarner Losh {
2491ca987d46SWarner Losh     ficlTick(pVM);
2492ca987d46SWarner Losh     literalIm(pVM);
2493ca987d46SWarner Losh 
2494ca987d46SWarner Losh     return;
2495ca987d46SWarner Losh }
2496ca987d46SWarner Losh 
2497ca987d46SWarner Losh 
2498ca987d46SWarner Losh /**************************************************************************
2499ca987d46SWarner Losh                         p o s t p o n e
2500ca987d46SWarner Losh ** Lookup the next word in the input stream and compile code to
2501ca987d46SWarner Losh ** insert it into definitions created by the resulting word
2502ca987d46SWarner Losh ** (defers compilation, even of immediate words)
2503ca987d46SWarner Losh **************************************************************************/
2504ca987d46SWarner Losh 
postponeCoIm(FICL_VM * pVM)2505ca987d46SWarner Losh static void postponeCoIm(FICL_VM *pVM)
2506ca987d46SWarner Losh {
2507ca987d46SWarner Losh     FICL_DICT *dp  = vmGetDict(pVM);
2508ca987d46SWarner Losh     FICL_WORD *pFW;
2509ca987d46SWarner Losh     FICL_WORD *pComma = ficlLookup(pVM->pSys, ",");
2510ca987d46SWarner Losh     assert(pComma);
2511ca987d46SWarner Losh 
2512ca987d46SWarner Losh     ficlTick(pVM);
2513ca987d46SWarner Losh     pFW = stackGetTop(pVM->pStack).p;
2514ca987d46SWarner Losh     if (wordIsImmediate(pFW))
2515ca987d46SWarner Losh     {
2516ca987d46SWarner Losh         dictAppendCell(dp, stackPop(pVM->pStack));
2517ca987d46SWarner Losh     }
2518ca987d46SWarner Losh     else
2519ca987d46SWarner Losh     {
2520ca987d46SWarner Losh         literalIm(pVM);
2521ca987d46SWarner Losh         dictAppendCell(dp, LVALUEtoCELL(pComma));
2522ca987d46SWarner Losh     }
2523ca987d46SWarner Losh 
2524ca987d46SWarner Losh     return;
2525ca987d46SWarner Losh }
2526ca987d46SWarner Losh 
2527ca987d46SWarner Losh 
2528ca987d46SWarner Losh 
2529ca987d46SWarner Losh /**************************************************************************
2530ca987d46SWarner Losh                         e x e c u t e
2531ca987d46SWarner Losh ** Pop an execution token (pointer to a word) off the stack and
2532ca987d46SWarner Losh ** run it
2533ca987d46SWarner Losh **************************************************************************/
2534ca987d46SWarner Losh 
execute(FICL_VM * pVM)2535ca987d46SWarner Losh static void execute(FICL_VM *pVM)
2536ca987d46SWarner Losh {
2537ca987d46SWarner Losh     FICL_WORD *pFW;
2538ca987d46SWarner Losh #if FICL_ROBUST > 1
2539ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
2540ca987d46SWarner Losh #endif
2541ca987d46SWarner Losh 
2542ca987d46SWarner Losh     pFW = stackPopPtr(pVM->pStack);
2543ca987d46SWarner Losh     vmExecute(pVM, pFW);
2544ca987d46SWarner Losh 
2545ca987d46SWarner Losh     return;
2546ca987d46SWarner Losh }
2547ca987d46SWarner Losh 
2548ca987d46SWarner Losh 
2549ca987d46SWarner Losh /**************************************************************************
2550ca987d46SWarner Losh                         i m m e d i a t e
2551ca987d46SWarner Losh ** Make the most recently compiled word IMMEDIATE -- it executes even
2552ca987d46SWarner Losh ** in compile state (most often used for control compiling words
2553ca987d46SWarner Losh ** such as IF, THEN, etc)
2554ca987d46SWarner Losh **************************************************************************/
2555ca987d46SWarner Losh 
immediate(FICL_VM * pVM)2556ca987d46SWarner Losh static void immediate(FICL_VM *pVM)
2557ca987d46SWarner Losh {
2558ca987d46SWarner Losh     IGNORE(pVM);
2559ca987d46SWarner Losh     dictSetImmediate(vmGetDict(pVM));
2560ca987d46SWarner Losh     return;
2561ca987d46SWarner Losh }
2562ca987d46SWarner Losh 
2563ca987d46SWarner Losh 
compileOnly(FICL_VM * pVM)2564ca987d46SWarner Losh static void compileOnly(FICL_VM *pVM)
2565ca987d46SWarner Losh {
2566ca987d46SWarner Losh     IGNORE(pVM);
2567ca987d46SWarner Losh     dictSetFlags(vmGetDict(pVM), FW_COMPILE, 0);
2568ca987d46SWarner Losh     return;
2569ca987d46SWarner Losh }
2570ca987d46SWarner Losh 
2571ca987d46SWarner Losh 
setObjectFlag(FICL_VM * pVM)2572ca987d46SWarner Losh static void setObjectFlag(FICL_VM *pVM)
2573ca987d46SWarner Losh {
2574ca987d46SWarner Losh     IGNORE(pVM);
2575ca987d46SWarner Losh     dictSetFlags(vmGetDict(pVM), FW_ISOBJECT, 0);
2576ca987d46SWarner Losh     return;
2577ca987d46SWarner Losh }
2578ca987d46SWarner Losh 
isObject(FICL_VM * pVM)2579ca987d46SWarner Losh static void isObject(FICL_VM *pVM)
2580ca987d46SWarner Losh {
2581ca987d46SWarner Losh     FICL_INT flag;
2582ca987d46SWarner Losh     FICL_WORD *pFW = (FICL_WORD *)stackPopPtr(pVM->pStack);
2583ca987d46SWarner Losh 
2584ca987d46SWarner Losh     flag = ((pFW != NULL) && (pFW->flags & FW_ISOBJECT)) ? FICL_TRUE : FICL_FALSE;
2585ca987d46SWarner Losh     stackPushINT(pVM->pStack, flag);
2586ca987d46SWarner Losh     return;
2587ca987d46SWarner Losh }
2588ca987d46SWarner Losh 
cstringLit(FICL_VM * pVM)2589ca987d46SWarner Losh static void cstringLit(FICL_VM *pVM)
2590ca987d46SWarner Losh {
2591ca987d46SWarner Losh     FICL_STRING *sp = (FICL_STRING *)(pVM->ip);
2592ca987d46SWarner Losh 
2593ca987d46SWarner Losh     char *cp = sp->text;
2594ca987d46SWarner Losh     cp += sp->count + 1;
2595ca987d46SWarner Losh     cp = alignPtr(cp);
2596ca987d46SWarner Losh     pVM->ip = (IPTYPE)(void *)cp;
2597ca987d46SWarner Losh 
2598ca987d46SWarner Losh     stackPushPtr(pVM->pStack, sp);
2599ca987d46SWarner Losh     return;
2600ca987d46SWarner Losh }
2601ca987d46SWarner Losh 
2602ca987d46SWarner Losh 
cstringQuoteIm(FICL_VM * pVM)2603ca987d46SWarner Losh static void cstringQuoteIm(FICL_VM *pVM)
2604ca987d46SWarner Losh {
2605ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
2606ca987d46SWarner Losh 
2607ca987d46SWarner Losh     if (pVM->state == INTERPRET)
2608ca987d46SWarner Losh     {
2609ca987d46SWarner Losh         FICL_STRING *sp = (FICL_STRING *) dp->here;
2610ca987d46SWarner Losh         vmGetString(pVM, sp, '\"');
2611ca987d46SWarner Losh         stackPushPtr(pVM->pStack, sp);
2612ca987d46SWarner Losh 		/* move HERE past string so it doesn't get overwritten.  --lch */
2613ca987d46SWarner Losh 		dictAllot(dp, sp->count + sizeof(FICL_COUNT));
2614ca987d46SWarner Losh     }
2615ca987d46SWarner Losh     else    /* COMPILE state */
2616ca987d46SWarner Losh     {
2617ca987d46SWarner Losh         dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pCStringLit));
2618ca987d46SWarner Losh         dp->here = PTRtoCELL vmGetString(pVM, (FICL_STRING *)dp->here, '\"');
2619ca987d46SWarner Losh         dictAlign(dp);
2620ca987d46SWarner Losh     }
2621ca987d46SWarner Losh 
2622ca987d46SWarner Losh     return;
2623ca987d46SWarner Losh }
2624ca987d46SWarner Losh 
2625ca987d46SWarner Losh /**************************************************************************
2626ca987d46SWarner Losh                         d o t Q u o t e
2627ca987d46SWarner Losh ** IMMEDIATE word that compiles a string literal for later display
2628ca987d46SWarner Losh ** Compile stringLit, then copy the bytes of the string from the TIB
2629ca987d46SWarner Losh ** to the dictionary. Backpatch the count byte and align the dictionary.
2630ca987d46SWarner Losh **
2631ca987d46SWarner Losh ** stringlit: Fetch the count from the dictionary, then push the address
2632ca987d46SWarner Losh ** and count on the stack. Finally, update ip to point to the first
2633ca987d46SWarner Losh ** aligned address after the string text.
2634ca987d46SWarner Losh **************************************************************************/
2635ca987d46SWarner Losh 
stringLit(FICL_VM * pVM)2636ca987d46SWarner Losh static void stringLit(FICL_VM *pVM)
2637ca987d46SWarner Losh {
2638ca987d46SWarner Losh     FICL_STRING *sp;
2639ca987d46SWarner Losh     FICL_COUNT count;
2640ca987d46SWarner Losh     char *cp;
2641ca987d46SWarner Losh #if FICL_ROBUST > 1
2642ca987d46SWarner Losh     vmCheckStack(pVM, 0, 2);
2643ca987d46SWarner Losh #endif
2644ca987d46SWarner Losh 
2645ca987d46SWarner Losh     sp = (FICL_STRING *)(pVM->ip);
2646ca987d46SWarner Losh     count = sp->count;
2647ca987d46SWarner Losh     cp = sp->text;
2648ca987d46SWarner Losh     PUSHPTR(cp);
2649ca987d46SWarner Losh     PUSHUNS(count);
2650ca987d46SWarner Losh     cp += count + 1;
2651ca987d46SWarner Losh     cp = alignPtr(cp);
2652ca987d46SWarner Losh     pVM->ip = (IPTYPE)(void *)cp;
2653ca987d46SWarner Losh }
2654ca987d46SWarner Losh 
dotQuoteCoIm(FICL_VM * pVM)2655ca987d46SWarner Losh static void dotQuoteCoIm(FICL_VM *pVM)
2656ca987d46SWarner Losh {
2657ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
2658ca987d46SWarner Losh     FICL_WORD *pType = ficlLookup(pVM->pSys, "type");
2659ca987d46SWarner Losh     assert(pType);
2660ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStringLit));
2661ca987d46SWarner Losh     dp->here = PTRtoCELL vmGetString(pVM, (FICL_STRING *)dp->here, '\"');
2662ca987d46SWarner Losh     dictAlign(dp);
2663ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pType));
2664ca987d46SWarner Losh     return;
2665ca987d46SWarner Losh }
2666ca987d46SWarner Losh 
2667ca987d46SWarner Losh 
dotParen(FICL_VM * pVM)2668ca987d46SWarner Losh static void dotParen(FICL_VM *pVM)
2669ca987d46SWarner Losh {
2670ca987d46SWarner Losh     char *pSrc      = vmGetInBuf(pVM);
2671ca987d46SWarner Losh     char *pEnd      = vmGetInBufEnd(pVM);
2672ca987d46SWarner Losh     char *pDest     = pVM->pad;
2673ca987d46SWarner Losh     char ch;
2674ca987d46SWarner Losh 
2675ca987d46SWarner Losh     /*
2676ca987d46SWarner Losh     ** Note: the standard does not want leading spaces skipped (apparently)
2677ca987d46SWarner Losh     */
2678ca987d46SWarner Losh     for (ch = *pSrc; (pEnd != pSrc) && (ch != ')'); ch = *++pSrc)
2679ca987d46SWarner Losh         *pDest++ = ch;
2680ca987d46SWarner Losh 
2681ca987d46SWarner Losh     *pDest = '\0';
2682ca987d46SWarner Losh     if ((pEnd != pSrc) && (ch == ')'))
2683ca987d46SWarner Losh         pSrc++;
2684ca987d46SWarner Losh 
2685ca987d46SWarner Losh     vmTextOut(pVM, pVM->pad, 0);
2686ca987d46SWarner Losh     vmUpdateTib(pVM, pSrc);
2687ca987d46SWarner Losh 
2688ca987d46SWarner Losh     return;
2689ca987d46SWarner Losh }
2690ca987d46SWarner Losh 
2691ca987d46SWarner Losh 
2692ca987d46SWarner Losh /**************************************************************************
2693ca987d46SWarner Losh                         s l i t e r a l
2694ca987d46SWarner Losh ** STRING
2695ca987d46SWarner Losh ** Interpretation: Interpretation semantics for this word are undefined.
2696ca987d46SWarner Losh ** Compilation: ( c-addr1 u -- )
2697ca987d46SWarner Losh ** Append the run-time semantics given below to the current definition.
2698ca987d46SWarner Losh ** Run-time:       ( -- c-addr2 u )
2699ca987d46SWarner Losh ** Return c-addr2 u describing a string consisting of the characters
2700ca987d46SWarner Losh ** specified by c-addr1 u during compilation. A program shall not alter
2701ca987d46SWarner Losh ** the returned string.
2702ca987d46SWarner Losh **************************************************************************/
sLiteralCoIm(FICL_VM * pVM)2703ca987d46SWarner Losh static void sLiteralCoIm(FICL_VM *pVM)
2704ca987d46SWarner Losh {
2705ca987d46SWarner Losh     FICL_DICT *dp;
2706ca987d46SWarner Losh     char *cp, *cpDest;
2707ca987d46SWarner Losh     FICL_UNS u;
2708ca987d46SWarner Losh 
2709ca987d46SWarner Losh #if FICL_ROBUST > 1
2710ca987d46SWarner Losh     vmCheckStack(pVM, 2, 0);
2711ca987d46SWarner Losh #endif
2712ca987d46SWarner Losh 
2713ca987d46SWarner Losh     dp = vmGetDict(pVM);
2714ca987d46SWarner Losh     u  = POPUNS();
2715ca987d46SWarner Losh     cp = POPPTR();
2716ca987d46SWarner Losh 
2717ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStringLit));
2718ca987d46SWarner Losh     cpDest    = (char *) dp->here;
2719ca987d46SWarner Losh     *cpDest++ = (char)   u;
2720ca987d46SWarner Losh 
2721ca987d46SWarner Losh     for (; u > 0; --u)
2722ca987d46SWarner Losh     {
2723ca987d46SWarner Losh         *cpDest++ = *cp++;
2724ca987d46SWarner Losh     }
2725ca987d46SWarner Losh 
2726ca987d46SWarner Losh     *cpDest++ = 0;
2727ca987d46SWarner Losh     dp->here = PTRtoCELL alignPtr(cpDest);
2728ca987d46SWarner Losh     return;
2729ca987d46SWarner Losh }
2730ca987d46SWarner Losh 
2731ca987d46SWarner Losh 
2732ca987d46SWarner Losh /**************************************************************************
2733ca987d46SWarner Losh                         s t a t e
2734ca987d46SWarner Losh ** Return the address of the VM's state member (must be sized the
2735ca987d46SWarner Losh ** same as a CELL for this reason)
2736ca987d46SWarner Losh **************************************************************************/
state(FICL_VM * pVM)2737ca987d46SWarner Losh static void state(FICL_VM *pVM)
2738ca987d46SWarner Losh {
2739ca987d46SWarner Losh #if FICL_ROBUST > 1
2740ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
2741ca987d46SWarner Losh #endif
2742ca987d46SWarner Losh     PUSHPTR(&pVM->state);
2743ca987d46SWarner Losh     return;
2744ca987d46SWarner Losh }
2745ca987d46SWarner Losh 
2746ca987d46SWarner Losh 
2747ca987d46SWarner Losh /**************************************************************************
2748ca987d46SWarner Losh                         c r e a t e . . . d o e s >
2749ca987d46SWarner Losh ** Make a new word in the dictionary with the run-time effect of
2750ca987d46SWarner Losh ** a variable (push my address), but with extra space allotted
2751ca987d46SWarner Losh ** for use by does> .
2752ca987d46SWarner Losh **************************************************************************/
2753ca987d46SWarner Losh 
createParen(FICL_VM * pVM)2754ca987d46SWarner Losh static void createParen(FICL_VM *pVM)
2755ca987d46SWarner Losh {
2756ca987d46SWarner Losh     CELL *pCell;
2757ca987d46SWarner Losh 
2758ca987d46SWarner Losh #if FICL_ROBUST > 1
2759ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
2760ca987d46SWarner Losh #endif
2761ca987d46SWarner Losh 
2762ca987d46SWarner Losh     pCell = pVM->runningWord->param;
2763ca987d46SWarner Losh     PUSHPTR(pCell+1);
2764ca987d46SWarner Losh     return;
2765ca987d46SWarner Losh }
2766ca987d46SWarner Losh 
2767ca987d46SWarner Losh 
create(FICL_VM * pVM)2768ca987d46SWarner Losh static void create(FICL_VM *pVM)
2769ca987d46SWarner Losh {
2770ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
2771ca987d46SWarner Losh     STRINGINFO si = vmGetWord(pVM);
2772ca987d46SWarner Losh 
2773ca987d46SWarner Losh     dictCheckThreshold(dp);
2774ca987d46SWarner Losh 
2775ca987d46SWarner Losh     dictAppendWord2(dp, si, createParen, FW_DEFAULT);
2776ca987d46SWarner Losh     dictAllotCells(dp, 1);
2777ca987d46SWarner Losh     return;
2778ca987d46SWarner Losh }
2779ca987d46SWarner Losh 
2780ca987d46SWarner Losh 
doDoes(FICL_VM * pVM)2781ca987d46SWarner Losh static void doDoes(FICL_VM *pVM)
2782ca987d46SWarner Losh {
2783ca987d46SWarner Losh     CELL *pCell;
2784ca987d46SWarner Losh     IPTYPE tempIP;
2785ca987d46SWarner Losh #if FICL_ROBUST > 1
2786ca987d46SWarner Losh     vmCheckStack(pVM, 0, 1);
2787ca987d46SWarner Losh #endif
2788ca987d46SWarner Losh 
2789ca987d46SWarner Losh     pCell = pVM->runningWord->param;
2790ca987d46SWarner Losh     tempIP = (IPTYPE)((*pCell).p);
2791ca987d46SWarner Losh     PUSHPTR(pCell+1);
2792ca987d46SWarner Losh     vmPushIP(pVM, tempIP);
2793ca987d46SWarner Losh     return;
2794ca987d46SWarner Losh }
2795ca987d46SWarner Losh 
2796ca987d46SWarner Losh 
doesParen(FICL_VM * pVM)2797ca987d46SWarner Losh static void doesParen(FICL_VM *pVM)
2798ca987d46SWarner Losh {
2799ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
2800ca987d46SWarner Losh     dp->smudge->code = doDoes;
2801ca987d46SWarner Losh     dp->smudge->param[0] = LVALUEtoCELL(pVM->ip);
2802ca987d46SWarner Losh     vmPopIP(pVM);
2803ca987d46SWarner Losh     return;
2804ca987d46SWarner Losh }
2805ca987d46SWarner Losh 
2806ca987d46SWarner Losh 
doesCoIm(FICL_VM * pVM)2807ca987d46SWarner Losh static void doesCoIm(FICL_VM *pVM)
2808ca987d46SWarner Losh {
2809ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
2810ca987d46SWarner Losh #if FICL_WANT_LOCALS
2811ca987d46SWarner Losh     assert(pVM->pSys->pUnLinkParen);
2812ca987d46SWarner Losh     if (pVM->pSys->nLocals > 0)
2813ca987d46SWarner Losh     {
2814ca987d46SWarner Losh         FICL_DICT *pLoc = ficlGetLoc(pVM->pSys);
2815ca987d46SWarner Losh         dictEmpty(pLoc, pLoc->pForthWords->size);
2816ca987d46SWarner Losh         dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pUnLinkParen));
2817ca987d46SWarner Losh     }
2818ca987d46SWarner Losh 
2819ca987d46SWarner Losh     pVM->pSys->nLocals = 0;
2820ca987d46SWarner Losh #endif
2821ca987d46SWarner Losh     IGNORE(pVM);
2822ca987d46SWarner Losh 
2823ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pDoesParen));
2824ca987d46SWarner Losh     return;
2825ca987d46SWarner Losh }
2826ca987d46SWarner Losh 
2827ca987d46SWarner Losh 
2828ca987d46SWarner Losh /**************************************************************************
2829ca987d46SWarner Losh                         t o   b o d y
2830ca987d46SWarner Losh ** to-body      CORE ( xt -- a-addr )
2831ca987d46SWarner Losh ** a-addr is the data-field address corresponding to xt. An ambiguous
2832ca987d46SWarner Losh ** condition exists if xt is not for a word defined via CREATE.
2833ca987d46SWarner Losh **************************************************************************/
toBody(FICL_VM * pVM)2834ca987d46SWarner Losh static void toBody(FICL_VM *pVM)
2835ca987d46SWarner Losh {
2836ca987d46SWarner Losh     FICL_WORD *pFW;
2837ca987d46SWarner Losh /*#$-GUY CHANGE: Added robustness.-$#*/
2838ca987d46SWarner Losh #if FICL_ROBUST > 1
2839ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
2840ca987d46SWarner Losh #endif
2841ca987d46SWarner Losh 
2842ca987d46SWarner Losh     pFW = POPPTR();
2843ca987d46SWarner Losh     PUSHPTR(pFW->param + 1);
2844ca987d46SWarner Losh     return;
2845ca987d46SWarner Losh }
2846ca987d46SWarner Losh 
2847ca987d46SWarner Losh 
2848ca987d46SWarner Losh /*
2849ca987d46SWarner Losh ** from-body       ficl ( a-addr -- xt )
2850ca987d46SWarner Losh ** Reverse effect of >body
2851ca987d46SWarner Losh */
fromBody(FICL_VM * pVM)2852ca987d46SWarner Losh static void fromBody(FICL_VM *pVM)
2853ca987d46SWarner Losh {
2854ca987d46SWarner Losh     char *ptr;
2855ca987d46SWarner Losh #if FICL_ROBUST > 1
2856ca987d46SWarner Losh     vmCheckStack(pVM, 1, 1);
2857ca987d46SWarner Losh #endif
2858ca987d46SWarner Losh 
2859ca987d46SWarner Losh     ptr = (char *)POPPTR() - sizeof (FICL_WORD);
2860ca987d46SWarner Losh     PUSHPTR(ptr);
2861ca987d46SWarner Losh     return;
2862ca987d46SWarner Losh }
2863ca987d46SWarner Losh 
2864ca987d46SWarner Losh 
2865ca987d46SWarner Losh /*
2866ca987d46SWarner Losh ** >name        ficl ( xt -- c-addr u )
2867ca987d46SWarner Losh ** Push the address and length of a word's name given its address
2868ca987d46SWarner Losh ** xt.
2869ca987d46SWarner Losh */
toName(FICL_VM * pVM)2870ca987d46SWarner Losh static void toName(FICL_VM *pVM)
2871ca987d46SWarner Losh {
2872ca987d46SWarner Losh     FICL_WORD *pFW;
2873ca987d46SWarner Losh #if FICL_ROBUST > 1
2874ca987d46SWarner Losh     vmCheckStack(pVM, 1, 2);
2875ca987d46SWarner Losh #endif
2876ca987d46SWarner Losh 
2877ca987d46SWarner Losh     pFW = POPPTR();
2878ca987d46SWarner Losh     PUSHPTR(pFW->name);
2879ca987d46SWarner Losh     PUSHUNS(pFW->nName);
2880ca987d46SWarner Losh     return;
2881ca987d46SWarner Losh }
2882ca987d46SWarner Losh 
2883ca987d46SWarner Losh 
getLastWord(FICL_VM * pVM)2884ca987d46SWarner Losh static void getLastWord(FICL_VM *pVM)
2885ca987d46SWarner Losh {
2886ca987d46SWarner Losh     FICL_DICT *pDict = vmGetDict(pVM);
2887ca987d46SWarner Losh     FICL_WORD *wp = pDict->smudge;
2888ca987d46SWarner Losh     assert(wp);
2889ca987d46SWarner Losh     vmPush(pVM, LVALUEtoCELL(wp));
2890ca987d46SWarner Losh     return;
2891ca987d46SWarner Losh }
2892ca987d46SWarner Losh 
2893ca987d46SWarner Losh 
2894ca987d46SWarner Losh /**************************************************************************
2895ca987d46SWarner Losh                         l b r a c k e t   e t c
2896ca987d46SWarner Losh **
2897ca987d46SWarner Losh **************************************************************************/
2898ca987d46SWarner Losh 
lbracketCoIm(FICL_VM * pVM)2899ca987d46SWarner Losh static void lbracketCoIm(FICL_VM *pVM)
2900ca987d46SWarner Losh {
2901ca987d46SWarner Losh     pVM->state = INTERPRET;
2902ca987d46SWarner Losh     return;
2903ca987d46SWarner Losh }
2904ca987d46SWarner Losh 
2905ca987d46SWarner Losh 
rbracket(FICL_VM * pVM)2906ca987d46SWarner Losh static void rbracket(FICL_VM *pVM)
2907ca987d46SWarner Losh {
2908ca987d46SWarner Losh     pVM->state = COMPILE;
2909ca987d46SWarner Losh     return;
2910ca987d46SWarner Losh }
2911ca987d46SWarner Losh 
2912ca987d46SWarner Losh 
2913ca987d46SWarner Losh /**************************************************************************
2914ca987d46SWarner Losh                         p i c t u r e d   n u m e r i c   w o r d s
2915ca987d46SWarner Losh **
2916ca987d46SWarner Losh ** less-number-sign CORE ( -- )
2917ca987d46SWarner Losh ** Initialize the pictured numeric output conversion process.
2918ca987d46SWarner Losh ** (clear the pad)
2919ca987d46SWarner Losh **************************************************************************/
lessNumberSign(FICL_VM * pVM)2920ca987d46SWarner Losh static void lessNumberSign(FICL_VM *pVM)
2921ca987d46SWarner Losh {
2922ca987d46SWarner Losh     FICL_STRING *sp = PTRtoSTRING pVM->pad;
2923ca987d46SWarner Losh     sp->count = 0;
2924ca987d46SWarner Losh     return;
2925ca987d46SWarner Losh }
2926ca987d46SWarner Losh 
2927ca987d46SWarner Losh /*
2928ca987d46SWarner Losh ** number-sign      CORE ( ud1 -- ud2 )
2929ca987d46SWarner Losh ** Divide ud1 by the number in BASE giving the quotient ud2 and the remainder
2930ca987d46SWarner Losh ** n. (n is the least-significant digit of ud1.) Convert n to external form
2931ca987d46SWarner Losh ** and add the resulting character to the beginning of the pictured numeric
2932ca987d46SWarner Losh ** output  string. An ambiguous condition exists if # executes outside of a
2933ca987d46SWarner Losh ** <# #> delimited number conversion.
2934ca987d46SWarner Losh */
numberSign(FICL_VM * pVM)2935ca987d46SWarner Losh static void numberSign(FICL_VM *pVM)
2936ca987d46SWarner Losh {
2937ca987d46SWarner Losh     FICL_STRING *sp;
2938ca987d46SWarner Losh     DPUNS u;
2939ca987d46SWarner Losh     UNS16 rem;
2940ca987d46SWarner Losh #if FICL_ROBUST > 1
2941ca987d46SWarner Losh     vmCheckStack(pVM, 2, 2);
2942ca987d46SWarner Losh #endif
2943ca987d46SWarner Losh 
2944ca987d46SWarner Losh     sp = PTRtoSTRING pVM->pad;
2945ca987d46SWarner Losh     u = u64Pop(pVM->pStack);
2946ca987d46SWarner Losh     rem = m64UMod(&u, (UNS16)(pVM->base));
2947ca987d46SWarner Losh     sp->text[sp->count++] = digit_to_char(rem);
2948ca987d46SWarner Losh     u64Push(pVM->pStack, u);
2949ca987d46SWarner Losh     return;
2950ca987d46SWarner Losh }
2951ca987d46SWarner Losh 
2952ca987d46SWarner Losh /*
2953ca987d46SWarner Losh ** number-sign-greater CORE ( xd -- c-addr u )
2954ca987d46SWarner Losh ** Drop xd. Make the pictured numeric output string available as a character
2955ca987d46SWarner Losh ** string. c-addr and u specify the resulting character string. A program
2956ca987d46SWarner Losh ** may replace characters within the string.
2957ca987d46SWarner Losh */
numberSignGreater(FICL_VM * pVM)2958ca987d46SWarner Losh static void numberSignGreater(FICL_VM *pVM)
2959ca987d46SWarner Losh {
2960ca987d46SWarner Losh     FICL_STRING *sp;
2961ca987d46SWarner Losh #if FICL_ROBUST > 1
2962ca987d46SWarner Losh     vmCheckStack(pVM, 2, 2);
2963ca987d46SWarner Losh #endif
2964ca987d46SWarner Losh 
2965ca987d46SWarner Losh     sp = PTRtoSTRING pVM->pad;
2966ca987d46SWarner Losh     sp->text[sp->count] = 0;
2967ca987d46SWarner Losh     strrev(sp->text);
2968ca987d46SWarner Losh     DROP(2);
2969ca987d46SWarner Losh     PUSHPTR(sp->text);
2970ca987d46SWarner Losh     PUSHUNS(sp->count);
2971ca987d46SWarner Losh     return;
2972ca987d46SWarner Losh }
2973ca987d46SWarner Losh 
2974ca987d46SWarner Losh /*
2975ca987d46SWarner Losh ** number-sign-s    CORE ( ud1 -- ud2 )
2976ca987d46SWarner Losh ** Convert one digit of ud1 according to the rule for #. Continue conversion
2977ca987d46SWarner Losh ** until the quotient is zero. ud2 is zero. An ambiguous condition exists if
2978ca987d46SWarner Losh ** #S executes outside of a <# #> delimited number conversion.
2979ca987d46SWarner Losh ** TO DO: presently does not use ud1 hi cell - use it!
2980ca987d46SWarner Losh */
numberSignS(FICL_VM * pVM)2981ca987d46SWarner Losh static void numberSignS(FICL_VM *pVM)
2982ca987d46SWarner Losh {
2983ca987d46SWarner Losh     FICL_STRING *sp;
2984ca987d46SWarner Losh     DPUNS u;
2985ca987d46SWarner Losh     UNS16 rem;
2986ca987d46SWarner Losh #if FICL_ROBUST > 1
2987ca987d46SWarner Losh     vmCheckStack(pVM, 2, 2);
2988ca987d46SWarner Losh #endif
2989ca987d46SWarner Losh 
2990ca987d46SWarner Losh     sp = PTRtoSTRING pVM->pad;
2991ca987d46SWarner Losh     u = u64Pop(pVM->pStack);
2992ca987d46SWarner Losh 
2993ca987d46SWarner Losh     do
2994ca987d46SWarner Losh     {
2995ca987d46SWarner Losh         rem = m64UMod(&u, (UNS16)(pVM->base));
2996ca987d46SWarner Losh         sp->text[sp->count++] = digit_to_char(rem);
2997ca987d46SWarner Losh     }
2998ca987d46SWarner Losh     while (u.hi || u.lo);
2999ca987d46SWarner Losh 
3000ca987d46SWarner Losh     u64Push(pVM->pStack, u);
3001ca987d46SWarner Losh     return;
3002ca987d46SWarner Losh }
3003ca987d46SWarner Losh 
3004ca987d46SWarner Losh /*
3005ca987d46SWarner Losh ** HOLD             CORE ( char -- )
3006ca987d46SWarner Losh ** Add char to the beginning of the pictured numeric output string. An ambiguous
3007ca987d46SWarner Losh ** condition exists if HOLD executes outside of a <# #> delimited number conversion.
3008ca987d46SWarner Losh */
hold(FICL_VM * pVM)3009ca987d46SWarner Losh static void hold(FICL_VM *pVM)
3010ca987d46SWarner Losh {
3011ca987d46SWarner Losh     FICL_STRING *sp;
3012ca987d46SWarner Losh     int i;
3013ca987d46SWarner Losh #if FICL_ROBUST > 1
3014ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
3015ca987d46SWarner Losh #endif
3016ca987d46SWarner Losh 
3017ca987d46SWarner Losh     sp = PTRtoSTRING pVM->pad;
3018ca987d46SWarner Losh     i = POPINT();
3019ca987d46SWarner Losh     sp->text[sp->count++] = (char) i;
3020ca987d46SWarner Losh     return;
3021ca987d46SWarner Losh }
3022ca987d46SWarner Losh 
3023ca987d46SWarner Losh /*
3024ca987d46SWarner Losh ** SIGN             CORE ( n -- )
3025ca987d46SWarner Losh ** If n is negative, add a minus sign to the beginning of the pictured
3026ca987d46SWarner Losh ** numeric output string. An ambiguous condition exists if SIGN
3027ca987d46SWarner Losh ** executes outside of a <# #> delimited number conversion.
3028ca987d46SWarner Losh */
sign(FICL_VM * pVM)3029ca987d46SWarner Losh static void sign(FICL_VM *pVM)
3030ca987d46SWarner Losh {
3031ca987d46SWarner Losh     FICL_STRING *sp;
3032ca987d46SWarner Losh     int i;
3033ca987d46SWarner Losh #if FICL_ROBUST > 1
3034ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
3035ca987d46SWarner Losh #endif
3036ca987d46SWarner Losh 
3037ca987d46SWarner Losh     sp = PTRtoSTRING pVM->pad;
3038ca987d46SWarner Losh     i = POPINT();
3039ca987d46SWarner Losh     if (i < 0)
3040ca987d46SWarner Losh         sp->text[sp->count++] = '-';
3041ca987d46SWarner Losh     return;
3042ca987d46SWarner Losh }
3043ca987d46SWarner Losh 
3044ca987d46SWarner Losh 
3045ca987d46SWarner Losh /**************************************************************************
3046ca987d46SWarner Losh                         t o   N u m b e r
3047ca987d46SWarner Losh ** to-number CORE ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 )
3048ca987d46SWarner Losh ** ud2 is the unsigned result of converting the characters within the
3049ca987d46SWarner Losh ** string specified by c-addr1 u1 into digits, using the number in BASE,
3050ca987d46SWarner Losh ** and adding each into ud1 after multiplying ud1 by the number in BASE.
3051ca987d46SWarner Losh ** Conversion continues left-to-right until a character that is not
3052ca987d46SWarner Losh ** convertible, including any + or -, is encountered or the string is
3053ca987d46SWarner Losh ** entirely converted. c-addr2 is the location of the first unconverted
3054ca987d46SWarner Losh ** character or the first character past the end of the string if the string
3055ca987d46SWarner Losh ** was entirely converted. u2 is the number of unconverted characters in the
3056ca987d46SWarner Losh ** string. An ambiguous condition exists if ud2 overflows during the
3057ca987d46SWarner Losh ** conversion.
3058ca987d46SWarner Losh **************************************************************************/
toNumber(FICL_VM * pVM)3059ca987d46SWarner Losh static void toNumber(FICL_VM *pVM)
3060ca987d46SWarner Losh {
3061ca987d46SWarner Losh     FICL_UNS count;
3062ca987d46SWarner Losh     char *cp;
3063ca987d46SWarner Losh     DPUNS accum;
3064ca987d46SWarner Losh     FICL_UNS base = pVM->base;
3065ca987d46SWarner Losh     FICL_UNS ch;
3066ca987d46SWarner Losh     FICL_UNS digit;
3067ca987d46SWarner Losh 
3068ca987d46SWarner Losh #if FICL_ROBUST > 1
3069ca987d46SWarner Losh     vmCheckStack(pVM,4,4);
3070ca987d46SWarner Losh #endif
3071ca987d46SWarner Losh 
3072ca987d46SWarner Losh     count = POPUNS();
3073ca987d46SWarner Losh     cp = (char *)POPPTR();
3074ca987d46SWarner Losh     accum = u64Pop(pVM->pStack);
3075ca987d46SWarner Losh 
3076ca987d46SWarner Losh     for (ch = *cp; count > 0; ch = *++cp, count--)
3077ca987d46SWarner Losh     {
3078ca987d46SWarner Losh         if (ch < '0')
3079ca987d46SWarner Losh             break;
3080ca987d46SWarner Losh 
3081ca987d46SWarner Losh         digit = ch - '0';
3082ca987d46SWarner Losh 
3083ca987d46SWarner Losh         if (digit > 9)
3084ca987d46SWarner Losh             digit = tolower(ch) - 'a' + 10;
3085ca987d46SWarner Losh         /*
3086ca987d46SWarner Losh         ** Note: following test also catches chars between 9 and a
3087ca987d46SWarner Losh         ** because 'digit' is unsigned!
3088ca987d46SWarner Losh         */
3089ca987d46SWarner Losh         if (digit >= base)
3090ca987d46SWarner Losh             break;
3091ca987d46SWarner Losh 
3092ca987d46SWarner Losh         accum = m64Mac(accum, base, digit);
3093ca987d46SWarner Losh     }
3094ca987d46SWarner Losh 
3095ca987d46SWarner Losh     u64Push(pVM->pStack, accum);
3096ca987d46SWarner Losh     PUSHPTR(cp);
3097ca987d46SWarner Losh     PUSHUNS(count);
3098ca987d46SWarner Losh 
3099ca987d46SWarner Losh     return;
3100ca987d46SWarner Losh }
3101ca987d46SWarner Losh 
3102ca987d46SWarner Losh 
3103ca987d46SWarner Losh 
3104ca987d46SWarner Losh /**************************************************************************
3105ca987d46SWarner Losh                         q u i t   &   a b o r t
3106ca987d46SWarner Losh ** quit CORE   ( -- )  ( R:  i*x -- )
3107ca987d46SWarner Losh ** Empty the return stack, store zero in SOURCE-ID if it is present, make
3108ca987d46SWarner Losh ** the user input device the input source, and enter interpretation state.
3109ca987d46SWarner Losh ** Do not display a message. Repeat the following:
3110ca987d46SWarner Losh **
3111ca987d46SWarner Losh **   Accept a line from the input source into the input buffer, set >IN to
3112ca987d46SWarner Losh **   zero, and interpret.
3113ca987d46SWarner Losh **   Display the implementation-defined system prompt if in
3114ca987d46SWarner Losh **   interpretation state, all processing has been completed, and no
3115ca987d46SWarner Losh **   ambiguous condition exists.
3116ca987d46SWarner Losh **************************************************************************/
3117ca987d46SWarner Losh 
quit(FICL_VM * pVM)3118ca987d46SWarner Losh static void quit(FICL_VM *pVM)
3119ca987d46SWarner Losh {
3120ca987d46SWarner Losh     vmThrow(pVM, VM_QUIT);
3121ca987d46SWarner Losh     return;
3122ca987d46SWarner Losh }
3123ca987d46SWarner Losh 
3124ca987d46SWarner Losh 
ficlAbort(FICL_VM * pVM)3125ca987d46SWarner Losh static void ficlAbort(FICL_VM *pVM)
3126ca987d46SWarner Losh {
3127ca987d46SWarner Losh     vmThrow(pVM, VM_ABORT);
3128ca987d46SWarner Losh     return;
3129ca987d46SWarner Losh }
3130ca987d46SWarner Losh 
3131ca987d46SWarner Losh 
3132ca987d46SWarner Losh /**************************************************************************
3133ca987d46SWarner Losh                         a c c e p t
3134ca987d46SWarner Losh ** accept       CORE ( c-addr +n1 -- +n2 )
3135ca987d46SWarner Losh ** Receive a string of at most +n1 characters. An ambiguous condition
3136ca987d46SWarner Losh ** exists if +n1 is zero or greater than 32,767. Display graphic characters
3137ca987d46SWarner Losh ** as they are received. A program that depends on the presence or absence
3138ca987d46SWarner Losh ** of non-graphic characters in the string has an environmental dependency.
3139ca987d46SWarner Losh ** The editing functions, if any, that the system performs in order to
3140ca987d46SWarner Losh ** construct the string are implementation-defined.
3141ca987d46SWarner Losh **
3142ca987d46SWarner Losh ** (Although the standard text doesn't say so, I assume that the intent
3143ca987d46SWarner Losh ** of 'accept' is to store the string at the address specified on
3144ca987d46SWarner Losh ** the stack.)
3145ca987d46SWarner Losh ** Implementation: if there's more text in the TIB, use it. Otherwise
3146ca987d46SWarner Losh ** throw out for more text. Copy characters up to the max count into the
3147ca987d46SWarner Losh ** address given, and return the number of actual characters copied.
3148ca987d46SWarner Losh **
3149ca987d46SWarner Losh ** Note (sobral) this may not be the behavior you'd expect if you're
3150ca987d46SWarner Losh ** trying to get user input at load time!
3151ca987d46SWarner Losh **************************************************************************/
accept(FICL_VM * pVM)3152ca987d46SWarner Losh static void accept(FICL_VM *pVM)
3153ca987d46SWarner Losh {
3154ca987d46SWarner Losh     FICL_UNS count, len;
3155ca987d46SWarner Losh     char *cp;
3156ca987d46SWarner Losh     char *pBuf, *pEnd;
3157ca987d46SWarner Losh 
3158ca987d46SWarner Losh #if FICL_ROBUST > 1
3159ca987d46SWarner Losh     vmCheckStack(pVM,2,1);
3160ca987d46SWarner Losh #endif
3161ca987d46SWarner Losh 
3162ca987d46SWarner Losh     pBuf = vmGetInBuf(pVM);
3163ca987d46SWarner Losh     pEnd = vmGetInBufEnd(pVM);
3164ca987d46SWarner Losh     len = pEnd - pBuf;
3165ca987d46SWarner Losh     if (len == 0)
3166ca987d46SWarner Losh         vmThrow(pVM, VM_RESTART);
3167ca987d46SWarner Losh 
3168ca987d46SWarner Losh     /*
3169ca987d46SWarner Losh     ** Now we have something in the text buffer - use it
3170ca987d46SWarner Losh     */
3171ca987d46SWarner Losh     count = stackPopINT(pVM->pStack);
3172ca987d46SWarner Losh     cp    = stackPopPtr(pVM->pStack);
3173ca987d46SWarner Losh 
3174ca987d46SWarner Losh     len = (count < len) ? count : len;
3175ca987d46SWarner Losh     strncpy(cp, vmGetInBuf(pVM), len);
3176ca987d46SWarner Losh     pBuf += len;
3177ca987d46SWarner Losh     vmUpdateTib(pVM, pBuf);
3178ca987d46SWarner Losh     PUSHINT(len);
3179ca987d46SWarner Losh 
3180ca987d46SWarner Losh     return;
3181ca987d46SWarner Losh }
3182ca987d46SWarner Losh 
3183ca987d46SWarner Losh 
3184ca987d46SWarner Losh /**************************************************************************
3185ca987d46SWarner Losh                         a l i g n
3186ca987d46SWarner Losh ** 6.1.0705 ALIGN       CORE ( -- )
3187ca987d46SWarner Losh ** If the data-space pointer is not aligned, reserve enough space to
3188ca987d46SWarner Losh ** align it.
3189ca987d46SWarner Losh **************************************************************************/
align(FICL_VM * pVM)3190ca987d46SWarner Losh static void align(FICL_VM *pVM)
3191ca987d46SWarner Losh {
3192ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
3193ca987d46SWarner Losh     IGNORE(pVM);
3194ca987d46SWarner Losh     dictAlign(dp);
3195ca987d46SWarner Losh     return;
3196ca987d46SWarner Losh }
3197ca987d46SWarner Losh 
3198ca987d46SWarner Losh 
3199ca987d46SWarner Losh /**************************************************************************
3200ca987d46SWarner Losh                         a l i g n e d
3201ca987d46SWarner Losh **
3202ca987d46SWarner Losh **************************************************************************/
aligned(FICL_VM * pVM)3203ca987d46SWarner Losh static void aligned(FICL_VM *pVM)
3204ca987d46SWarner Losh {
3205ca987d46SWarner Losh     void *addr;
3206ca987d46SWarner Losh #if FICL_ROBUST > 1
3207ca987d46SWarner Losh     vmCheckStack(pVM,1,1);
3208ca987d46SWarner Losh #endif
3209ca987d46SWarner Losh 
3210ca987d46SWarner Losh     addr = POPPTR();
3211ca987d46SWarner Losh     PUSHPTR(alignPtr(addr));
3212ca987d46SWarner Losh     return;
3213ca987d46SWarner Losh }
3214ca987d46SWarner Losh 
3215ca987d46SWarner Losh 
3216ca987d46SWarner Losh /**************************************************************************
3217ca987d46SWarner Losh                         b e g i n   &   f r i e n d s
3218ca987d46SWarner Losh ** Indefinite loop control structures
3219ca987d46SWarner Losh ** A.6.1.0760 BEGIN
3220ca987d46SWarner Losh ** Typical use:
3221ca987d46SWarner Losh **      : X ... BEGIN ... test UNTIL ;
3222ca987d46SWarner Losh ** or
3223ca987d46SWarner Losh **      : X ... BEGIN ... test WHILE ... REPEAT ;
3224ca987d46SWarner Losh **************************************************************************/
beginCoIm(FICL_VM * pVM)3225ca987d46SWarner Losh static void beginCoIm(FICL_VM *pVM)
3226ca987d46SWarner Losh {
3227ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
3228ca987d46SWarner Losh     markBranch(dp, pVM, destTag);
3229ca987d46SWarner Losh     return;
3230ca987d46SWarner Losh }
3231ca987d46SWarner Losh 
untilCoIm(FICL_VM * pVM)3232ca987d46SWarner Losh static void untilCoIm(FICL_VM *pVM)
3233ca987d46SWarner Losh {
3234ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
3235ca987d46SWarner Losh 
3236ca987d46SWarner Losh     assert(pVM->pSys->pBranch0);
3237ca987d46SWarner Losh 
3238ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranch0));
3239ca987d46SWarner Losh     resolveBackBranch(dp, pVM, destTag);
3240ca987d46SWarner Losh     return;
3241ca987d46SWarner Losh }
3242ca987d46SWarner Losh 
whileCoIm(FICL_VM * pVM)3243ca987d46SWarner Losh static void whileCoIm(FICL_VM *pVM)
3244ca987d46SWarner Losh {
3245ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
3246ca987d46SWarner Losh 
3247ca987d46SWarner Losh     assert(pVM->pSys->pBranch0);
3248ca987d46SWarner Losh 
3249ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranch0));
3250ca987d46SWarner Losh     markBranch(dp, pVM, origTag);
3251ca987d46SWarner Losh     twoSwap(pVM);
3252ca987d46SWarner Losh     dictAppendUNS(dp, 1);
3253ca987d46SWarner Losh     return;
3254ca987d46SWarner Losh }
3255ca987d46SWarner Losh 
repeatCoIm(FICL_VM * pVM)3256ca987d46SWarner Losh static void repeatCoIm(FICL_VM *pVM)
3257ca987d46SWarner Losh {
3258ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
3259ca987d46SWarner Losh 
3260ca987d46SWarner Losh     assert(pVM->pSys->pBranchParen);
3261ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen));
3262ca987d46SWarner Losh 
3263ca987d46SWarner Losh     /* expect "begin" branch marker */
3264ca987d46SWarner Losh     resolveBackBranch(dp, pVM, destTag);
3265ca987d46SWarner Losh     /* expect "while" branch marker */
3266ca987d46SWarner Losh     resolveForwardBranch(dp, pVM, origTag);
3267ca987d46SWarner Losh     return;
3268ca987d46SWarner Losh }
3269ca987d46SWarner Losh 
3270ca987d46SWarner Losh 
againCoIm(FICL_VM * pVM)3271ca987d46SWarner Losh static void againCoIm(FICL_VM *pVM)
3272ca987d46SWarner Losh {
3273ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
3274ca987d46SWarner Losh 
3275ca987d46SWarner Losh     assert(pVM->pSys->pBranchParen);
3276ca987d46SWarner Losh     dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pBranchParen));
3277ca987d46SWarner Losh 
3278ca987d46SWarner Losh     /* expect "begin" branch marker */
3279ca987d46SWarner Losh     resolveBackBranch(dp, pVM, destTag);
3280ca987d46SWarner Losh     return;
3281ca987d46SWarner Losh }
3282ca987d46SWarner Losh 
3283ca987d46SWarner Losh 
3284ca987d46SWarner Losh /**************************************************************************
3285ca987d46SWarner Losh                         c h a r   &   f r i e n d s
3286ca987d46SWarner Losh ** 6.1.0895 CHAR    CORE ( "<spaces>name" -- char )
3287ca987d46SWarner Losh ** Skip leading space delimiters. Parse name delimited by a space.
3288ca987d46SWarner Losh ** Put the value of its first character onto the stack.
3289ca987d46SWarner Losh **
3290ca987d46SWarner Losh ** bracket-char     CORE
3291ca987d46SWarner Losh ** Interpretation: Interpretation semantics for this word are undefined.
3292ca987d46SWarner Losh ** Compilation: ( "<spaces>name" -- )
3293ca987d46SWarner Losh ** Skip leading space delimiters. Parse name delimited by a space.
3294ca987d46SWarner Losh ** Append the run-time semantics given below to the current definition.
3295ca987d46SWarner Losh ** Run-time: ( -- char )
3296ca987d46SWarner Losh ** Place char, the value of the first character of name, on the stack.
3297ca987d46SWarner Losh **************************************************************************/
ficlChar(FICL_VM * pVM)3298ca987d46SWarner Losh static void ficlChar(FICL_VM *pVM)
3299ca987d46SWarner Losh {
3300ca987d46SWarner Losh     STRINGINFO si;
3301ca987d46SWarner Losh #if FICL_ROBUST > 1
3302ca987d46SWarner Losh     vmCheckStack(pVM,0,1);
3303ca987d46SWarner Losh #endif
3304ca987d46SWarner Losh 
3305ca987d46SWarner Losh     si = vmGetWord(pVM);
3306ca987d46SWarner Losh     PUSHUNS((FICL_UNS)(si.cp[0]));
3307ca987d46SWarner Losh     return;
3308ca987d46SWarner Losh }
3309ca987d46SWarner Losh 
charCoIm(FICL_VM * pVM)3310ca987d46SWarner Losh static void charCoIm(FICL_VM *pVM)
3311ca987d46SWarner Losh {
3312ca987d46SWarner Losh     ficlChar(pVM);
3313ca987d46SWarner Losh     literalIm(pVM);
3314ca987d46SWarner Losh     return;
3315ca987d46SWarner Losh }
3316ca987d46SWarner Losh 
3317ca987d46SWarner Losh /**************************************************************************
3318ca987d46SWarner Losh                         c h a r P l u s
3319ca987d46SWarner Losh ** char-plus        CORE ( c-addr1 -- c-addr2 )
3320ca987d46SWarner Losh ** Add the size in address units of a character to c-addr1, giving c-addr2.
3321ca987d46SWarner Losh **************************************************************************/
charPlus(FICL_VM * pVM)3322ca987d46SWarner Losh static void charPlus(FICL_VM *pVM)
3323ca987d46SWarner Losh {
3324ca987d46SWarner Losh     char *cp;
3325ca987d46SWarner Losh #if FICL_ROBUST > 1
3326ca987d46SWarner Losh     vmCheckStack(pVM,1,1);
3327ca987d46SWarner Losh #endif
3328ca987d46SWarner Losh 
3329ca987d46SWarner Losh     cp = POPPTR();
3330ca987d46SWarner Losh     PUSHPTR(cp + 1);
3331ca987d46SWarner Losh     return;
3332ca987d46SWarner Losh }
3333ca987d46SWarner Losh 
3334ca987d46SWarner Losh /**************************************************************************
3335ca987d46SWarner Losh                         c h a r s
3336ca987d46SWarner Losh ** chars        CORE ( n1 -- n2 )
3337ca987d46SWarner Losh ** n2 is the size in address units of n1 characters.
3338ca987d46SWarner Losh ** For most processors, this function can be a no-op. To guarantee
3339ca987d46SWarner Losh ** portability, we'll multiply by sizeof (char).
3340ca987d46SWarner Losh **************************************************************************/
3341ca987d46SWarner Losh #if defined (_M_IX86)
3342ca987d46SWarner Losh #pragma warning(disable: 4127)
3343ca987d46SWarner Losh #endif
ficlChars(FICL_VM * pVM)3344ca987d46SWarner Losh static void ficlChars(FICL_VM *pVM)
3345ca987d46SWarner Losh {
3346ca987d46SWarner Losh     if (sizeof (char) > 1)
3347ca987d46SWarner Losh     {
3348ca987d46SWarner Losh         FICL_INT i;
3349ca987d46SWarner Losh #if FICL_ROBUST > 1
3350ca987d46SWarner Losh         vmCheckStack(pVM,1,1);
3351ca987d46SWarner Losh #endif
3352ca987d46SWarner Losh         i = POPINT();
3353ca987d46SWarner Losh         PUSHINT(i * sizeof (char));
3354ca987d46SWarner Losh     }
3355ca987d46SWarner Losh     /* otherwise no-op! */
3356ca987d46SWarner Losh     return;
3357ca987d46SWarner Losh }
3358ca987d46SWarner Losh #if defined (_M_IX86)
3359ca987d46SWarner Losh #pragma warning(default: 4127)
3360ca987d46SWarner Losh #endif
3361ca987d46SWarner Losh 
3362ca987d46SWarner Losh 
3363ca987d46SWarner Losh /**************************************************************************
3364ca987d46SWarner Losh                         c o u n t
3365ca987d46SWarner Losh ** COUNT    CORE ( c-addr1 -- c-addr2 u )
3366ca987d46SWarner Losh ** Return the character string specification for the counted string stored
3367ca987d46SWarner Losh ** at c-addr1. c-addr2 is the address of the first character after c-addr1.
3368ca987d46SWarner Losh ** u is the contents of the character at c-addr1, which is the length in
3369ca987d46SWarner Losh ** characters of the string at c-addr2.
3370ca987d46SWarner Losh **************************************************************************/
count(FICL_VM * pVM)3371ca987d46SWarner Losh static void count(FICL_VM *pVM)
3372ca987d46SWarner Losh {
3373ca987d46SWarner Losh     FICL_STRING *sp;
3374ca987d46SWarner Losh #if FICL_ROBUST > 1
3375ca987d46SWarner Losh     vmCheckStack(pVM,1,2);
3376ca987d46SWarner Losh #endif
3377ca987d46SWarner Losh 
3378ca987d46SWarner Losh     sp = POPPTR();
3379ca987d46SWarner Losh     PUSHPTR(sp->text);
3380ca987d46SWarner Losh     PUSHUNS(sp->count);
3381ca987d46SWarner Losh     return;
3382ca987d46SWarner Losh }
3383ca987d46SWarner Losh 
3384ca987d46SWarner Losh /**************************************************************************
3385ca987d46SWarner Losh                         e n v i r o n m e n t ?
3386ca987d46SWarner Losh ** environment-query CORE ( c-addr u -- false | i*x true )
3387ca987d46SWarner Losh ** c-addr is the address of a character string and u is the string's
3388ca987d46SWarner Losh ** character count. u may have a value in the range from zero to an
3389ca987d46SWarner Losh ** implementation-defined maximum which shall not be less than 31. The
3390ca987d46SWarner Losh ** character string should contain a keyword from 3.2.6 Environmental
3391ca987d46SWarner Losh ** queries or the optional word sets to be checked for correspondence
3392ca987d46SWarner Losh ** with an attribute of the present environment. If the system treats the
3393ca987d46SWarner Losh ** attribute as unknown, the returned flag is false; otherwise, the flag
3394ca987d46SWarner Losh ** is true and the i*x returned is of the type specified in the table for
3395ca987d46SWarner Losh ** the attribute queried.
3396ca987d46SWarner Losh **************************************************************************/
environmentQ(FICL_VM * pVM)3397ca987d46SWarner Losh static void environmentQ(FICL_VM *pVM)
3398ca987d46SWarner Losh {
3399ca987d46SWarner Losh     FICL_DICT *envp;
3400ca987d46SWarner Losh     FICL_WORD *pFW;
3401ca987d46SWarner Losh     STRINGINFO si;
3402ca987d46SWarner Losh #if FICL_ROBUST > 1
3403ca987d46SWarner Losh     vmCheckStack(pVM,2,1);
3404ca987d46SWarner Losh #endif
3405ca987d46SWarner Losh 
3406ca987d46SWarner Losh     envp = pVM->pSys->envp;
3407ca987d46SWarner Losh     si.count = (FICL_COUNT)stackPopUNS(pVM->pStack);
3408ca987d46SWarner Losh     si.cp    = stackPopPtr(pVM->pStack);
3409ca987d46SWarner Losh 
3410ca987d46SWarner Losh     pFW = dictLookup(envp, si);
3411ca987d46SWarner Losh 
3412ca987d46SWarner Losh     if (pFW != NULL)
3413ca987d46SWarner Losh     {
3414ca987d46SWarner Losh         vmExecute(pVM, pFW);
3415ca987d46SWarner Losh         PUSHINT(FICL_TRUE);
3416ca987d46SWarner Losh     }
3417ca987d46SWarner Losh     else
3418ca987d46SWarner Losh     {
3419ca987d46SWarner Losh         PUSHINT(FICL_FALSE);
3420ca987d46SWarner Losh     }
3421ca987d46SWarner Losh     return;
3422ca987d46SWarner Losh }
3423ca987d46SWarner Losh 
3424ca987d46SWarner Losh /**************************************************************************
3425ca987d46SWarner Losh                         e v a l u a t e
3426ca987d46SWarner Losh ** EVALUATE CORE ( i*x c-addr u -- j*x )
3427ca987d46SWarner Losh ** Save the current input source specification. Store minus-one (-1) in
3428ca987d46SWarner Losh ** SOURCE-ID if it is present. Make the string described by c-addr and u
3429ca987d46SWarner Losh ** both the input source and input buffer, set >IN to zero, and interpret.
3430ca987d46SWarner Losh ** When the parse area is empty, restore the prior input source
3431ca987d46SWarner Losh ** specification. Other stack effects are due to the words EVALUATEd.
3432ca987d46SWarner Losh **
3433ca987d46SWarner Losh **************************************************************************/
evaluate(FICL_VM * pVM)3434ca987d46SWarner Losh static void evaluate(FICL_VM *pVM)
3435ca987d46SWarner Losh {
3436ca987d46SWarner Losh     FICL_UNS count;
3437ca987d46SWarner Losh     char *cp;
3438ca987d46SWarner Losh     CELL id;
3439ca987d46SWarner Losh     int result;
3440ca987d46SWarner Losh #if FICL_ROBUST > 1
3441ca987d46SWarner Losh     vmCheckStack(pVM,2,0);
3442ca987d46SWarner Losh #endif
3443ca987d46SWarner Losh 
3444ca987d46SWarner Losh     count = POPUNS();
3445ca987d46SWarner Losh     cp = POPPTR();
3446ca987d46SWarner Losh 
3447ca987d46SWarner Losh     IGNORE(count);
3448ca987d46SWarner Losh     id = pVM->sourceID;
3449ca987d46SWarner Losh     pVM->sourceID.i = -1;
3450ca987d46SWarner Losh     result = ficlExecC(pVM, cp, count);
3451ca987d46SWarner Losh     pVM->sourceID = id;
3452ca987d46SWarner Losh     if (result != VM_OUTOFTEXT)
3453ca987d46SWarner Losh         vmThrow(pVM, result);
3454ca987d46SWarner Losh 
3455ca987d46SWarner Losh     return;
3456ca987d46SWarner Losh }
3457ca987d46SWarner Losh 
3458ca987d46SWarner Losh 
3459ca987d46SWarner Losh /**************************************************************************
3460ca987d46SWarner Losh                         s t r i n g   q u o t e
3461ca987d46SWarner Losh ** Interpreting: get string delimited by a quote from the input stream,
3462ca987d46SWarner Losh ** copy to a scratch area, and put its count and address on the stack.
3463ca987d46SWarner Losh ** Compiling: compile code to push the address and count of a string
3464ca987d46SWarner Losh ** literal, compile the string from the input stream, and align the dict
3465ca987d46SWarner Losh ** pointer.
3466ca987d46SWarner Losh **************************************************************************/
stringQuoteIm(FICL_VM * pVM)3467ca987d46SWarner Losh static void stringQuoteIm(FICL_VM *pVM)
3468ca987d46SWarner Losh {
3469ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
3470ca987d46SWarner Losh 
3471ca987d46SWarner Losh     if (pVM->state == INTERPRET)
3472ca987d46SWarner Losh     {
3473ca987d46SWarner Losh         FICL_STRING *sp = (FICL_STRING *) dp->here;
3474ca987d46SWarner Losh         vmGetString(pVM, sp, '\"');
3475ca987d46SWarner Losh         PUSHPTR(sp->text);
3476ca987d46SWarner Losh         PUSHUNS(sp->count);
3477ca987d46SWarner Losh     }
3478ca987d46SWarner Losh     else    /* COMPILE state */
3479ca987d46SWarner Losh     {
3480ca987d46SWarner Losh         dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStringLit));
3481ca987d46SWarner Losh         dp->here = PTRtoCELL vmGetString(pVM, (FICL_STRING *)dp->here, '\"');
3482ca987d46SWarner Losh         dictAlign(dp);
3483ca987d46SWarner Losh     }
3484ca987d46SWarner Losh 
3485ca987d46SWarner Losh     return;
3486ca987d46SWarner Losh }
3487ca987d46SWarner Losh 
3488ca987d46SWarner Losh 
3489ca987d46SWarner Losh /**************************************************************************
3490ca987d46SWarner Losh                         t y p e
3491ca987d46SWarner Losh ** Pop count and char address from stack and print the designated string.
3492ca987d46SWarner Losh **************************************************************************/
type(FICL_VM * pVM)3493ca987d46SWarner Losh static void type(FICL_VM *pVM)
3494ca987d46SWarner Losh {
3495ca987d46SWarner Losh     FICL_UNS count = stackPopUNS(pVM->pStack);
3496ca987d46SWarner Losh     char *cp    = stackPopPtr(pVM->pStack);
3497ca987d46SWarner Losh     char *pDest = (char *)ficlMalloc(count + 1);
3498ca987d46SWarner Losh 
3499ca987d46SWarner Losh     /*
3500ca987d46SWarner Losh     ** Since we don't have an output primitive for a counted string
3501ca987d46SWarner Losh     ** (oops), make sure the string is null terminated. If not, copy
3502ca987d46SWarner Losh     ** and terminate it.
3503ca987d46SWarner Losh     */
3504ca987d46SWarner Losh     if (!pDest)
3505ca987d46SWarner Losh 	vmThrowErr(pVM, "Error: out of memory");
3506ca987d46SWarner Losh 
3507ca987d46SWarner Losh     strncpy(pDest, cp, count);
3508ca987d46SWarner Losh     pDest[count] = '\0';
3509ca987d46SWarner Losh 
3510ca987d46SWarner Losh     vmTextOut(pVM, pDest, 0);
3511ca987d46SWarner Losh 
3512ca987d46SWarner Losh     ficlFree(pDest);
3513ca987d46SWarner Losh     return;
3514ca987d46SWarner Losh }
3515ca987d46SWarner Losh 
3516ca987d46SWarner Losh /**************************************************************************
3517ca987d46SWarner Losh                         w o r d
3518ca987d46SWarner Losh ** word CORE ( char "<chars>ccc<char>" -- c-addr )
3519ca987d46SWarner Losh ** Skip leading delimiters. Parse characters ccc delimited by char. An
3520ca987d46SWarner Losh ** ambiguous condition exists if the length of the parsed string is greater
3521ca987d46SWarner Losh ** than the implementation-defined length of a counted string.
3522ca987d46SWarner Losh **
3523ca987d46SWarner Losh ** c-addr is the address of a transient region containing the parsed word
3524ca987d46SWarner Losh ** as a counted string. If the parse area was empty or contained no
3525ca987d46SWarner Losh ** characters other than the delimiter, the resulting string has a zero
3526ca987d46SWarner Losh ** length. A space, not included in the length, follows the string. A
3527ca987d46SWarner Losh ** program may replace characters within the string.
3528ca987d46SWarner Losh ** NOTE! Ficl also NULL-terminates the dest string.
3529ca987d46SWarner Losh **************************************************************************/
ficlWord(FICL_VM * pVM)3530ca987d46SWarner Losh static void ficlWord(FICL_VM *pVM)
3531ca987d46SWarner Losh {
3532ca987d46SWarner Losh     FICL_STRING *sp;
3533ca987d46SWarner Losh     char delim;
3534ca987d46SWarner Losh     STRINGINFO   si;
3535ca987d46SWarner Losh #if FICL_ROBUST > 1
3536ca987d46SWarner Losh     vmCheckStack(pVM,1,1);
3537ca987d46SWarner Losh #endif
3538ca987d46SWarner Losh 
3539ca987d46SWarner Losh     sp = (FICL_STRING *)pVM->pad;
3540ca987d46SWarner Losh     delim = (char)POPINT();
3541ca987d46SWarner Losh     si = vmParseStringEx(pVM, delim, 1);
3542ca987d46SWarner Losh 
3543ca987d46SWarner Losh     if (SI_COUNT(si) > nPAD-1)
3544ca987d46SWarner Losh         SI_SETLEN(si, nPAD-1);
3545ca987d46SWarner Losh 
3546ca987d46SWarner Losh     sp->count = (FICL_COUNT)SI_COUNT(si);
3547ca987d46SWarner Losh     strncpy(sp->text, SI_PTR(si), SI_COUNT(si));
3548ca987d46SWarner Losh     /*#$-GUY CHANGE: I added this.-$#*/
3549ca987d46SWarner Losh     sp->text[sp->count] = 0;
3550ca987d46SWarner Losh     strcat(sp->text, " ");
3551ca987d46SWarner Losh 
3552ca987d46SWarner Losh     PUSHPTR(sp);
3553ca987d46SWarner Losh     return;
3554ca987d46SWarner Losh }
3555ca987d46SWarner Losh 
3556ca987d46SWarner Losh 
3557ca987d46SWarner Losh /**************************************************************************
3558ca987d46SWarner Losh                         p a r s e - w o r d
3559ca987d46SWarner Losh ** ficl   PARSE-WORD  ( <spaces>name -- c-addr u )
3560ca987d46SWarner Losh ** Skip leading spaces and parse name delimited by a space. c-addr is the
3561ca987d46SWarner Losh ** address within the input buffer and u is the length of the selected
3562ca987d46SWarner Losh ** string. If the parse area is empty, the resulting string has a zero length.
3563ca987d46SWarner Losh **************************************************************************/
parseNoCopy(FICL_VM * pVM)3564ca987d46SWarner Losh static void parseNoCopy(FICL_VM *pVM)
3565ca987d46SWarner Losh {
3566ca987d46SWarner Losh     STRINGINFO si;
3567ca987d46SWarner Losh #if FICL_ROBUST > 1
3568ca987d46SWarner Losh     vmCheckStack(pVM,0,2);
3569ca987d46SWarner Losh #endif
3570ca987d46SWarner Losh 
3571ca987d46SWarner Losh     si = vmGetWord0(pVM);
3572ca987d46SWarner Losh     PUSHPTR(SI_PTR(si));
3573ca987d46SWarner Losh     PUSHUNS(SI_COUNT(si));
3574ca987d46SWarner Losh     return;
3575ca987d46SWarner Losh }
3576ca987d46SWarner Losh 
3577ca987d46SWarner Losh 
3578ca987d46SWarner Losh /**************************************************************************
3579ca987d46SWarner Losh                         p a r s e
3580ca987d46SWarner Losh ** CORE EXT  ( char "ccc<char>" -- c-addr u )
3581ca987d46SWarner Losh ** Parse ccc delimited by the delimiter char.
3582ca987d46SWarner Losh ** c-addr is the address (within the input buffer) and u is the length of
3583ca987d46SWarner Losh ** the parsed string. If the parse area was empty, the resulting string has
3584ca987d46SWarner Losh ** a zero length.
3585ca987d46SWarner Losh ** NOTE! PARSE differs from WORD: it does not skip leading delimiters.
3586ca987d46SWarner Losh **************************************************************************/
parse(FICL_VM * pVM)3587ca987d46SWarner Losh static void parse(FICL_VM *pVM)
3588ca987d46SWarner Losh {
3589ca987d46SWarner Losh     STRINGINFO si;
3590ca987d46SWarner Losh     char delim;
3591ca987d46SWarner Losh 
3592ca987d46SWarner Losh #if FICL_ROBUST > 1
3593ca987d46SWarner Losh     vmCheckStack(pVM,1,2);
3594ca987d46SWarner Losh #endif
3595ca987d46SWarner Losh 
3596ca987d46SWarner Losh     delim = (char)POPINT();
3597ca987d46SWarner Losh 
3598ca987d46SWarner Losh     si = vmParseStringEx(pVM, delim, 0);
3599ca987d46SWarner Losh     PUSHPTR(SI_PTR(si));
3600ca987d46SWarner Losh     PUSHUNS(SI_COUNT(si));
3601ca987d46SWarner Losh     return;
3602ca987d46SWarner Losh }
3603ca987d46SWarner Losh 
3604ca987d46SWarner Losh 
3605ca987d46SWarner Losh /**************************************************************************
3606ca987d46SWarner Losh                         f i l l
3607ca987d46SWarner Losh ** CORE ( c-addr u char -- )
3608ca987d46SWarner Losh ** If u is greater than zero, store char in each of u consecutive
3609ca987d46SWarner Losh ** characters of memory beginning at c-addr.
3610ca987d46SWarner Losh **************************************************************************/
fill(FICL_VM * pVM)3611ca987d46SWarner Losh static void fill(FICL_VM *pVM)
3612ca987d46SWarner Losh {
3613ca987d46SWarner Losh     char ch;
3614ca987d46SWarner Losh     FICL_UNS u;
3615ca987d46SWarner Losh     char *cp;
3616ca987d46SWarner Losh #if FICL_ROBUST > 1
3617ca987d46SWarner Losh     vmCheckStack(pVM,3,0);
3618ca987d46SWarner Losh #endif
3619ca987d46SWarner Losh     ch = (char)POPINT();
3620ca987d46SWarner Losh     u = POPUNS();
3621ca987d46SWarner Losh     cp = (char *)POPPTR();
3622ca987d46SWarner Losh 
3623ca987d46SWarner Losh     while (u > 0)
3624ca987d46SWarner Losh     {
3625ca987d46SWarner Losh         *cp++ = ch;
3626ca987d46SWarner Losh         u--;
3627ca987d46SWarner Losh     }
3628ca987d46SWarner Losh     return;
3629ca987d46SWarner Losh }
3630ca987d46SWarner Losh 
3631ca987d46SWarner Losh 
3632ca987d46SWarner Losh /**************************************************************************
3633ca987d46SWarner Losh                         f i n d
3634ca987d46SWarner Losh ** FIND CORE ( c-addr -- c-addr 0  |  xt 1  |  xt -1 )
3635ca987d46SWarner Losh ** Find the definition named in the counted string at c-addr. If the
3636ca987d46SWarner Losh ** definition is not found, return c-addr and zero. If the definition is
3637ca987d46SWarner Losh ** found, return its execution token xt. If the definition is immediate,
3638ca987d46SWarner Losh ** also return one (1), otherwise also return minus-one (-1). For a given
3639ca987d46SWarner Losh ** string, the values returned by FIND while compiling may differ from
3640ca987d46SWarner Losh ** those returned while not compiling.
3641ca987d46SWarner Losh **************************************************************************/
do_find(FICL_VM * pVM,STRINGINFO si,void * returnForFailure)3642ca987d46SWarner Losh static void do_find(FICL_VM *pVM, STRINGINFO si, void *returnForFailure)
3643ca987d46SWarner Losh {
3644ca987d46SWarner Losh     FICL_WORD *pFW;
3645ca987d46SWarner Losh 
3646ca987d46SWarner Losh     pFW = dictLookup(vmGetDict(pVM), si);
3647ca987d46SWarner Losh     if (pFW)
3648ca987d46SWarner Losh     {
3649ca987d46SWarner Losh         PUSHPTR(pFW);
3650ca987d46SWarner Losh         PUSHINT((wordIsImmediate(pFW) ? 1 : -1));
3651ca987d46SWarner Losh     }
3652ca987d46SWarner Losh     else
3653ca987d46SWarner Losh     {
3654ca987d46SWarner Losh         PUSHPTR(returnForFailure);
3655ca987d46SWarner Losh         PUSHUNS(0);
3656ca987d46SWarner Losh     }
3657ca987d46SWarner Losh     return;
3658ca987d46SWarner Losh }
3659ca987d46SWarner Losh 
3660ca987d46SWarner Losh 
3661ca987d46SWarner Losh 
3662ca987d46SWarner Losh /**************************************************************************
3663ca987d46SWarner Losh                         f i n d
3664ca987d46SWarner Losh ** FIND CORE ( c-addr -- c-addr 0  |  xt 1  |  xt -1 )
3665ca987d46SWarner Losh ** Find the definition named in the counted string at c-addr. If the
3666ca987d46SWarner Losh ** definition is not found, return c-addr and zero. If the definition is
3667ca987d46SWarner Losh ** found, return its execution token xt. If the definition is immediate,
3668ca987d46SWarner Losh ** also return one (1), otherwise also return minus-one (-1). For a given
3669ca987d46SWarner Losh ** string, the values returned by FIND while compiling may differ from
3670ca987d46SWarner Losh ** those returned while not compiling.
3671ca987d46SWarner Losh **************************************************************************/
cFind(FICL_VM * pVM)3672ca987d46SWarner Losh static void cFind(FICL_VM *pVM)
3673ca987d46SWarner Losh {
3674ca987d46SWarner Losh     FICL_STRING *sp;
3675ca987d46SWarner Losh     STRINGINFO si;
3676ca987d46SWarner Losh 
3677ca987d46SWarner Losh #if FICL_ROBUST > 1
3678ca987d46SWarner Losh     vmCheckStack(pVM,1,2);
3679ca987d46SWarner Losh #endif
3680ca987d46SWarner Losh     sp = POPPTR();
3681ca987d46SWarner Losh     SI_PFS(si, sp);
3682ca987d46SWarner Losh     do_find(pVM, si, sp);
3683ca987d46SWarner Losh }
3684ca987d46SWarner Losh 
3685ca987d46SWarner Losh 
3686ca987d46SWarner Losh 
3687ca987d46SWarner Losh /**************************************************************************
3688ca987d46SWarner Losh                         s f i n d
3689ca987d46SWarner Losh ** FICL   ( c-addr u -- 0 0  |  xt 1  |  xt -1 )
3690ca987d46SWarner Losh ** Like FIND, but takes "c-addr u" for the string.
3691ca987d46SWarner Losh **************************************************************************/
sFind(FICL_VM * pVM)3692ca987d46SWarner Losh static void sFind(FICL_VM *pVM)
3693ca987d46SWarner Losh {
3694ca987d46SWarner Losh     STRINGINFO si;
3695ca987d46SWarner Losh 
3696ca987d46SWarner Losh #if FICL_ROBUST > 1
3697ca987d46SWarner Losh     vmCheckStack(pVM,2,2);
3698ca987d46SWarner Losh #endif
3699ca987d46SWarner Losh 
3700ca987d46SWarner Losh     si.count = stackPopINT(pVM->pStack);
3701ca987d46SWarner Losh     si.cp = stackPopPtr(pVM->pStack);
3702ca987d46SWarner Losh 
3703ca987d46SWarner Losh     do_find(pVM, si, NULL);
3704ca987d46SWarner Losh }
3705ca987d46SWarner Losh 
3706ca987d46SWarner Losh 
3707ca987d46SWarner Losh 
3708ca987d46SWarner Losh /**************************************************************************
3709ca987d46SWarner Losh                         f m S l a s h M o d
3710ca987d46SWarner Losh ** f-m-slash-mod CORE ( d1 n1 -- n2 n3 )
3711ca987d46SWarner Losh ** Divide d1 by n1, giving the floored quotient n3 and the remainder n2.
3712ca987d46SWarner Losh ** Input and output stack arguments are signed. An ambiguous condition
3713ca987d46SWarner Losh ** exists if n1 is zero or if the quotient lies outside the range of a
3714ca987d46SWarner Losh ** single-cell signed integer.
3715ca987d46SWarner Losh **************************************************************************/
fmSlashMod(FICL_VM * pVM)3716ca987d46SWarner Losh static void fmSlashMod(FICL_VM *pVM)
3717ca987d46SWarner Losh {
3718ca987d46SWarner Losh     DPINT d1;
3719ca987d46SWarner Losh     FICL_INT n1;
3720ca987d46SWarner Losh     INTQR qr;
3721ca987d46SWarner Losh #if FICL_ROBUST > 1
3722ca987d46SWarner Losh     vmCheckStack(pVM,3,2);
3723ca987d46SWarner Losh #endif
3724ca987d46SWarner Losh 
3725ca987d46SWarner Losh     n1 = POPINT();
3726ca987d46SWarner Losh     d1 = i64Pop(pVM->pStack);
3727ca987d46SWarner Losh     qr = m64FlooredDivI(d1, n1);
3728ca987d46SWarner Losh     PUSHINT(qr.rem);
3729ca987d46SWarner Losh     PUSHINT(qr.quot);
3730ca987d46SWarner Losh     return;
3731ca987d46SWarner Losh }
3732ca987d46SWarner Losh 
3733ca987d46SWarner Losh 
3734ca987d46SWarner Losh /**************************************************************************
3735ca987d46SWarner Losh                         s m S l a s h R e m
3736ca987d46SWarner Losh ** s-m-slash-rem CORE ( d1 n1 -- n2 n3 )
3737ca987d46SWarner Losh ** Divide d1 by n1, giving the symmetric quotient n3 and the remainder n2.
3738ca987d46SWarner Losh ** Input and output stack arguments are signed. An ambiguous condition
3739ca987d46SWarner Losh ** exists if n1 is zero or if the quotient lies outside the range of a
3740ca987d46SWarner Losh ** single-cell signed integer.
3741ca987d46SWarner Losh **************************************************************************/
smSlashRem(FICL_VM * pVM)3742ca987d46SWarner Losh static void smSlashRem(FICL_VM *pVM)
3743ca987d46SWarner Losh {
3744ca987d46SWarner Losh     DPINT d1;
3745ca987d46SWarner Losh     FICL_INT n1;
3746ca987d46SWarner Losh     INTQR qr;
3747ca987d46SWarner Losh #if FICL_ROBUST > 1
3748ca987d46SWarner Losh     vmCheckStack(pVM,3,2);
3749ca987d46SWarner Losh #endif
3750ca987d46SWarner Losh 
3751ca987d46SWarner Losh     n1 = POPINT();
3752ca987d46SWarner Losh     d1 = i64Pop(pVM->pStack);
3753ca987d46SWarner Losh     qr = m64SymmetricDivI(d1, n1);
3754ca987d46SWarner Losh     PUSHINT(qr.rem);
3755ca987d46SWarner Losh     PUSHINT(qr.quot);
3756ca987d46SWarner Losh     return;
3757ca987d46SWarner Losh }
3758ca987d46SWarner Losh 
3759ca987d46SWarner Losh 
ficlMod(FICL_VM * pVM)3760ca987d46SWarner Losh static void ficlMod(FICL_VM *pVM)
3761ca987d46SWarner Losh {
3762ca987d46SWarner Losh     DPINT d1;
3763ca987d46SWarner Losh     FICL_INT n1;
3764ca987d46SWarner Losh     INTQR qr;
3765ca987d46SWarner Losh #if FICL_ROBUST > 1
3766ca987d46SWarner Losh     vmCheckStack(pVM,2,1);
3767ca987d46SWarner Losh #endif
3768ca987d46SWarner Losh 
3769ca987d46SWarner Losh     n1 = POPINT();
3770ca987d46SWarner Losh     d1.lo = POPINT();
3771ca987d46SWarner Losh     i64Extend(d1);
3772ca987d46SWarner Losh     qr = m64SymmetricDivI(d1, n1);
3773ca987d46SWarner Losh     PUSHINT(qr.rem);
3774ca987d46SWarner Losh     return;
3775ca987d46SWarner Losh }
3776ca987d46SWarner Losh 
3777ca987d46SWarner Losh 
3778ca987d46SWarner Losh /**************************************************************************
3779ca987d46SWarner Losh                         u m S l a s h M o d
3780ca987d46SWarner Losh ** u-m-slash-mod CORE ( ud u1 -- u2 u3 )
3781ca987d46SWarner Losh ** Divide ud by u1, giving the quotient u3 and the remainder u2.
3782ca987d46SWarner Losh ** All values and arithmetic are unsigned. An ambiguous condition
3783ca987d46SWarner Losh ** exists if u1 is zero or if the quotient lies outside the range of a
3784ca987d46SWarner Losh ** single-cell unsigned integer.
3785ca987d46SWarner Losh *************************************************************************/
umSlashMod(FICL_VM * pVM)3786ca987d46SWarner Losh static void umSlashMod(FICL_VM *pVM)
3787ca987d46SWarner Losh {
3788ca987d46SWarner Losh     DPUNS ud;
3789ca987d46SWarner Losh     FICL_UNS u1;
3790ca987d46SWarner Losh     UNSQR qr;
3791ca987d46SWarner Losh 
3792ca987d46SWarner Losh     u1    = stackPopUNS(pVM->pStack);
3793ca987d46SWarner Losh     ud    = u64Pop(pVM->pStack);
3794ca987d46SWarner Losh     qr    = ficlLongDiv(ud, u1);
3795ca987d46SWarner Losh     PUSHUNS(qr.rem);
3796ca987d46SWarner Losh     PUSHUNS(qr.quot);
3797ca987d46SWarner Losh     return;
3798ca987d46SWarner Losh }
3799ca987d46SWarner Losh 
3800ca987d46SWarner Losh 
3801ca987d46SWarner Losh /**************************************************************************
3802ca987d46SWarner Losh                         l s h i f t
3803ca987d46SWarner Losh ** l-shift CORE ( x1 u -- x2 )
3804ca987d46SWarner Losh ** Perform a logical left shift of u bit-places on x1, giving x2.
3805ca987d46SWarner Losh ** Put zeroes into the least significant bits vacated by the shift.
3806ca987d46SWarner Losh ** An ambiguous condition exists if u is greater than or equal to the
3807ca987d46SWarner Losh ** number of bits in a cell.
3808ca987d46SWarner Losh **
3809ca987d46SWarner Losh ** r-shift CORE ( x1 u -- x2 )
3810ca987d46SWarner Losh ** Perform a logical right shift of u bit-places on x1, giving x2.
3811ca987d46SWarner Losh ** Put zeroes into the most significant bits vacated by the shift. An
3812ca987d46SWarner Losh ** ambiguous condition exists if u is greater than or equal to the
3813ca987d46SWarner Losh ** number of bits in a cell.
3814ca987d46SWarner Losh **************************************************************************/
lshift(FICL_VM * pVM)3815ca987d46SWarner Losh static void lshift(FICL_VM *pVM)
3816ca987d46SWarner Losh {
3817ca987d46SWarner Losh     FICL_UNS nBits;
3818ca987d46SWarner Losh     FICL_UNS x1;
3819ca987d46SWarner Losh #if FICL_ROBUST > 1
3820ca987d46SWarner Losh     vmCheckStack(pVM,2,1);
3821ca987d46SWarner Losh #endif
3822ca987d46SWarner Losh 
3823ca987d46SWarner Losh     nBits = POPUNS();
3824ca987d46SWarner Losh     x1 = POPUNS();
3825ca987d46SWarner Losh     PUSHUNS(x1 << nBits);
3826ca987d46SWarner Losh     return;
3827ca987d46SWarner Losh }
3828ca987d46SWarner Losh 
3829ca987d46SWarner Losh 
rshift(FICL_VM * pVM)3830ca987d46SWarner Losh static void rshift(FICL_VM *pVM)
3831ca987d46SWarner Losh {
3832ca987d46SWarner Losh     FICL_UNS nBits;
3833ca987d46SWarner Losh     FICL_UNS x1;
3834ca987d46SWarner Losh #if FICL_ROBUST > 1
3835ca987d46SWarner Losh     vmCheckStack(pVM,2,1);
3836ca987d46SWarner Losh #endif
3837ca987d46SWarner Losh 
3838ca987d46SWarner Losh     nBits = POPUNS();
3839ca987d46SWarner Losh     x1 = POPUNS();
3840ca987d46SWarner Losh 
3841ca987d46SWarner Losh     PUSHUNS(x1 >> nBits);
3842ca987d46SWarner Losh     return;
3843ca987d46SWarner Losh }
3844ca987d46SWarner Losh 
3845ca987d46SWarner Losh 
3846ca987d46SWarner Losh /**************************************************************************
3847ca987d46SWarner Losh                         m S t a r
3848ca987d46SWarner Losh ** m-star CORE ( n1 n2 -- d )
3849ca987d46SWarner Losh ** d is the signed product of n1 times n2.
3850ca987d46SWarner Losh **************************************************************************/
mStar(FICL_VM * pVM)3851ca987d46SWarner Losh static void mStar(FICL_VM *pVM)
3852ca987d46SWarner Losh {
3853ca987d46SWarner Losh     FICL_INT n2;
3854ca987d46SWarner Losh     FICL_INT n1;
3855ca987d46SWarner Losh     DPINT d;
3856ca987d46SWarner Losh #if FICL_ROBUST > 1
3857ca987d46SWarner Losh     vmCheckStack(pVM,2,2);
3858ca987d46SWarner Losh #endif
3859ca987d46SWarner Losh 
3860ca987d46SWarner Losh     n2 = POPINT();
3861ca987d46SWarner Losh     n1 = POPINT();
3862ca987d46SWarner Losh 
3863ca987d46SWarner Losh     d = m64MulI(n1, n2);
3864ca987d46SWarner Losh     i64Push(pVM->pStack, d);
3865ca987d46SWarner Losh     return;
3866ca987d46SWarner Losh }
3867ca987d46SWarner Losh 
3868ca987d46SWarner Losh 
umStar(FICL_VM * pVM)3869ca987d46SWarner Losh static void umStar(FICL_VM *pVM)
3870ca987d46SWarner Losh {
3871ca987d46SWarner Losh     FICL_UNS u2;
3872ca987d46SWarner Losh     FICL_UNS u1;
3873ca987d46SWarner Losh     DPUNS ud;
3874ca987d46SWarner Losh #if FICL_ROBUST > 1
3875ca987d46SWarner Losh     vmCheckStack(pVM,2,2);
3876ca987d46SWarner Losh #endif
3877ca987d46SWarner Losh 
3878ca987d46SWarner Losh     u2 = POPUNS();
3879ca987d46SWarner Losh     u1 = POPUNS();
3880ca987d46SWarner Losh 
3881ca987d46SWarner Losh     ud = ficlLongMul(u1, u2);
3882ca987d46SWarner Losh     u64Push(pVM->pStack, ud);
3883ca987d46SWarner Losh     return;
3884ca987d46SWarner Losh }
3885ca987d46SWarner Losh 
3886ca987d46SWarner Losh 
3887ca987d46SWarner Losh /**************************************************************************
3888ca987d46SWarner Losh                         m a x   &   m i n
3889ca987d46SWarner Losh **
3890ca987d46SWarner Losh **************************************************************************/
ficlMax(FICL_VM * pVM)3891ca987d46SWarner Losh static void ficlMax(FICL_VM *pVM)
3892ca987d46SWarner Losh {
3893ca987d46SWarner Losh     FICL_INT n2;
3894ca987d46SWarner Losh     FICL_INT n1;
3895ca987d46SWarner Losh #if FICL_ROBUST > 1
3896ca987d46SWarner Losh     vmCheckStack(pVM,2,1);
3897ca987d46SWarner Losh #endif
3898ca987d46SWarner Losh 
3899ca987d46SWarner Losh     n2 = POPINT();
3900ca987d46SWarner Losh     n1 = POPINT();
3901ca987d46SWarner Losh 
3902ca987d46SWarner Losh     PUSHINT((n1 > n2) ? n1 : n2);
3903ca987d46SWarner Losh     return;
3904ca987d46SWarner Losh }
3905ca987d46SWarner Losh 
ficlMin(FICL_VM * pVM)3906ca987d46SWarner Losh static void ficlMin(FICL_VM *pVM)
3907ca987d46SWarner Losh {
3908ca987d46SWarner Losh     FICL_INT n2;
3909ca987d46SWarner Losh     FICL_INT n1;
3910ca987d46SWarner Losh #if FICL_ROBUST > 1
3911ca987d46SWarner Losh     vmCheckStack(pVM,2,1);
3912ca987d46SWarner Losh #endif
3913ca987d46SWarner Losh 
3914ca987d46SWarner Losh     n2 = POPINT();
3915ca987d46SWarner Losh     n1 = POPINT();
3916ca987d46SWarner Losh 
3917ca987d46SWarner Losh     PUSHINT((n1 < n2) ? n1 : n2);
3918ca987d46SWarner Losh     return;
3919ca987d46SWarner Losh }
3920ca987d46SWarner Losh 
3921ca987d46SWarner Losh 
3922ca987d46SWarner Losh /**************************************************************************
3923ca987d46SWarner Losh                         m o v e
3924ca987d46SWarner Losh ** CORE ( addr1 addr2 u -- )
3925ca987d46SWarner Losh ** If u is greater than zero, copy the contents of u consecutive address
3926ca987d46SWarner Losh ** units at addr1 to the u consecutive address units at addr2. After MOVE
3927ca987d46SWarner Losh ** completes, the u consecutive address units at addr2 contain exactly
3928ca987d46SWarner Losh ** what the u consecutive address units at addr1 contained before the move.
3929ca987d46SWarner Losh ** NOTE! This implementation assumes that a char is the same size as
3930ca987d46SWarner Losh **       an address unit.
3931ca987d46SWarner Losh **************************************************************************/
move(FICL_VM * pVM)3932ca987d46SWarner Losh static void move(FICL_VM *pVM)
3933ca987d46SWarner Losh {
3934ca987d46SWarner Losh     FICL_UNS u;
3935ca987d46SWarner Losh     char *addr2;
3936ca987d46SWarner Losh     char *addr1;
3937ca987d46SWarner Losh #if FICL_ROBUST > 1
3938ca987d46SWarner Losh     vmCheckStack(pVM,3,0);
3939ca987d46SWarner Losh #endif
3940ca987d46SWarner Losh 
3941ca987d46SWarner Losh     u = POPUNS();
3942ca987d46SWarner Losh     addr2 = POPPTR();
3943ca987d46SWarner Losh     addr1 = POPPTR();
3944ca987d46SWarner Losh 
3945ca987d46SWarner Losh     if (u == 0)
3946ca987d46SWarner Losh         return;
3947ca987d46SWarner Losh     /*
3948ca987d46SWarner Losh     ** Do the copy carefully, so as to be
3949ca987d46SWarner Losh     ** correct even if the two ranges overlap
3950ca987d46SWarner Losh     */
3951ca987d46SWarner Losh     if (addr1 >= addr2)
3952ca987d46SWarner Losh     {
3953ca987d46SWarner Losh         for (; u > 0; u--)
3954ca987d46SWarner Losh             *addr2++ = *addr1++;
3955ca987d46SWarner Losh     }
3956ca987d46SWarner Losh     else
3957ca987d46SWarner Losh     {
3958ca987d46SWarner Losh         addr2 += u-1;
3959ca987d46SWarner Losh         addr1 += u-1;
3960ca987d46SWarner Losh         for (; u > 0; u--)
3961ca987d46SWarner Losh             *addr2-- = *addr1--;
3962ca987d46SWarner Losh     }
3963ca987d46SWarner Losh 
3964ca987d46SWarner Losh     return;
3965ca987d46SWarner Losh }
3966ca987d46SWarner Losh 
3967ca987d46SWarner Losh 
3968ca987d46SWarner Losh /**************************************************************************
3969ca987d46SWarner Losh                         r e c u r s e
3970ca987d46SWarner Losh **
3971ca987d46SWarner Losh **************************************************************************/
recurseCoIm(FICL_VM * pVM)3972ca987d46SWarner Losh static void recurseCoIm(FICL_VM *pVM)
3973ca987d46SWarner Losh {
3974ca987d46SWarner Losh     FICL_DICT *pDict = vmGetDict(pVM);
3975ca987d46SWarner Losh 
3976ca987d46SWarner Losh     IGNORE(pVM);
3977ca987d46SWarner Losh     dictAppendCell(pDict, LVALUEtoCELL(pDict->smudge));
3978ca987d46SWarner Losh     return;
3979ca987d46SWarner Losh }
3980ca987d46SWarner Losh 
3981ca987d46SWarner Losh 
3982ca987d46SWarner Losh /**************************************************************************
3983ca987d46SWarner Losh                         s t o d
3984ca987d46SWarner Losh ** s-to-d CORE ( n -- d )
3985ca987d46SWarner Losh ** Convert the number n to the double-cell number d with the same
3986ca987d46SWarner Losh ** numerical value.
3987ca987d46SWarner Losh **************************************************************************/
sToD(FICL_VM * pVM)3988ca987d46SWarner Losh static void sToD(FICL_VM *pVM)
3989ca987d46SWarner Losh {
3990ca987d46SWarner Losh     FICL_INT s;
3991ca987d46SWarner Losh #if FICL_ROBUST > 1
3992ca987d46SWarner Losh     vmCheckStack(pVM,1,2);
3993ca987d46SWarner Losh #endif
3994ca987d46SWarner Losh 
3995ca987d46SWarner Losh     s = POPINT();
3996ca987d46SWarner Losh 
3997ca987d46SWarner Losh     /* sign extend to 64 bits.. */
3998ca987d46SWarner Losh     PUSHINT(s);
3999ca987d46SWarner Losh     PUSHINT((s < 0) ? -1 : 0);
4000ca987d46SWarner Losh     return;
4001ca987d46SWarner Losh }
4002ca987d46SWarner Losh 
4003ca987d46SWarner Losh 
4004ca987d46SWarner Losh /**************************************************************************
4005ca987d46SWarner Losh                         s o u r c e
4006ca987d46SWarner Losh ** CORE ( -- c-addr u )
4007ca987d46SWarner Losh ** c-addr is the address of, and u is the number of characters in, the
4008ca987d46SWarner Losh ** input buffer.
4009ca987d46SWarner Losh **************************************************************************/
source(FICL_VM * pVM)4010ca987d46SWarner Losh static void source(FICL_VM *pVM)
4011ca987d46SWarner Losh {
4012ca987d46SWarner Losh #if FICL_ROBUST > 1
4013ca987d46SWarner Losh     vmCheckStack(pVM,0,2);
4014ca987d46SWarner Losh #endif
4015ca987d46SWarner Losh     PUSHPTR(pVM->tib.cp);
4016ca987d46SWarner Losh     PUSHINT(vmGetInBufLen(pVM));
4017ca987d46SWarner Losh     return;
4018ca987d46SWarner Losh }
4019ca987d46SWarner Losh 
4020ca987d46SWarner Losh 
4021ca987d46SWarner Losh /**************************************************************************
4022ca987d46SWarner Losh                         v e r s i o n
4023ca987d46SWarner Losh ** non-standard...
4024ca987d46SWarner Losh **************************************************************************/
ficlVersion(FICL_VM * pVM)4025ca987d46SWarner Losh static void ficlVersion(FICL_VM *pVM)
4026ca987d46SWarner Losh {
4027ca987d46SWarner Losh     vmTextOut(pVM, "ficl Version " FICL_VER, 1);
4028ca987d46SWarner Losh     return;
4029ca987d46SWarner Losh }
4030ca987d46SWarner Losh 
4031ca987d46SWarner Losh 
4032ca987d46SWarner Losh /**************************************************************************
4033ca987d46SWarner Losh                         t o I n
4034ca987d46SWarner Losh ** to-in CORE
4035ca987d46SWarner Losh **************************************************************************/
toIn(FICL_VM * pVM)4036ca987d46SWarner Losh static void toIn(FICL_VM *pVM)
4037ca987d46SWarner Losh {
4038ca987d46SWarner Losh #if FICL_ROBUST > 1
4039ca987d46SWarner Losh     vmCheckStack(pVM,0,1);
4040ca987d46SWarner Losh #endif
4041ca987d46SWarner Losh     PUSHPTR(&pVM->tib.index);
4042ca987d46SWarner Losh     return;
4043ca987d46SWarner Losh }
4044ca987d46SWarner Losh 
4045ca987d46SWarner Losh 
4046ca987d46SWarner Losh /**************************************************************************
4047ca987d46SWarner Losh                         c o l o n N o N a m e
4048ca987d46SWarner Losh ** CORE EXT ( C:  -- colon-sys )  ( S:  -- xt )
4049ca987d46SWarner Losh ** Create an unnamed colon definition and push its address.
4050ca987d46SWarner Losh ** Change state to compile.
4051ca987d46SWarner Losh **************************************************************************/
colonNoName(FICL_VM * pVM)4052ca987d46SWarner Losh static void colonNoName(FICL_VM *pVM)
4053ca987d46SWarner Losh {
4054ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
4055ca987d46SWarner Losh     FICL_WORD *pFW;
4056ca987d46SWarner Losh     STRINGINFO si;
4057ca987d46SWarner Losh 
4058ca987d46SWarner Losh     SI_SETLEN(si, 0);
4059ca987d46SWarner Losh     SI_SETPTR(si, NULL);
4060ca987d46SWarner Losh 
4061ca987d46SWarner Losh     pVM->state = COMPILE;
4062ca987d46SWarner Losh     pFW = dictAppendWord2(dp, si, colonParen, FW_DEFAULT | FW_SMUDGE);
4063ca987d46SWarner Losh     PUSHPTR(pFW);
4064ca987d46SWarner Losh     markControlTag(pVM, colonTag);
4065ca987d46SWarner Losh     return;
4066ca987d46SWarner Losh }
4067ca987d46SWarner Losh 
4068ca987d46SWarner Losh 
4069ca987d46SWarner Losh /**************************************************************************
4070ca987d46SWarner Losh                         u s e r   V a r i a b l e
4071ca987d46SWarner Losh ** user  ( u -- )  "<spaces>name"
4072ca987d46SWarner Losh ** Get a name from the input stream and create a user variable
4073ca987d46SWarner Losh ** with the name and the index supplied. The run-time effect
4074ca987d46SWarner Losh ** of a user variable is to push the address of the indexed cell
4075ca987d46SWarner Losh ** in the running vm's user array.
4076ca987d46SWarner Losh **
4077ca987d46SWarner Losh ** User variables are vm local cells. Each vm has an array of
4078ca987d46SWarner Losh ** FICL_USER_CELLS of them when FICL_WANT_USER is nonzero.
4079ca987d46SWarner Losh ** Ficl's user facility is implemented with two primitives,
4080ca987d46SWarner Losh ** "user" and "(user)", a variable ("nUser") (in softcore.c) that
4081ca987d46SWarner Losh ** holds the index of the next free user cell, and a redefinition
4082ca987d46SWarner Losh ** (also in softcore) of "user" that defines a user word and increments
4083ca987d46SWarner Losh ** nUser.
4084ca987d46SWarner Losh **************************************************************************/
4085ca987d46SWarner Losh #if FICL_WANT_USER
userParen(FICL_VM * pVM)4086ca987d46SWarner Losh static void userParen(FICL_VM *pVM)
4087ca987d46SWarner Losh {
4088ca987d46SWarner Losh     FICL_INT i = pVM->runningWord->param[0].i;
4089ca987d46SWarner Losh     PUSHPTR(&pVM->user[i]);
4090ca987d46SWarner Losh     return;
4091ca987d46SWarner Losh }
4092ca987d46SWarner Losh 
4093ca987d46SWarner Losh 
userVariable(FICL_VM * pVM)4094ca987d46SWarner Losh static void userVariable(FICL_VM *pVM)
4095ca987d46SWarner Losh {
4096ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
4097ca987d46SWarner Losh     STRINGINFO si = vmGetWord(pVM);
4098ca987d46SWarner Losh     CELL c;
4099ca987d46SWarner Losh 
4100ca987d46SWarner Losh     c = stackPop(pVM->pStack);
4101ca987d46SWarner Losh     if (c.i >= FICL_USER_CELLS)
4102ca987d46SWarner Losh     {
4103ca987d46SWarner Losh         vmThrowErr(pVM, "Error - out of user space");
4104ca987d46SWarner Losh     }
4105ca987d46SWarner Losh 
4106ca987d46SWarner Losh     dictAppendWord2(dp, si, userParen, FW_DEFAULT);
4107ca987d46SWarner Losh     dictAppendCell(dp, c);
4108ca987d46SWarner Losh     return;
4109ca987d46SWarner Losh }
4110ca987d46SWarner Losh #endif
4111ca987d46SWarner Losh 
4112ca987d46SWarner Losh 
4113ca987d46SWarner Losh /**************************************************************************
4114ca987d46SWarner Losh                         t o V a l u e
4115ca987d46SWarner Losh ** CORE EXT
4116ca987d46SWarner Losh ** Interpretation: ( x "<spaces>name" -- )
4117ca987d46SWarner Losh ** Skip leading spaces and parse name delimited by a space. Store x in
4118ca987d46SWarner Losh ** name. An ambiguous condition exists if name was not defined by VALUE.
4119ca987d46SWarner Losh ** NOTE: In ficl, VALUE is an alias of CONSTANT
4120ca987d46SWarner Losh **************************************************************************/
toValue(FICL_VM * pVM)4121ca987d46SWarner Losh static void toValue(FICL_VM *pVM)
4122ca987d46SWarner Losh {
4123ca987d46SWarner Losh     STRINGINFO si = vmGetWord(pVM);
4124ca987d46SWarner Losh     FICL_DICT *dp = vmGetDict(pVM);
4125ca987d46SWarner Losh     FICL_WORD *pFW;
4126ca987d46SWarner Losh 
4127ca987d46SWarner Losh #if FICL_WANT_LOCALS
4128ca987d46SWarner Losh     if ((pVM->pSys->nLocals > 0) && (pVM->state == COMPILE))
4129ca987d46SWarner Losh     {
4130ca987d46SWarner Losh         FICL_DICT *pLoc = ficlGetLoc(pVM->pSys);
4131ca987d46SWarner Losh         pFW = dictLookup(pLoc, si);
4132ca987d46SWarner Losh         if (pFW && (pFW->code == doLocalIm))
4133ca987d46SWarner Losh         {
4134ca987d46SWarner Losh             dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pToLocalParen));
4135ca987d46SWarner Losh             dictAppendCell(dp, LVALUEtoCELL(pFW->param[0]));
4136ca987d46SWarner Losh             return;
4137ca987d46SWarner Losh         }
4138ca987d46SWarner Losh         else if (pFW && pFW->code == do2LocalIm)
4139ca987d46SWarner Losh         {
4140ca987d46SWarner Losh             dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pTo2LocalParen));
4141ca987d46SWarner Losh             dictAppendCell(dp, LVALUEtoCELL(pFW->param[0]));
4142ca987d46SWarner Losh             return;
4143ca987d46SWarner Losh         }
4144ca987d46SWarner Losh     }
4145ca987d46SWarner Losh #endif
4146ca987d46SWarner Losh 
4147ca987d46SWarner Losh     assert(pVM->pSys->pStore);
4148ca987d46SWarner Losh 
4149ca987d46SWarner Losh     pFW = dictLookup(dp, si);
4150ca987d46SWarner Losh     if (!pFW)
4151ca987d46SWarner Losh     {
4152ca987d46SWarner Losh         int i = SI_COUNT(si);
4153ca987d46SWarner Losh         vmThrowErr(pVM, "%.*s not found", i, SI_PTR(si));
4154ca987d46SWarner Losh     }
4155ca987d46SWarner Losh 
4156ca987d46SWarner Losh     if (pVM->state == INTERPRET)
4157ca987d46SWarner Losh         pFW->param[0] = stackPop(pVM->pStack);
4158ca987d46SWarner Losh     else        /* compile code to store to word's param */
4159ca987d46SWarner Losh     {
4160ca987d46SWarner Losh         PUSHPTR(&pFW->param[0]);
4161ca987d46SWarner Losh         literalIm(pVM);
4162ca987d46SWarner Losh         dictAppendCell(dp, LVALUEtoCELL(pVM->pSys->pStore));
4163ca987d46SWarner Losh     }
4164ca987d46SWarner Losh     return;
4165ca987d46SWarner Losh }
4166ca987d46SWarner Losh 
4167ca987d46SWarner Losh 
4168ca987d46SWarner Losh #if FICL_WANT_LOCALS
4169ca987d46SWarner Losh /**************************************************************************
4170ca987d46SWarner Losh                         l i n k P a r e n
4171ca987d46SWarner Losh ** ( -- )
4172ca987d46SWarner Losh ** Link a frame on the return stack, reserving nCells of space for
4173ca987d46SWarner Losh ** locals - the value of nCells is the next cell in the instruction
4174ca987d46SWarner Losh ** stream.
4175ca987d46SWarner Losh **************************************************************************/
linkParen(FICL_VM * pVM)4176ca987d46SWarner Losh static void linkParen(FICL_VM *pVM)
4177ca987d46SWarner Losh {
4178ca987d46SWarner Losh     FICL_INT nLink = *(FICL_INT *)(pVM->ip);
4179ca987d46SWarner Losh     vmBranchRelative(pVM, 1);
4180ca987d46SWarner Losh     stackLink(pVM->rStack, nLink);
4181ca987d46SWarner Losh     return;
4182ca987d46SWarner Losh }
4183ca987d46SWarner Losh 
4184ca987d46SWarner Losh 
unlinkParen(FICL_VM * pVM)4185ca987d46SWarner Losh static void unlinkParen(FICL_VM *pVM)
4186ca987d46SWarner Losh {
4187ca987d46SWarner Losh     stackUnlink(pVM->rStack);
4188ca987d46SWarner Losh     return;
4189ca987d46SWarner Losh }
4190ca987d46SWarner Losh 
4191ca987d46SWarner Losh 
4192ca987d46SWarner Losh /**************************************************************************
4193ca987d46SWarner Losh                         d o L o c a l I m
4194ca987d46SWarner Losh ** Immediate - cfa of a local while compiling - when executed, compiles
4195ca987d46SWarner Losh ** code to fetch the value of a local given the local's index in the
4196ca987d46SWarner Losh ** word's pfa
4197ca987d46SWarner Losh **************************************************************************/
getLocalParen(FICL_VM * pVM)4198ca987d46SWarner Losh static void getLocalParen(FICL_VM *pVM)
4199ca987d46SWarner Losh {
4200ca987d46SWarner Losh     FICL_INT nLocal = *(FICL_INT *)(pVM->ip++);
4201ca987d46SWarner Losh     stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]);
4202ca987d46SWarner Losh     return;
4203ca987d46SWarner Losh }
4204ca987d46SWarner Losh 
4205ca987d46SWarner Losh 
toLocalParen(FICL_VM * pVM)4206ca987d46SWarner Losh static void toLocalParen(FICL_VM *pVM)
4207ca987d46SWarner Losh {
4208ca987d46SWarner Losh     FICL_INT nLocal = *(FICL_INT *)(pVM->ip++);
4209ca987d46SWarner Losh     pVM->rStack->pFrame[nLocal] = stackPop(pVM->pStack);
4210ca987d46SWarner Losh     return;
4211ca987d46SWarner Losh }
4212ca987d46SWarner Losh 
4213ca987d46SWarner Losh 
getLocal0(FICL_VM * pVM)4214ca987d46SWarner Losh static void getLocal0(FICL_VM *pVM)
4215ca987d46SWarner Losh {
4216ca987d46SWarner Losh     stackPush(pVM->pStack, pVM->rStack->pFrame[0]);
4217ca987d46SWarner Losh     return;
4218ca987d46SWarner Losh }
4219ca987d46SWarner Losh 
4220ca987d46SWarner Losh 
toLocal0(FICL_VM * pVM)4221ca987d46SWarner Losh static void toLocal0(FICL_VM *pVM)
4222ca987d46SWarner Losh {
4223ca987d46SWarner Losh     pVM->rStack->pFrame[0] = stackPop(pVM->pStack);
4224ca987d46SWarner Losh     return;
4225ca987d46SWarner Losh }
4226ca987d46SWarner Losh 
4227ca987d46SWarner Losh 
getLocal1(FICL_VM * pVM)4228ca987d46SWarner Losh static void getLocal1(FICL_VM *pVM)
4229ca987d46SWarner Losh {
4230ca987d46SWarner Losh     stackPush(pVM->pStack, pVM->rStack->pFrame[1]);
4231ca987d46SWarner Losh     return;
4232ca987d46SWarner Losh }
4233ca987d46SWarner Losh 
4234ca987d46SWarner Losh 
toLocal1(FICL_VM * pVM)4235ca987d46SWarner Losh static void toLocal1(FICL_VM *pVM)
4236ca987d46SWarner Losh {
4237ca987d46SWarner Losh     pVM->rStack->pFrame[1] = stackPop(pVM->pStack);
4238ca987d46SWarner Losh     return;
4239ca987d46SWarner Losh }
4240ca987d46SWarner Losh 
4241ca987d46SWarner Losh 
4242ca987d46SWarner Losh /*
4243ca987d46SWarner Losh ** Each local is recorded in a private locals dictionary as a
4244ca987d46SWarner Losh ** word that does doLocalIm at runtime. DoLocalIm compiles code
4245ca987d46SWarner Losh ** into the client definition to fetch the value of the
4246ca987d46SWarner Losh ** corresponding local variable from the return stack.
4247ca987d46SWarner Losh ** The private dictionary gets initialized at the end of each block
4248ca987d46SWarner Losh ** that uses locals (in ; and does> for example).
4249ca987d46SWarner Losh */
doLocalIm(FICL_VM * pVM)4250ca987d46SWarner Losh static void doLocalIm(FICL_VM *pVM)
4251ca987d46SWarner Losh {
4252ca987d46SWarner Losh     FICL_DICT *pDict = vmGetDict(pVM);
4253ca987d46SWarner Losh     FICL_INT nLocal = pVM->runningWord->param[0].i;
4254ca987d46SWarner Losh 
4255ca987d46SWarner Losh     if (pVM->state == INTERPRET)
4256ca987d46SWarner Losh     {
4257ca987d46SWarner Losh         stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]);
4258ca987d46SWarner Losh     }
4259ca987d46SWarner Losh     else
4260ca987d46SWarner Losh     {
4261ca987d46SWarner Losh 
4262ca987d46SWarner Losh         if (nLocal == 0)
4263ca987d46SWarner Losh         {
4264ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGetLocal0));
4265ca987d46SWarner Losh         }
4266ca987d46SWarner Losh         else if (nLocal == 1)
4267ca987d46SWarner Losh         {
4268ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGetLocal1));
4269ca987d46SWarner Losh         }
4270ca987d46SWarner Losh         else
4271ca987d46SWarner Losh         {
4272ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGetLocalParen));
4273ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(nLocal));
4274ca987d46SWarner Losh         }
4275ca987d46SWarner Losh     }
4276ca987d46SWarner Losh     return;
4277ca987d46SWarner Losh }
4278ca987d46SWarner Losh 
4279ca987d46SWarner Losh 
4280ca987d46SWarner Losh /**************************************************************************
4281ca987d46SWarner Losh                         l o c a l P a r e n
4282ca987d46SWarner Losh ** paren-local-paren LOCAL
4283ca987d46SWarner Losh ** Interpretation: Interpretation semantics for this word are undefined.
4284ca987d46SWarner Losh ** Execution: ( c-addr u -- )
4285ca987d46SWarner Losh ** When executed during compilation, (LOCAL) passes a message to the
4286ca987d46SWarner Losh ** system that has one of two meanings. If u is non-zero,
4287ca987d46SWarner Losh ** the message identifies a new local whose definition name is given by
4288ca987d46SWarner Losh ** the string of characters identified by c-addr u. If u is zero,
4289ca987d46SWarner Losh ** the message is last local and c-addr has no significance.
4290ca987d46SWarner Losh **
4291ca987d46SWarner Losh ** The result of executing (LOCAL) during compilation of a definition is
4292ca987d46SWarner Losh ** to create a set of named local identifiers, each of which is
4293ca987d46SWarner Losh ** a definition name, that only have execution semantics within the scope
4294ca987d46SWarner Losh ** of that definition's source.
4295ca987d46SWarner Losh **
4296ca987d46SWarner Losh ** local Execution: ( -- x )
4297ca987d46SWarner Losh **
4298ca987d46SWarner Losh ** Push the local's value, x, onto the stack. The local's value is
4299ca987d46SWarner Losh ** initialized as described in 13.3.3 Processing locals and may be
4300ca987d46SWarner Losh ** changed by preceding the local's name with TO. An ambiguous condition
4301ca987d46SWarner Losh ** exists when local is executed while in interpretation state.
4302ca987d46SWarner Losh **************************************************************************/
localParen(FICL_VM * pVM)4303ca987d46SWarner Losh static void localParen(FICL_VM *pVM)
4304ca987d46SWarner Losh {
4305ca987d46SWarner Losh     FICL_DICT *pDict;
4306ca987d46SWarner Losh     STRINGINFO si;
4307ca987d46SWarner Losh #if FICL_ROBUST > 1
4308ca987d46SWarner Losh     vmCheckStack(pVM,2,0);
4309ca987d46SWarner Losh #endif
4310ca987d46SWarner Losh 
4311ca987d46SWarner Losh     pDict = vmGetDict(pVM);
4312ca987d46SWarner Losh     SI_SETLEN(si, POPUNS());
4313ca987d46SWarner Losh     SI_SETPTR(si, (char *)POPPTR());
4314ca987d46SWarner Losh 
4315ca987d46SWarner Losh     if (SI_COUNT(si) > 0)
4316ca987d46SWarner Losh     {   /* add a local to the **locals** dict and update nLocals */
4317ca987d46SWarner Losh         FICL_DICT *pLoc = ficlGetLoc(pVM->pSys);
4318ca987d46SWarner Losh         if (pVM->pSys->nLocals >= FICL_MAX_LOCALS)
4319ca987d46SWarner Losh         {
4320ca987d46SWarner Losh             vmThrowErr(pVM, "Error: out of local space");
4321ca987d46SWarner Losh         }
4322ca987d46SWarner Losh 
4323ca987d46SWarner Losh         dictAppendWord2(pLoc, si, doLocalIm, FW_COMPIMMED);
4324ca987d46SWarner Losh         dictAppendCell(pLoc,  LVALUEtoCELL(pVM->pSys->nLocals));
4325ca987d46SWarner Losh 
4326ca987d46SWarner Losh         if (pVM->pSys->nLocals == 0)
4327ca987d46SWarner Losh         {   /* compile code to create a local stack frame */
4328ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pLinkParen));
4329ca987d46SWarner Losh             /* save location in dictionary for #locals */
4330ca987d46SWarner Losh             pVM->pSys->pMarkLocals = pDict->here;
4331ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals));
4332ca987d46SWarner Losh             /* compile code to initialize first local */
4333ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pToLocal0));
4334ca987d46SWarner Losh         }
4335ca987d46SWarner Losh         else if (pVM->pSys->nLocals == 1)
4336ca987d46SWarner Losh         {
4337ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pToLocal1));
4338ca987d46SWarner Losh         }
4339ca987d46SWarner Losh         else
4340ca987d46SWarner Losh         {
4341ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pToLocalParen));
4342ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals));
4343ca987d46SWarner Losh         }
4344ca987d46SWarner Losh 
4345ca987d46SWarner Losh         (pVM->pSys->nLocals)++;
4346ca987d46SWarner Losh     }
4347ca987d46SWarner Losh     else if (pVM->pSys->nLocals > 0)
4348ca987d46SWarner Losh     {       /* write nLocals to (link) param area in dictionary */
4349ca987d46SWarner Losh         *(FICL_INT *)(pVM->pSys->pMarkLocals) = pVM->pSys->nLocals;
4350ca987d46SWarner Losh     }
4351ca987d46SWarner Losh 
4352ca987d46SWarner Losh     return;
4353ca987d46SWarner Losh }
4354ca987d46SWarner Losh 
4355ca987d46SWarner Losh 
get2LocalParen(FICL_VM * pVM)4356ca987d46SWarner Losh static void get2LocalParen(FICL_VM *pVM)
4357ca987d46SWarner Losh {
4358ca987d46SWarner Losh     FICL_INT nLocal = *(FICL_INT *)(pVM->ip++);
4359ca987d46SWarner Losh     stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]);
4360ca987d46SWarner Losh     stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal+1]);
4361ca987d46SWarner Losh     return;
4362ca987d46SWarner Losh }
4363ca987d46SWarner Losh 
4364ca987d46SWarner Losh 
do2LocalIm(FICL_VM * pVM)4365ca987d46SWarner Losh static void do2LocalIm(FICL_VM *pVM)
4366ca987d46SWarner Losh {
4367ca987d46SWarner Losh     FICL_DICT *pDict = vmGetDict(pVM);
4368ca987d46SWarner Losh     FICL_INT nLocal = pVM->runningWord->param[0].i;
4369ca987d46SWarner Losh 
4370ca987d46SWarner Losh     if (pVM->state == INTERPRET)
4371ca987d46SWarner Losh     {
4372ca987d46SWarner Losh         stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal]);
4373ca987d46SWarner Losh         stackPush(pVM->pStack, pVM->rStack->pFrame[nLocal+1]);
4374ca987d46SWarner Losh     }
4375ca987d46SWarner Losh     else
4376ca987d46SWarner Losh     {
4377ca987d46SWarner Losh         dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pGet2LocalParen));
4378ca987d46SWarner Losh         dictAppendCell(pDict, LVALUEtoCELL(nLocal));
4379ca987d46SWarner Losh     }
4380ca987d46SWarner Losh     return;
4381ca987d46SWarner Losh }
4382ca987d46SWarner Losh 
4383ca987d46SWarner Losh 
to2LocalParen(FICL_VM * pVM)4384ca987d46SWarner Losh static void to2LocalParen(FICL_VM *pVM)
4385ca987d46SWarner Losh {
4386ca987d46SWarner Losh     FICL_INT nLocal = *(FICL_INT *)(pVM->ip++);
4387ca987d46SWarner Losh     pVM->rStack->pFrame[nLocal+1] = stackPop(pVM->pStack);
4388ca987d46SWarner Losh     pVM->rStack->pFrame[nLocal]   = stackPop(pVM->pStack);
4389ca987d46SWarner Losh     return;
4390ca987d46SWarner Losh }
4391ca987d46SWarner Losh 
4392ca987d46SWarner Losh 
twoLocalParen(FICL_VM * pVM)4393ca987d46SWarner Losh static void twoLocalParen(FICL_VM *pVM)
4394ca987d46SWarner Losh {
4395ca987d46SWarner Losh     FICL_DICT *pDict = vmGetDict(pVM);
4396ca987d46SWarner Losh     STRINGINFO si;
4397ca987d46SWarner Losh     SI_SETLEN(si, stackPopUNS(pVM->pStack));
4398ca987d46SWarner Losh     SI_SETPTR(si, (char *)stackPopPtr(pVM->pStack));
4399ca987d46SWarner Losh 
4400ca987d46SWarner Losh     if (SI_COUNT(si) > 0)
4401ca987d46SWarner Losh     {   /* add a local to the **locals** dict and update nLocals */
4402ca987d46SWarner Losh         FICL_DICT *pLoc = ficlGetLoc(pVM->pSys);
4403ca987d46SWarner Losh         if (pVM->pSys->nLocals >= FICL_MAX_LOCALS)
4404ca987d46SWarner Losh         {
4405ca987d46SWarner Losh             vmThrowErr(pVM, "Error: out of local space");
4406ca987d46SWarner Losh         }
4407ca987d46SWarner Losh 
4408ca987d46SWarner Losh         dictAppendWord2(pLoc, si, do2LocalIm, FW_COMPIMMED);
4409ca987d46SWarner Losh         dictAppendCell(pLoc,  LVALUEtoCELL(pVM->pSys->nLocals));
4410ca987d46SWarner Losh 
4411ca987d46SWarner Losh         if (pVM->pSys->nLocals == 0)
4412ca987d46SWarner Losh         {   /* compile code to create a local stack frame */
4413ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pLinkParen));
4414ca987d46SWarner Losh             /* save location in dictionary for #locals */
4415ca987d46SWarner Losh             pVM->pSys->pMarkLocals = pDict->here;
4416ca987d46SWarner Losh             dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals));
4417ca987d46SWarner Losh         }
4418ca987d46SWarner Losh 
4419ca987d46SWarner Losh         dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->pTo2LocalParen));
4420ca987d46SWarner Losh         dictAppendCell(pDict, LVALUEtoCELL(pVM->pSys->nLocals));
4421ca987d46SWarner Losh 
4422ca987d46SWarner Losh         pVM->pSys->nLocals += 2;
4423ca987d46SWarner Losh     }
4424ca987d46SWarner Losh     else if (pVM->pSys->nLocals > 0)
4425ca987d46SWarner Losh     {       /* write nLocals to (link) param area in dictionary */
4426ca987d46SWarner Losh         *(FICL_INT *)(pVM->pSys->pMarkLocals) = pVM->pSys->nLocals;
4427ca987d46SWarner Losh     }
4428ca987d46SWarner Losh 
4429ca987d46SWarner Losh     return;
4430ca987d46SWarner Losh }
4431ca987d46SWarner Losh 
4432ca987d46SWarner Losh 
4433ca987d46SWarner Losh #endif
4434ca987d46SWarner Losh /**************************************************************************
4435ca987d46SWarner Losh                         c o m p a r e
4436ca987d46SWarner Losh ** STRING ( c-addr1 u1 c-addr2 u2 -- n )
4437ca987d46SWarner Losh ** Compare the string specified by c-addr1 u1 to the string specified by
4438ca987d46SWarner Losh ** c-addr2 u2. The strings are compared, beginning at the given addresses,
4439ca987d46SWarner Losh ** character by character, up to the length of the shorter string or until a
4440ca987d46SWarner Losh ** difference is found. If the two strings are identical, n is zero. If the two
4441ca987d46SWarner Losh ** strings are identical up to the length of the shorter string, n is minus-one
4442ca987d46SWarner Losh ** (-1) if u1 is less than u2 and one (1) otherwise. If the two strings are not
4443ca987d46SWarner Losh ** identical up to the length of the shorter string, n is minus-one (-1) if the
4444ca987d46SWarner Losh ** first non-matching character in the string specified by c-addr1 u1 has a
4445ca987d46SWarner Losh ** lesser numeric value than the corresponding character in the string specified
4446ca987d46SWarner Losh ** by c-addr2 u2 and one (1) otherwise.
4447ca987d46SWarner Losh **************************************************************************/
compareInternal(FICL_VM * pVM,int caseInsensitive)4448ca987d46SWarner Losh static void compareInternal(FICL_VM *pVM, int caseInsensitive)
4449ca987d46SWarner Losh {
4450ca987d46SWarner Losh     char *cp1, *cp2;
4451ca987d46SWarner Losh     FICL_UNS u1, u2, uMin;
4452ca987d46SWarner Losh     int n = 0;
4453ca987d46SWarner Losh 
4454ca987d46SWarner Losh     vmCheckStack(pVM, 4, 1);
4455ca987d46SWarner Losh     u2  = stackPopUNS(pVM->pStack);
4456ca987d46SWarner Losh     cp2 = (char *)stackPopPtr(pVM->pStack);
4457ca987d46SWarner Losh     u1  = stackPopUNS(pVM->pStack);
4458ca987d46SWarner Losh     cp1 = (char *)stackPopPtr(pVM->pStack);
4459ca987d46SWarner Losh 
4460ca987d46SWarner Losh     uMin = (u1 < u2)? u1 : u2;
4461ca987d46SWarner Losh     for ( ; (uMin > 0) && (n == 0); uMin--)
4462ca987d46SWarner Losh     {
4463ca987d46SWarner Losh 		char c1 = *cp1++;
4464ca987d46SWarner Losh 		char c2 = *cp2++;
4465ca987d46SWarner Losh 		if (caseInsensitive)
4466ca987d46SWarner Losh 		{
4467ca987d46SWarner Losh 			c1 = (char)tolower(c1);
4468ca987d46SWarner Losh 			c2 = (char)tolower(c2);
4469ca987d46SWarner Losh 		}
4470ca987d46SWarner Losh         n = (int)(c1 - c2);
4471ca987d46SWarner Losh     }
4472ca987d46SWarner Losh 
4473ca987d46SWarner Losh     if (n == 0)
4474ca987d46SWarner Losh         n = (int)(u1 - u2);
4475ca987d46SWarner Losh 
4476ca987d46SWarner Losh     if (n < 0)
4477ca987d46SWarner Losh         n = -1;
4478ca987d46SWarner Losh     else if (n > 0)
4479ca987d46SWarner Losh         n = 1;
4480ca987d46SWarner Losh 
4481ca987d46SWarner Losh     PUSHINT(n);
4482ca987d46SWarner Losh     return;
4483ca987d46SWarner Losh }
4484ca987d46SWarner Losh 
4485ca987d46SWarner Losh 
compareString(FICL_VM * pVM)4486ca987d46SWarner Losh static void compareString(FICL_VM *pVM)
4487ca987d46SWarner Losh {
4488ca987d46SWarner Losh 	compareInternal(pVM, FALSE);
4489ca987d46SWarner Losh }
4490ca987d46SWarner Losh 
4491ca987d46SWarner Losh 
compareStringInsensitive(FICL_VM * pVM)4492ca987d46SWarner Losh static void compareStringInsensitive(FICL_VM *pVM)
4493ca987d46SWarner Losh {
4494ca987d46SWarner Losh 	compareInternal(pVM, TRUE);
4495ca987d46SWarner Losh }
4496ca987d46SWarner Losh 
4497ca987d46SWarner Losh 
4498ca987d46SWarner Losh /**************************************************************************
4499ca987d46SWarner Losh                         p a d
4500ca987d46SWarner Losh ** CORE EXT  ( -- c-addr )
4501ca987d46SWarner Losh ** c-addr is the address of a transient region that can be used to hold
4502ca987d46SWarner Losh ** data for intermediate processing.
4503ca987d46SWarner Losh **************************************************************************/
pad(FICL_VM * pVM)4504ca987d46SWarner Losh static void pad(FICL_VM *pVM)
4505ca987d46SWarner Losh {
4506ca987d46SWarner Losh     stackPushPtr(pVM->pStack, pVM->pad);
4507ca987d46SWarner Losh }
4508ca987d46SWarner Losh 
4509ca987d46SWarner Losh 
4510ca987d46SWarner Losh /**************************************************************************
4511ca987d46SWarner Losh                         s o u r c e - i d
4512ca987d46SWarner Losh ** CORE EXT, FILE   ( -- 0 | -1 | fileid )
4513ca987d46SWarner Losh **    Identifies the input source as follows:
4514ca987d46SWarner Losh **
4515ca987d46SWarner Losh ** SOURCE-ID       Input source
4516ca987d46SWarner Losh ** ---------       ------------
4517ca987d46SWarner Losh ** fileid          Text file fileid
4518ca987d46SWarner Losh ** -1              String (via EVALUATE)
4519ca987d46SWarner Losh ** 0               User input device
4520ca987d46SWarner Losh **************************************************************************/
sourceid(FICL_VM * pVM)4521ca987d46SWarner Losh static void sourceid(FICL_VM *pVM)
4522ca987d46SWarner Losh {
4523ca987d46SWarner Losh     PUSHINT(pVM->sourceID.i);
4524ca987d46SWarner Losh     return;
4525ca987d46SWarner Losh }
4526ca987d46SWarner Losh 
4527ca987d46SWarner Losh 
4528ca987d46SWarner Losh /**************************************************************************
4529ca987d46SWarner Losh                         r e f i l l
4530ca987d46SWarner Losh ** CORE EXT   ( -- flag )
4531ca987d46SWarner Losh ** Attempt to fill the input buffer from the input source, returning a true
4532ca987d46SWarner Losh ** flag if successful.
4533ca987d46SWarner Losh ** When the input source is the user input device, attempt to receive input
4534ca987d46SWarner Losh ** into the terminal input buffer. If successful, make the result the input
4535ca987d46SWarner Losh ** buffer, set >IN to zero, and return true. Receipt of a line containing no
4536ca987d46SWarner Losh ** characters is considered successful. If there is no input available from
4537ca987d46SWarner Losh ** the current input source, return false.
4538ca987d46SWarner Losh ** When the input source is a string from EVALUATE, return false and
4539ca987d46SWarner Losh ** perform no other action.
4540ca987d46SWarner Losh **************************************************************************/
refill(FICL_VM * pVM)4541ca987d46SWarner Losh static void refill(FICL_VM *pVM)
4542ca987d46SWarner Losh {
4543ca987d46SWarner Losh     FICL_INT ret = (pVM->sourceID.i == -1) ? FICL_FALSE : FICL_TRUE;
4544ca987d46SWarner Losh     if (ret && (pVM->fRestart == 0))
4545ca987d46SWarner Losh         vmThrow(pVM, VM_RESTART);
4546ca987d46SWarner Losh 
4547ca987d46SWarner Losh     PUSHINT(ret);
4548ca987d46SWarner Losh     return;
4549ca987d46SWarner Losh }
4550ca987d46SWarner Losh 
4551ca987d46SWarner Losh 
4552ca987d46SWarner Losh /**************************************************************************
4553ca987d46SWarner Losh                         freebsd exception handling words
4554ca987d46SWarner Losh ** Catch, from ANS Forth standard. Installs a safety net, then EXECUTE
4555ca987d46SWarner Losh ** the word in ToS. If an exception happens, restore the state to what
4556ca987d46SWarner Losh ** it was before, and pushes the exception value on the stack. If not,
4557ca987d46SWarner Losh ** push zero.
4558ca987d46SWarner Losh **
4559ca987d46SWarner Losh ** Notice that Catch implements an inner interpreter. This is ugly,
4560ca987d46SWarner Losh ** but given how ficl works, it cannot be helped. The problem is that
4561ca987d46SWarner Losh ** colon definitions will be executed *after* the function returns,
4562ca987d46SWarner Losh ** while "code" definitions will be executed immediately. I considered
4563ca987d46SWarner Losh ** other solutions to this problem, but all of them shared the same
4564ca987d46SWarner Losh ** basic problem (with added disadvantages): if ficl ever changes it's
4565ca987d46SWarner Losh ** inner thread modus operandi, one would have to fix this word.
4566ca987d46SWarner Losh **
4567ca987d46SWarner Losh ** More comments can be found throughout catch's code.
4568ca987d46SWarner Losh **
4569ca987d46SWarner Losh ** Daniel C. Sobral Jan 09/1999
4570ca987d46SWarner Losh ** sadler may 2000 -- revised to follow ficl.c:ficlExecXT.
4571ca987d46SWarner Losh **************************************************************************/
4572ca987d46SWarner Losh 
ficlCatch(FICL_VM * pVM)4573ca987d46SWarner Losh static void ficlCatch(FICL_VM *pVM)
4574ca987d46SWarner Losh {
4575ca987d46SWarner Losh     int         except;
4576ca987d46SWarner Losh     jmp_buf     vmState;
4577ca987d46SWarner Losh     FICL_VM     VM;
4578ca987d46SWarner Losh     FICL_STACK  pStack;
4579ca987d46SWarner Losh     FICL_STACK  rStack;
4580ca987d46SWarner Losh     FICL_WORD   *pFW;
4581ca987d46SWarner Losh 
4582ca987d46SWarner Losh     assert(pVM);
4583ca987d46SWarner Losh     assert(pVM->pSys->pExitInner);
4584ca987d46SWarner Losh 
4585ca987d46SWarner Losh 
4586ca987d46SWarner Losh     /*
4587ca987d46SWarner Losh     ** Get xt.
4588ca987d46SWarner Losh     ** We need this *before* we save the stack pointer, or
4589ca987d46SWarner Losh     ** we'll have to pop one element out of the stack after
4590ca987d46SWarner Losh     ** an exception. I prefer to get done with it up front. :-)
4591ca987d46SWarner Losh     */
4592ca987d46SWarner Losh #if FICL_ROBUST > 1
4593ca987d46SWarner Losh     vmCheckStack(pVM, 1, 0);
4594ca987d46SWarner Losh #endif
4595ca987d46SWarner Losh     pFW = stackPopPtr(pVM->pStack);
4596ca987d46SWarner Losh 
4597ca987d46SWarner Losh     /*
4598ca987d46SWarner Losh     ** Save vm's state -- a catch will not back out environmental
4599ca987d46SWarner Losh     ** changes.
4600ca987d46SWarner Losh     **
4601ca987d46SWarner Losh     ** We are *not* saving dictionary state, since it is
4602ca987d46SWarner Losh     ** global instead of per vm, and we are not saving
4603ca987d46SWarner Losh     ** stack contents, since we are not required to (and,
4604ca987d46SWarner Losh     ** thus, it would be useless). We save pVM, and pVM
4605ca987d46SWarner Losh     ** "stacks" (a structure containing general information
4606ca987d46SWarner Losh     ** about it, including the current stack pointer).
4607ca987d46SWarner Losh     */
4608ca987d46SWarner Losh     memcpy((void*)&VM, (void*)pVM, sizeof(FICL_VM));
4609ca987d46SWarner Losh     memcpy((void*)&pStack, (void*)pVM->pStack, sizeof(FICL_STACK));
4610ca987d46SWarner Losh     memcpy((void*)&rStack, (void*)pVM->rStack, sizeof(FICL_STACK));
4611ca987d46SWarner Losh 
4612ca987d46SWarner Losh     /*
4613ca987d46SWarner Losh     ** Give pVM a jmp_buf
4614ca987d46SWarner Losh     */
4615ca987d46SWarner Losh     pVM->pState = &vmState;
4616ca987d46SWarner Losh 
4617ca987d46SWarner Losh     /*
4618ca987d46SWarner Losh     ** Safety net
4619ca987d46SWarner Losh     */
4620ca987d46SWarner Losh     except = setjmp(vmState);
4621ca987d46SWarner Losh 
4622ca987d46SWarner Losh     switch (except)
4623ca987d46SWarner Losh     {
4624ca987d46SWarner Losh         /*
4625ca987d46SWarner Losh         ** Setup condition - push poison pill so that the VM throws
4626ca987d46SWarner Losh         ** VM_INNEREXIT if the XT terminates normally, then execute
4627ca987d46SWarner Losh         ** the XT
4628ca987d46SWarner Losh         */
4629ca987d46SWarner Losh     case 0:
4630ca987d46SWarner Losh         vmPushIP(pVM, &(pVM->pSys->pExitInner));          /* Open mouth, insert emetic */
4631ca987d46SWarner Losh         vmExecute(pVM, pFW);
4632ca987d46SWarner Losh         vmInnerLoop(pVM);
4633ca987d46SWarner Losh         break;
4634ca987d46SWarner Losh 
4635ca987d46SWarner Losh         /*
4636ca987d46SWarner Losh         ** Normal exit from XT - lose the poison pill,
4637ca987d46SWarner Losh         ** restore old setjmp vector and push a zero.
4638ca987d46SWarner Losh         */
4639ca987d46SWarner Losh     case VM_INNEREXIT:
4640ca987d46SWarner Losh         vmPopIP(pVM);                   /* Gack - hurl poison pill */
4641ca987d46SWarner Losh         pVM->pState = VM.pState;        /* Restore just the setjmp vector */
4642ca987d46SWarner Losh         PUSHINT(0);   /* Push 0 -- everything is ok */
4643ca987d46SWarner Losh         break;
4644ca987d46SWarner Losh 
4645ca987d46SWarner Losh         /*
4646ca987d46SWarner Losh         ** Some other exception got thrown - restore pre-existing VM state
4647ca987d46SWarner Losh         ** and push the exception code
4648ca987d46SWarner Losh         */
4649ca987d46SWarner Losh     default:
4650ca987d46SWarner Losh         /* Restore vm's state */
4651ca987d46SWarner Losh         memcpy((void*)pVM, (void*)&VM, sizeof(FICL_VM));
4652ca987d46SWarner Losh         memcpy((void*)pVM->pStack, (void*)&pStack, sizeof(FICL_STACK));
4653ca987d46SWarner Losh         memcpy((void*)pVM->rStack, (void*)&rStack, sizeof(FICL_STACK));
4654ca987d46SWarner Losh 
4655ca987d46SWarner Losh         PUSHINT(except);/* Push error */
4656ca987d46SWarner Losh         break;
4657ca987d46SWarner Losh     }
4658ca987d46SWarner Losh }
4659ca987d46SWarner Losh 
4660ca987d46SWarner Losh /**************************************************************************
4661ca987d46SWarner Losh **                     t h r o w
4662ca987d46SWarner Losh ** EXCEPTION
4663ca987d46SWarner Losh ** Throw --  From ANS Forth standard.
4664ca987d46SWarner Losh **
4665ca987d46SWarner Losh ** Throw takes the ToS and, if that's different from zero,
4666ca987d46SWarner Losh ** returns to the last executed catch context. Further throws will
4667ca987d46SWarner Losh ** unstack previously executed "catches", in LIFO mode.
4668ca987d46SWarner Losh **
4669ca987d46SWarner Losh ** Daniel C. Sobral Jan 09/1999
4670ca987d46SWarner Losh **************************************************************************/
ficlThrow(FICL_VM * pVM)4671ca987d46SWarner Losh static void ficlThrow(FICL_VM *pVM)
4672ca987d46SWarner Losh {
4673ca987d46SWarner Losh     int except;
4674ca987d46SWarner Losh 
4675ca987d46SWarner Losh     except = stackPopINT(pVM->pStack);
4676ca987d46SWarner Losh 
4677ca987d46SWarner Losh     if (except)
4678ca987d46SWarner Losh         vmThrow(pVM, except);
4679ca987d46SWarner Losh }
4680ca987d46SWarner Losh 
4681ca987d46SWarner Losh 
4682ca987d46SWarner Losh /**************************************************************************
4683ca987d46SWarner Losh **                     a l l o c a t e
4684ca987d46SWarner Losh ** MEMORY
4685ca987d46SWarner Losh **************************************************************************/
ansAllocate(FICL_VM * pVM)4686ca987d46SWarner Losh static void ansAllocate(FICL_VM *pVM)
4687ca987d46SWarner Losh {
4688ca987d46SWarner Losh     size_t size;
4689ca987d46SWarner Losh     void *p;
4690ca987d46SWarner Losh 
4691ca987d46SWarner Losh     size = stackPopINT(pVM->pStack);
4692ca987d46SWarner Losh     p = ficlMalloc(size);
4693ca987d46SWarner Losh     PUSHPTR(p);
4694ca987d46SWarner Losh     if (p)
4695ca987d46SWarner Losh         PUSHINT(0);
4696ca987d46SWarner Losh     else
4697ca987d46SWarner Losh         PUSHINT(1);
4698ca987d46SWarner Losh }
4699ca987d46SWarner Losh 
4700ca987d46SWarner Losh 
4701ca987d46SWarner Losh /**************************************************************************
4702ca987d46SWarner Losh **                     f r e e
4703ca987d46SWarner Losh ** MEMORY
4704ca987d46SWarner Losh **************************************************************************/
ansFree(FICL_VM * pVM)4705ca987d46SWarner Losh static void ansFree(FICL_VM *pVM)
4706ca987d46SWarner Losh {
4707ca987d46SWarner Losh     void *p;
4708ca987d46SWarner Losh 
4709ca987d46SWarner Losh     p = stackPopPtr(pVM->pStack);
4710ca987d46SWarner Losh     ficlFree(p);
4711ca987d46SWarner Losh     PUSHINT(0);
4712ca987d46SWarner Losh }
4713ca987d46SWarner Losh 
4714ca987d46SWarner Losh 
4715ca987d46SWarner Losh /**************************************************************************
4716ca987d46SWarner Losh **                     r e s i z e
4717ca987d46SWarner Losh ** MEMORY
4718ca987d46SWarner Losh **************************************************************************/
ansResize(FICL_VM * pVM)4719ca987d46SWarner Losh static void ansResize(FICL_VM *pVM)
4720ca987d46SWarner Losh {
4721ca987d46SWarner Losh     size_t size;
4722ca987d46SWarner Losh     void *new, *old;
4723ca987d46SWarner Losh 
4724ca987d46SWarner Losh     size = stackPopINT(pVM->pStack);
4725ca987d46SWarner Losh     old = stackPopPtr(pVM->pStack);
4726ca987d46SWarner Losh     new = ficlRealloc(old, size);
4727ca987d46SWarner Losh     if (new)
4728ca987d46SWarner Losh     {
4729ca987d46SWarner Losh         PUSHPTR(new);
4730ca987d46SWarner Losh         PUSHINT(0);
4731ca987d46SWarner Losh     }
4732ca987d46SWarner Losh     else
4733ca987d46SWarner Losh     {
4734ca987d46SWarner Losh         PUSHPTR(old);
4735ca987d46SWarner Losh         PUSHINT(1);
4736ca987d46SWarner Losh     }
4737ca987d46SWarner Losh }
4738ca987d46SWarner Losh 
4739ca987d46SWarner Losh 
4740ca987d46SWarner Losh /**************************************************************************
4741ca987d46SWarner Losh **                     e x i t - i n n e r
4742ca987d46SWarner Losh ** Signals execXT that an inner loop has completed
4743ca987d46SWarner Losh **************************************************************************/
ficlExitInner(FICL_VM * pVM)4744ca987d46SWarner Losh static void ficlExitInner(FICL_VM *pVM)
4745ca987d46SWarner Losh {
4746ca987d46SWarner Losh     vmThrow(pVM, VM_INNEREXIT);
4747ca987d46SWarner Losh }
4748ca987d46SWarner Losh 
4749ca987d46SWarner Losh 
4750ca987d46SWarner Losh /**************************************************************************
4751ca987d46SWarner Losh                         d n e g a t e
4752ca987d46SWarner Losh ** DOUBLE   ( d1 -- d2 )
4753ca987d46SWarner Losh ** d2 is the negation of d1.
4754ca987d46SWarner Losh **************************************************************************/
dnegate(FICL_VM * pVM)4755ca987d46SWarner Losh static void dnegate(FICL_VM *pVM)
4756ca987d46SWarner Losh {
4757ca987d46SWarner Losh     DPINT i = i64Pop(pVM->pStack);
4758ca987d46SWarner Losh     i = m64Negate(i);
4759ca987d46SWarner Losh     i64Push(pVM->pStack, i);
4760ca987d46SWarner Losh 
4761ca987d46SWarner Losh     return;
4762ca987d46SWarner Losh }
4763ca987d46SWarner Losh 
4764ca987d46SWarner Losh 
4765ca987d46SWarner Losh #if 0
4766ca987d46SWarner Losh /**************************************************************************
4767ca987d46SWarner Losh 
4768ca987d46SWarner Losh **
4769ca987d46SWarner Losh **************************************************************************/
4770ca987d46SWarner Losh static void funcname(FICL_VM *pVM)
4771ca987d46SWarner Losh {
4772ca987d46SWarner Losh     IGNORE(pVM);
4773ca987d46SWarner Losh     return;
4774ca987d46SWarner Losh }
4775ca987d46SWarner Losh 
4776ca987d46SWarner Losh 
4777ca987d46SWarner Losh #endif
4778ca987d46SWarner Losh /**************************************************************************
4779ca987d46SWarner Losh                         f i c l W o r d C l a s s i f y
4780ca987d46SWarner Losh ** This public function helps to classify word types for SEE
4781ca987d46SWarner Losh ** and the deugger in tools.c. Given a pointer to a word, it returns
4782ca987d46SWarner Losh ** a member of WOR
4783ca987d46SWarner Losh **************************************************************************/
ficlWordClassify(FICL_WORD * pFW)4784ca987d46SWarner Losh WORDKIND ficlWordClassify(FICL_WORD *pFW)
4785ca987d46SWarner Losh {
4786ca987d46SWarner Losh     typedef struct
4787ca987d46SWarner Losh     {
4788ca987d46SWarner Losh         WORDKIND kind;
4789ca987d46SWarner Losh         FICL_CODE code;
4790ca987d46SWarner Losh     } CODEtoKIND;
4791ca987d46SWarner Losh 
4792ca987d46SWarner Losh     static CODEtoKIND codeMap[] =
4793ca987d46SWarner Losh     {
4794ca987d46SWarner Losh         {BRANCH,     branchParen},
4795ca987d46SWarner Losh         {COLON,       colonParen},
4796ca987d46SWarner Losh         {CONSTANT, constantParen},
4797ca987d46SWarner Losh         {CREATE,     createParen},
4798ca987d46SWarner Losh         {DO,             doParen},
4799ca987d46SWarner Losh         {DOES,            doDoes},
4800ca987d46SWarner Losh         {IF,             branch0},
4801ca987d46SWarner Losh         {LITERAL,   literalParen},
4802ca987d46SWarner Losh         {LOOP,         loopParen},
4803ca987d46SWarner Losh         {OF,             ofParen},
4804ca987d46SWarner Losh         {PLOOP,    plusLoopParen},
4805ca987d46SWarner Losh         {QDO,           qDoParen},
4806ca987d46SWarner Losh         {CSTRINGLIT,  cstringLit},
4807ca987d46SWarner Losh         {STRINGLIT,    stringLit},
4808ca987d46SWarner Losh #if FICL_WANT_USER
4809ca987d46SWarner Losh         {USER,         userParen},
4810ca987d46SWarner Losh #endif
4811ca987d46SWarner Losh         {VARIABLE, variableParen},
4812ca987d46SWarner Losh     };
4813ca987d46SWarner Losh 
4814ca987d46SWarner Losh #define nMAP (sizeof(codeMap) / sizeof(CODEtoKIND))
4815ca987d46SWarner Losh 
4816ca987d46SWarner Losh     FICL_CODE code = pFW->code;
4817ca987d46SWarner Losh     int i;
4818ca987d46SWarner Losh 
4819ca987d46SWarner Losh     for (i=0; i < nMAP; i++)
4820ca987d46SWarner Losh     {
4821ca987d46SWarner Losh         if (codeMap[i].code == code)
4822ca987d46SWarner Losh             return codeMap[i].kind;
4823ca987d46SWarner Losh     }
4824ca987d46SWarner Losh 
4825ca987d46SWarner Losh     return PRIMITIVE;
4826ca987d46SWarner Losh }
4827ca987d46SWarner Losh 
4828ca987d46SWarner Losh 
4829ca987d46SWarner Losh #ifdef TESTMAIN
4830ca987d46SWarner Losh /**************************************************************************
4831ca987d46SWarner Losh **                     r a n d o m
4832ca987d46SWarner Losh ** FICL-specific
4833ca987d46SWarner Losh **************************************************************************/
ficlRandom(FICL_VM * pVM)4834ca987d46SWarner Losh static void ficlRandom(FICL_VM *pVM)
4835ca987d46SWarner Losh {
4836ca987d46SWarner Losh     PUSHUNS(random());
4837ca987d46SWarner Losh }
4838ca987d46SWarner Losh 
4839ca987d46SWarner Losh 
4840ca987d46SWarner Losh /**************************************************************************
4841ca987d46SWarner Losh **                     s e e d - r a n d o m
4842ca987d46SWarner Losh ** FICL-specific
4843ca987d46SWarner Losh **************************************************************************/
ficlSeedRandom(FICL_VM * pVM)4844ca987d46SWarner Losh static void ficlSeedRandom(FICL_VM *pVM)
4845ca987d46SWarner Losh {
4846ca987d46SWarner Losh     srandom(POPUNS());
4847ca987d46SWarner Losh }
4848ca987d46SWarner Losh #endif
4849ca987d46SWarner Losh 
4850ca987d46SWarner Losh 
4851ca987d46SWarner Losh /**************************************************************************
4852ca987d46SWarner Losh                         f i c l C o m p i l e C o r e
4853ca987d46SWarner Losh ** Builds the primitive wordset and the environment-query namespace.
4854ca987d46SWarner Losh **************************************************************************/
4855ca987d46SWarner Losh 
ficlCompileCore(FICL_SYSTEM * pSys)4856ca987d46SWarner Losh void ficlCompileCore(FICL_SYSTEM *pSys)
4857ca987d46SWarner Losh {
4858ca987d46SWarner Losh     FICL_DICT *dp = pSys->dp;
4859ca987d46SWarner Losh     assert (dp);
4860ca987d46SWarner Losh 
4861ca987d46SWarner Losh 
4862ca987d46SWarner Losh     /*
4863ca987d46SWarner Losh     ** CORE word set
4864ca987d46SWarner Losh     ** see softcore.c for definitions of: abs bl space spaces abort"
4865ca987d46SWarner Losh     */
4866ca987d46SWarner Losh     pSys->pStore =
4867ca987d46SWarner Losh     dictAppendWord(dp, "!",         store,          FW_DEFAULT);
4868ca987d46SWarner Losh     dictAppendWord(dp, "#",         numberSign,     FW_DEFAULT);
4869ca987d46SWarner Losh     dictAppendWord(dp, "#>",        numberSignGreater,FW_DEFAULT);
4870ca987d46SWarner Losh     dictAppendWord(dp, "#s",        numberSignS,    FW_DEFAULT);
4871ca987d46SWarner Losh     dictAppendWord(dp, "\'",        ficlTick,       FW_DEFAULT);
4872ca987d46SWarner Losh     dictAppendWord(dp, "(",         commentHang,    FW_IMMEDIATE);
4873ca987d46SWarner Losh     dictAppendWord(dp, "*",         mul,            FW_DEFAULT);
4874ca987d46SWarner Losh     dictAppendWord(dp, "*/",        mulDiv,         FW_DEFAULT);
4875ca987d46SWarner Losh     dictAppendWord(dp, "*/mod",     mulDivRem,      FW_DEFAULT);
4876ca987d46SWarner Losh     dictAppendWord(dp, "+",         add,            FW_DEFAULT);
4877ca987d46SWarner Losh     dictAppendWord(dp, "+!",        plusStore,      FW_DEFAULT);
4878ca987d46SWarner Losh     dictAppendWord(dp, "+loop",     plusLoopCoIm,   FW_COMPIMMED);
4879ca987d46SWarner Losh     dictAppendWord(dp, ",",         comma,          FW_DEFAULT);
4880ca987d46SWarner Losh     dictAppendWord(dp, "-",         sub,            FW_DEFAULT);
4881ca987d46SWarner Losh     dictAppendWord(dp, ".",         displayCell,    FW_DEFAULT);
4882ca987d46SWarner Losh     dictAppendWord(dp, ".\"",       dotQuoteCoIm,   FW_COMPIMMED);
4883ca987d46SWarner Losh     dictAppendWord(dp, "/",         ficlDiv,        FW_DEFAULT);
4884ca987d46SWarner Losh     dictAppendWord(dp, "/mod",      slashMod,       FW_DEFAULT);
4885ca987d46SWarner Losh     dictAppendWord(dp, "0<",        zeroLess,       FW_DEFAULT);
4886ca987d46SWarner Losh     dictAppendWord(dp, "0=",        zeroEquals,     FW_DEFAULT);
4887ca987d46SWarner Losh     dictAppendWord(dp, "1+",        onePlus,        FW_DEFAULT);
4888ca987d46SWarner Losh     dictAppendWord(dp, "1-",        oneMinus,       FW_DEFAULT);
4889ca987d46SWarner Losh     dictAppendWord(dp, "2!",        twoStore,       FW_DEFAULT);
4890ca987d46SWarner Losh     dictAppendWord(dp, "2*",        twoMul,         FW_DEFAULT);
4891ca987d46SWarner Losh     dictAppendWord(dp, "2/",        twoDiv,         FW_DEFAULT);
4892ca987d46SWarner Losh     dictAppendWord(dp, "2@",        twoFetch,       FW_DEFAULT);
4893ca987d46SWarner Losh     dictAppendWord(dp, "2drop",     twoDrop,        FW_DEFAULT);
4894ca987d46SWarner Losh     dictAppendWord(dp, "2dup",      twoDup,         FW_DEFAULT);
4895ca987d46SWarner Losh     dictAppendWord(dp, "2over",     twoOver,        FW_DEFAULT);
4896ca987d46SWarner Losh     dictAppendWord(dp, "2swap",     twoSwap,        FW_DEFAULT);
4897ca987d46SWarner Losh     dictAppendWord(dp, ":",         colon,          FW_DEFAULT);
4898ca987d46SWarner Losh     dictAppendWord(dp, ";",         semicolonCoIm,  FW_COMPIMMED);
4899ca987d46SWarner Losh     dictAppendWord(dp, "<",         isLess,         FW_DEFAULT);
4900ca987d46SWarner Losh     dictAppendWord(dp, "<#",        lessNumberSign, FW_DEFAULT);
4901ca987d46SWarner Losh     dictAppendWord(dp, "=",         isEqual,        FW_DEFAULT);
4902ca987d46SWarner Losh     dictAppendWord(dp, ">",         isGreater,      FW_DEFAULT);
4903ca987d46SWarner Losh     dictAppendWord(dp, ">body",     toBody,         FW_DEFAULT);
4904ca987d46SWarner Losh     dictAppendWord(dp, ">in",       toIn,           FW_DEFAULT);
4905ca987d46SWarner Losh     dictAppendWord(dp, ">number",   toNumber,       FW_DEFAULT);
4906ca987d46SWarner Losh     dictAppendWord(dp, ">r",        toRStack,       FW_COMPILE);
4907ca987d46SWarner Losh     dictAppendWord(dp, "?dup",      questionDup,    FW_DEFAULT);
4908ca987d46SWarner Losh     dictAppendWord(dp, "@",         fetch,          FW_DEFAULT);
4909ca987d46SWarner Losh     dictAppendWord(dp, "abort",     ficlAbort,      FW_DEFAULT);
4910ca987d46SWarner Losh     dictAppendWord(dp, "accept",    accept,         FW_DEFAULT);
4911ca987d46SWarner Losh     dictAppendWord(dp, "align",     align,          FW_DEFAULT);
4912ca987d46SWarner Losh     dictAppendWord(dp, "aligned",   aligned,        FW_DEFAULT);
4913ca987d46SWarner Losh     dictAppendWord(dp, "allot",     allot,          FW_DEFAULT);
4914ca987d46SWarner Losh     dictAppendWord(dp, "and",       bitwiseAnd,     FW_DEFAULT);
4915ca987d46SWarner Losh     dictAppendWord(dp, "base",      base,           FW_DEFAULT);
4916ca987d46SWarner Losh     dictAppendWord(dp, "begin",     beginCoIm,      FW_COMPIMMED);
4917ca987d46SWarner Losh     dictAppendWord(dp, "c!",        cStore,         FW_DEFAULT);
4918ca987d46SWarner Losh     dictAppendWord(dp, "c,",        cComma,         FW_DEFAULT);
4919ca987d46SWarner Losh     dictAppendWord(dp, "c@",        cFetch,         FW_DEFAULT);
4920ca987d46SWarner Losh     dictAppendWord(dp, "case",      caseCoIm,       FW_COMPIMMED);
4921ca987d46SWarner Losh     dictAppendWord(dp, "cell+",     cellPlus,       FW_DEFAULT);
4922ca987d46SWarner Losh     dictAppendWord(dp, "cells",     cells,          FW_DEFAULT);
4923ca987d46SWarner Losh     dictAppendWord(dp, "char",      ficlChar,       FW_DEFAULT);
4924ca987d46SWarner Losh     dictAppendWord(dp, "char+",     charPlus,       FW_DEFAULT);
4925ca987d46SWarner Losh     dictAppendWord(dp, "chars",     ficlChars,      FW_DEFAULT);
4926ca987d46SWarner Losh     dictAppendWord(dp, "constant",  constant,       FW_DEFAULT);
4927ca987d46SWarner Losh     dictAppendWord(dp, "count",     count,          FW_DEFAULT);
4928ca987d46SWarner Losh     dictAppendWord(dp, "cr",        cr,             FW_DEFAULT);
4929ca987d46SWarner Losh     dictAppendWord(dp, "create",    create,         FW_DEFAULT);
4930ca987d46SWarner Losh     dictAppendWord(dp, "decimal",   decimal,        FW_DEFAULT);
4931ca987d46SWarner Losh     dictAppendWord(dp, "depth",     depth,          FW_DEFAULT);
4932ca987d46SWarner Losh     dictAppendWord(dp, "do",        doCoIm,         FW_COMPIMMED);
4933ca987d46SWarner Losh     dictAppendWord(dp, "does>",     doesCoIm,       FW_COMPIMMED);
4934ca987d46SWarner Losh     pSys->pDrop =
4935ca987d46SWarner Losh     dictAppendWord(dp, "drop",      drop,           FW_DEFAULT);
4936ca987d46SWarner Losh     dictAppendWord(dp, "dup",       dup,            FW_DEFAULT);
4937ca987d46SWarner Losh     dictAppendWord(dp, "else",      elseCoIm,       FW_COMPIMMED);
4938ca987d46SWarner Losh     dictAppendWord(dp, "emit",      emit,           FW_DEFAULT);
4939ca987d46SWarner Losh     dictAppendWord(dp, "endcase",   endcaseCoIm,    FW_COMPIMMED);
4940ca987d46SWarner Losh     dictAppendWord(dp, "endof",     endofCoIm,      FW_COMPIMMED);
4941ca987d46SWarner Losh     dictAppendWord(dp, "environment?", environmentQ,FW_DEFAULT);
4942ca987d46SWarner Losh     dictAppendWord(dp, "evaluate",  evaluate,       FW_DEFAULT);
4943ca987d46SWarner Losh     dictAppendWord(dp, "execute",   execute,        FW_DEFAULT);
4944ca987d46SWarner Losh     dictAppendWord(dp, "exit",      exitCoIm,       FW_COMPIMMED);
4945ca987d46SWarner Losh     dictAppendWord(dp, "fallthrough",fallthroughCoIm,FW_COMPIMMED);
4946ca987d46SWarner Losh     dictAppendWord(dp, "fill",      fill,           FW_DEFAULT);
4947ca987d46SWarner Losh     dictAppendWord(dp, "find",      cFind,          FW_DEFAULT);
4948ca987d46SWarner Losh     dictAppendWord(dp, "fm/mod",    fmSlashMod,     FW_DEFAULT);
4949ca987d46SWarner Losh     dictAppendWord(dp, "here",      here,           FW_DEFAULT);
4950ca987d46SWarner Losh     dictAppendWord(dp, "hold",      hold,           FW_DEFAULT);
4951ca987d46SWarner Losh     dictAppendWord(dp, "i",         loopICo,        FW_COMPILE);
4952ca987d46SWarner Losh     dictAppendWord(dp, "if",        ifCoIm,         FW_COMPIMMED);
4953ca987d46SWarner Losh     dictAppendWord(dp, "immediate", immediate,      FW_DEFAULT);
4954ca987d46SWarner Losh     dictAppendWord(dp, "invert",    bitwiseNot,     FW_DEFAULT);
4955ca987d46SWarner Losh     dictAppendWord(dp, "j",         loopJCo,        FW_COMPILE);
4956ca987d46SWarner Losh     dictAppendWord(dp, "k",         loopKCo,        FW_COMPILE);
4957ca987d46SWarner Losh     dictAppendWord(dp, "leave",     leaveCo,        FW_COMPILE);
4958ca987d46SWarner Losh     dictAppendWord(dp, "literal",   literalIm,      FW_IMMEDIATE);
4959ca987d46SWarner Losh     dictAppendWord(dp, "loop",      loopCoIm,       FW_COMPIMMED);
4960ca987d46SWarner Losh     dictAppendWord(dp, "lshift",    lshift,         FW_DEFAULT);
4961ca987d46SWarner Losh     dictAppendWord(dp, "m*",        mStar,          FW_DEFAULT);
4962ca987d46SWarner Losh     dictAppendWord(dp, "max",       ficlMax,        FW_DEFAULT);
4963ca987d46SWarner Losh     dictAppendWord(dp, "min",       ficlMin,        FW_DEFAULT);
4964ca987d46SWarner Losh     dictAppendWord(dp, "mod",       ficlMod,        FW_DEFAULT);
4965ca987d46SWarner Losh     dictAppendWord(dp, "move",      move,           FW_DEFAULT);
4966ca987d46SWarner Losh     dictAppendWord(dp, "negate",    negate,         FW_DEFAULT);
4967ca987d46SWarner Losh     dictAppendWord(dp, "of",        ofCoIm,         FW_COMPIMMED);
4968ca987d46SWarner Losh     dictAppendWord(dp, "or",        bitwiseOr,      FW_DEFAULT);
4969ca987d46SWarner Losh     dictAppendWord(dp, "over",      over,           FW_DEFAULT);
4970ca987d46SWarner Losh     dictAppendWord(dp, "postpone",  postponeCoIm,   FW_COMPIMMED);
4971ca987d46SWarner Losh     dictAppendWord(dp, "quit",      quit,           FW_DEFAULT);
4972ca987d46SWarner Losh     dictAppendWord(dp, "r>",        fromRStack,     FW_COMPILE);
4973ca987d46SWarner Losh     dictAppendWord(dp, "r@",        fetchRStack,    FW_COMPILE);
4974ca987d46SWarner Losh     dictAppendWord(dp, "recurse",   recurseCoIm,    FW_COMPIMMED);
4975ca987d46SWarner Losh     dictAppendWord(dp, "repeat",    repeatCoIm,     FW_COMPIMMED);
4976ca987d46SWarner Losh     dictAppendWord(dp, "rot",       rot,            FW_DEFAULT);
4977ca987d46SWarner Losh     dictAppendWord(dp, "rshift",    rshift,         FW_DEFAULT);
4978ca987d46SWarner Losh     dictAppendWord(dp, "s\"",       stringQuoteIm,  FW_IMMEDIATE);
4979ca987d46SWarner Losh     dictAppendWord(dp, "s>d",       sToD,           FW_DEFAULT);
4980ca987d46SWarner Losh     dictAppendWord(dp, "sign",      sign,           FW_DEFAULT);
4981ca987d46SWarner Losh     dictAppendWord(dp, "sm/rem",    smSlashRem,     FW_DEFAULT);
4982ca987d46SWarner Losh     dictAppendWord(dp, "source",    source,         FW_DEFAULT);
4983ca987d46SWarner Losh     dictAppendWord(dp, "state",     state,          FW_DEFAULT);
4984ca987d46SWarner Losh     dictAppendWord(dp, "swap",      swap,           FW_DEFAULT);
4985ca987d46SWarner Losh     dictAppendWord(dp, "then",      endifCoIm,      FW_COMPIMMED);
4986ca987d46SWarner Losh     dictAppendWord(dp, "type",      type,           FW_DEFAULT);
4987ca987d46SWarner Losh     dictAppendWord(dp, "u.",        uDot,           FW_DEFAULT);
4988ca987d46SWarner Losh     dictAppendWord(dp, "u<",        uIsLess,        FW_DEFAULT);
49890bd5d367SToomas Soome     dictAppendWord(dp, "u>",        uIsGreater,     FW_DEFAULT);
4990ca987d46SWarner Losh     dictAppendWord(dp, "um*",       umStar,         FW_DEFAULT);
4991ca987d46SWarner Losh     dictAppendWord(dp, "um/mod",    umSlashMod,     FW_DEFAULT);
4992ca987d46SWarner Losh     dictAppendWord(dp, "unloop",    unloopCo,       FW_COMPILE);
4993ca987d46SWarner Losh     dictAppendWord(dp, "until",     untilCoIm,      FW_COMPIMMED);
4994ca987d46SWarner Losh     dictAppendWord(dp, "variable",  variable,       FW_DEFAULT);
4995ca987d46SWarner Losh     dictAppendWord(dp, "while",     whileCoIm,      FW_COMPIMMED);
4996ca987d46SWarner Losh     dictAppendWord(dp, "word",      ficlWord,       FW_DEFAULT);
4997ca987d46SWarner Losh     dictAppendWord(dp, "xor",       bitwiseXor,     FW_DEFAULT);
4998ca987d46SWarner Losh     dictAppendWord(dp, "[",         lbracketCoIm,   FW_COMPIMMED);
4999ca987d46SWarner Losh     dictAppendWord(dp, "[\']",      bracketTickCoIm,FW_COMPIMMED);
5000ca987d46SWarner Losh     dictAppendWord(dp, "[char]",    charCoIm,       FW_COMPIMMED);
5001ca987d46SWarner Losh     dictAppendWord(dp, "]",         rbracket,       FW_DEFAULT);
5002ca987d46SWarner Losh     /*
5003ca987d46SWarner Losh     ** CORE EXT word set...
5004ca987d46SWarner Losh     ** see softcore.fr for other definitions
5005ca987d46SWarner Losh     */
5006ca987d46SWarner Losh     /* "#tib" */
5007ca987d46SWarner Losh     dictAppendWord(dp, ".(",        dotParen,       FW_IMMEDIATE);
5008ca987d46SWarner Losh     /* ".r" */
5009ca987d46SWarner Losh     dictAppendWord(dp, "0>",        zeroGreater,    FW_DEFAULT);
5010ca987d46SWarner Losh     dictAppendWord(dp, "2>r",       twoToR,         FW_COMPILE);
5011ca987d46SWarner Losh     dictAppendWord(dp, "2r>",       twoRFrom,       FW_COMPILE);
5012ca987d46SWarner Losh     dictAppendWord(dp, "2r@",       twoRFetch,      FW_COMPILE);
5013ca987d46SWarner Losh     dictAppendWord(dp, ":noname",   colonNoName,    FW_DEFAULT);
5014ca987d46SWarner Losh     dictAppendWord(dp, "?do",       qDoCoIm,        FW_COMPIMMED);
5015ca987d46SWarner Losh     dictAppendWord(dp, "again",     againCoIm,      FW_COMPIMMED);
5016ca987d46SWarner Losh     dictAppendWord(dp, "c\"",       cstringQuoteIm, FW_IMMEDIATE);
5017ca987d46SWarner Losh     dictAppendWord(dp, "hex",       hex,            FW_DEFAULT);
5018ca987d46SWarner Losh     dictAppendWord(dp, "pad",       pad,            FW_DEFAULT);
5019ca987d46SWarner Losh     dictAppendWord(dp, "parse",     parse,          FW_DEFAULT);
5020ca987d46SWarner Losh     dictAppendWord(dp, "pick",      pick,           FW_DEFAULT);
5021ca987d46SWarner Losh     /* query restore-input save-input tib u.r u> unused [compile] */
5022ca987d46SWarner Losh     dictAppendWord(dp, "roll",      roll,           FW_DEFAULT);
5023ca987d46SWarner Losh     dictAppendWord(dp, "refill",    refill,         FW_DEFAULT);
5024ca987d46SWarner Losh     dictAppendWord(dp, "source-id", sourceid,       FW_DEFAULT);
5025ca987d46SWarner Losh     dictAppendWord(dp, "to",        toValue,        FW_IMMEDIATE);
5026ca987d46SWarner Losh     dictAppendWord(dp, "value",     constant,       FW_DEFAULT);
5027ca987d46SWarner Losh     dictAppendWord(dp, "\\",        commentLine,    FW_IMMEDIATE);
5028ca987d46SWarner Losh 
5029ca987d46SWarner Losh 
5030ca987d46SWarner Losh     /*
5031ca987d46SWarner Losh     ** Set CORE environment query values
5032ca987d46SWarner Losh     */
5033ca987d46SWarner Losh     ficlSetEnv(pSys, "/counted-string",   FICL_STRING_MAX);
5034ca987d46SWarner Losh     ficlSetEnv(pSys, "/hold",             nPAD);
5035ca987d46SWarner Losh     ficlSetEnv(pSys, "/pad",              nPAD);
5036ca987d46SWarner Losh     ficlSetEnv(pSys, "address-unit-bits", 8);
5037ca987d46SWarner Losh     ficlSetEnv(pSys, "core",              FICL_TRUE);
5038ca987d46SWarner Losh     ficlSetEnv(pSys, "core-ext",          FICL_FALSE);
5039ca987d46SWarner Losh     ficlSetEnv(pSys, "floored",           FICL_FALSE);
5040ca987d46SWarner Losh     ficlSetEnv(pSys, "max-char",          UCHAR_MAX);
5041ca987d46SWarner Losh     ficlSetEnvD(pSys,"max-d",             0x7fffffff, 0xffffffff);
5042ca987d46SWarner Losh     ficlSetEnv(pSys, "max-n",             0x7fffffff);
5043ca987d46SWarner Losh     ficlSetEnv(pSys, "max-u",             0xffffffff);
5044ca987d46SWarner Losh     ficlSetEnvD(pSys,"max-ud",            0xffffffff, 0xffffffff);
5045ca987d46SWarner Losh     ficlSetEnv(pSys, "return-stack-cells",FICL_DEFAULT_STACK);
5046ca987d46SWarner Losh     ficlSetEnv(pSys, "stack-cells",       FICL_DEFAULT_STACK);
5047ca987d46SWarner Losh 
5048ca987d46SWarner Losh     /*
5049ca987d46SWarner Losh     ** DOUBLE word set (partial)
5050ca987d46SWarner Losh     */
5051ca987d46SWarner Losh     dictAppendWord(dp, "2constant", twoConstant,    FW_IMMEDIATE);
5052ca987d46SWarner Losh     dictAppendWord(dp, "2literal",  twoLiteralIm,   FW_IMMEDIATE);
5053ca987d46SWarner Losh     dictAppendWord(dp, "2variable", twoVariable,    FW_IMMEDIATE);
5054ca987d46SWarner Losh     dictAppendWord(dp, "dnegate",   dnegate,        FW_DEFAULT);
5055ca987d46SWarner Losh 
5056ca987d46SWarner Losh 
5057ca987d46SWarner Losh     /*
5058ca987d46SWarner Losh     ** EXCEPTION word set
5059ca987d46SWarner Losh     */
5060ca987d46SWarner Losh     dictAppendWord(dp, "catch",     ficlCatch,      FW_DEFAULT);
5061ca987d46SWarner Losh     dictAppendWord(dp, "throw",     ficlThrow,      FW_DEFAULT);
5062ca987d46SWarner Losh 
5063ca987d46SWarner Losh     ficlSetEnv(pSys, "exception",         FICL_TRUE);
5064ca987d46SWarner Losh     ficlSetEnv(pSys, "exception-ext",     FICL_TRUE);
5065ca987d46SWarner Losh 
5066ca987d46SWarner Losh     /*
5067ca987d46SWarner Losh     ** LOCAL and LOCAL EXT
5068ca987d46SWarner Losh     ** see softcore.c for implementation of locals|
5069ca987d46SWarner Losh     */
5070ca987d46SWarner Losh #if FICL_WANT_LOCALS
5071ca987d46SWarner Losh     pSys->pLinkParen =
5072ca987d46SWarner Losh     dictAppendWord(dp, "(link)",    linkParen,      FW_COMPILE);
5073ca987d46SWarner Losh     pSys->pUnLinkParen =
5074ca987d46SWarner Losh     dictAppendWord(dp, "(unlink)",  unlinkParen,    FW_COMPILE);
5075ca987d46SWarner Losh     dictAppendWord(dp, "doLocal",   doLocalIm,      FW_COMPIMMED);
5076ca987d46SWarner Losh     pSys->pGetLocalParen =
5077ca987d46SWarner Losh     dictAppendWord(dp, "(@local)",  getLocalParen,  FW_COMPILE);
5078ca987d46SWarner Losh     pSys->pToLocalParen =
5079ca987d46SWarner Losh     dictAppendWord(dp, "(toLocal)", toLocalParen,   FW_COMPILE);
5080ca987d46SWarner Losh     pSys->pGetLocal0 =
5081ca987d46SWarner Losh     dictAppendWord(dp, "(@local0)", getLocal0,      FW_COMPILE);
5082ca987d46SWarner Losh     pSys->pToLocal0 =
5083ca987d46SWarner Losh     dictAppendWord(dp, "(toLocal0)",toLocal0,       FW_COMPILE);
5084ca987d46SWarner Losh     pSys->pGetLocal1 =
5085ca987d46SWarner Losh     dictAppendWord(dp, "(@local1)", getLocal1,      FW_COMPILE);
5086ca987d46SWarner Losh     pSys->pToLocal1 =
5087ca987d46SWarner Losh     dictAppendWord(dp, "(toLocal1)",toLocal1,       FW_COMPILE);
5088ca987d46SWarner Losh     dictAppendWord(dp, "(local)",   localParen,     FW_COMPILE);
5089ca987d46SWarner Losh 
5090ca987d46SWarner Losh     pSys->pGet2LocalParen =
5091ca987d46SWarner Losh     dictAppendWord(dp, "(@2local)", get2LocalParen, FW_COMPILE);
5092ca987d46SWarner Losh     pSys->pTo2LocalParen =
5093ca987d46SWarner Losh     dictAppendWord(dp, "(to2Local)",to2LocalParen,  FW_COMPILE);
5094ca987d46SWarner Losh     dictAppendWord(dp, "(2local)",  twoLocalParen,  FW_COMPILE);
5095ca987d46SWarner Losh 
5096ca987d46SWarner Losh     ficlSetEnv(pSys, "locals",            FICL_TRUE);
5097ca987d46SWarner Losh     ficlSetEnv(pSys, "locals-ext",        FICL_TRUE);
5098ca987d46SWarner Losh     ficlSetEnv(pSys, "#locals",           FICL_MAX_LOCALS);
5099ca987d46SWarner Losh #endif
5100ca987d46SWarner Losh 
5101ca987d46SWarner Losh     /*
5102ca987d46SWarner Losh     ** Optional MEMORY-ALLOC word set
5103ca987d46SWarner Losh     */
5104ca987d46SWarner Losh 
5105ca987d46SWarner Losh     dictAppendWord(dp, "allocate",  ansAllocate,    FW_DEFAULT);
5106ca987d46SWarner Losh     dictAppendWord(dp, "free",      ansFree,        FW_DEFAULT);
5107ca987d46SWarner Losh     dictAppendWord(dp, "resize",    ansResize,      FW_DEFAULT);
5108ca987d46SWarner Losh 
5109ca987d46SWarner Losh     ficlSetEnv(pSys, "memory-alloc",      FICL_TRUE);
5110ca987d46SWarner Losh 
5111ca987d46SWarner Losh     /*
5112ca987d46SWarner Losh     ** optional SEARCH-ORDER word set
5113ca987d46SWarner Losh     */
5114ca987d46SWarner Losh     ficlCompileSearch(pSys);
5115ca987d46SWarner Losh 
5116ca987d46SWarner Losh     /*
5117ca987d46SWarner Losh     ** TOOLS and TOOLS EXT
5118ca987d46SWarner Losh     */
5119ca987d46SWarner Losh     ficlCompileTools(pSys);
5120ca987d46SWarner Losh 
5121ca987d46SWarner Losh     /*
5122ca987d46SWarner Losh     ** FILE and FILE EXT
5123ca987d46SWarner Losh     */
5124ca987d46SWarner Losh #if FICL_WANT_FILE
5125ca987d46SWarner Losh     ficlCompileFile(pSys);
5126ca987d46SWarner Losh #endif
5127ca987d46SWarner Losh 
5128ca987d46SWarner Losh     /*
5129ca987d46SWarner Losh     ** Ficl extras
5130ca987d46SWarner Losh     */
5131ca987d46SWarner Losh #if FICL_WANT_FLOAT
5132ca987d46SWarner Losh     dictAppendWord(dp, ".hash",     dictHashSummary,FW_DEFAULT);
5133ca987d46SWarner Losh #endif
5134ca987d46SWarner Losh     dictAppendWord(dp, ".ver",      ficlVersion,    FW_DEFAULT);
5135ca987d46SWarner Losh     dictAppendWord(dp, "-roll",     minusRoll,      FW_DEFAULT);
5136ca987d46SWarner Losh     dictAppendWord(dp, ">name",     toName,         FW_DEFAULT);
5137ca987d46SWarner Losh     dictAppendWord(dp, "add-parse-step",
5138ca987d46SWarner Losh                                     addParseStep,   FW_DEFAULT);
5139ca987d46SWarner Losh     dictAppendWord(dp, "body>",     fromBody,       FW_DEFAULT);
5140ca987d46SWarner Losh     dictAppendWord(dp, "compare",   compareString,  FW_DEFAULT);   /* STRING */
5141ca987d46SWarner Losh     dictAppendWord(dp, "compare-insensitive",   compareStringInsensitive,  FW_DEFAULT);   /* STRING */
5142ca987d46SWarner Losh     dictAppendWord(dp, "compile-only",
5143ca987d46SWarner Losh                                     compileOnly,    FW_DEFAULT);
5144ca987d46SWarner Losh     dictAppendWord(dp, "endif",     endifCoIm,      FW_COMPIMMED);
5145ca987d46SWarner Losh     dictAppendWord(dp, "last-word", getLastWord,    FW_DEFAULT);
5146ca987d46SWarner Losh     dictAppendWord(dp, "hash",      hash,           FW_DEFAULT);
5147ca987d46SWarner Losh     dictAppendWord(dp, "objectify", setObjectFlag,  FW_DEFAULT);
5148ca987d46SWarner Losh     dictAppendWord(dp, "?object",   isObject,       FW_DEFAULT);
5149ca987d46SWarner Losh     dictAppendWord(dp, "parse-word",parseNoCopy,    FW_DEFAULT);
5150ca987d46SWarner Losh     dictAppendWord(dp, "sfind",     sFind,          FW_DEFAULT);
5151ca987d46SWarner Losh     dictAppendWord(dp, "sliteral",  sLiteralCoIm,   FW_COMPIMMED); /* STRING */
5152ca987d46SWarner Losh     dictAppendWord(dp, "sprintf",   ficlSprintf,    FW_DEFAULT);
5153ca987d46SWarner Losh     dictAppendWord(dp, "strlen",    ficlStrlen,     FW_DEFAULT);
5154ca987d46SWarner Losh     dictAppendWord(dp, "q@",        quadFetch,      FW_DEFAULT);
5155ca987d46SWarner Losh     dictAppendWord(dp, "q!",        quadStore,      FW_DEFAULT);
5156ca987d46SWarner Losh     dictAppendWord(dp, "w@",        wFetch,         FW_DEFAULT);
5157ca987d46SWarner Losh     dictAppendWord(dp, "w!",        wStore,         FW_DEFAULT);
5158ca987d46SWarner Losh     dictAppendWord(dp, "x.",        hexDot,         FW_DEFAULT);
5159ca987d46SWarner Losh #if FICL_WANT_USER
5160ca987d46SWarner Losh     dictAppendWord(dp, "(user)",    userParen,      FW_DEFAULT);
5161ca987d46SWarner Losh     dictAppendWord(dp, "user",      userVariable,   FW_DEFAULT);
5162ca987d46SWarner Losh #endif
5163ca987d46SWarner Losh #ifdef TESTMAIN
5164ca987d46SWarner Losh     dictAppendWord(dp, "random",    ficlRandom,     FW_DEFAULT);
5165ca987d46SWarner Losh     dictAppendWord(dp, "seed-random",ficlSeedRandom,FW_DEFAULT);
5166ca987d46SWarner Losh #endif
5167ca987d46SWarner Losh 
5168ca987d46SWarner Losh     /*
5169ca987d46SWarner Losh     ** internal support words
5170ca987d46SWarner Losh     */
5171ca987d46SWarner Losh     dictAppendWord(dp, "(create)",  createParen,    FW_COMPILE);
5172ca987d46SWarner Losh     pSys->pExitParen =
5173ca987d46SWarner Losh     dictAppendWord(dp, "(exit)",    exitParen,      FW_COMPILE);
5174ca987d46SWarner Losh     pSys->pSemiParen =
5175ca987d46SWarner Losh     dictAppendWord(dp, "(;)",       semiParen,      FW_COMPILE);
5176ca987d46SWarner Losh     pSys->pLitParen =
5177ca987d46SWarner Losh     dictAppendWord(dp, "(literal)", literalParen,   FW_COMPILE);
5178ca987d46SWarner Losh     pSys->pTwoLitParen =
5179ca987d46SWarner Losh     dictAppendWord(dp, "(2literal)",twoLitParen,    FW_COMPILE);
5180ca987d46SWarner Losh     pSys->pStringLit =
5181ca987d46SWarner Losh     dictAppendWord(dp, "(.\")",     stringLit,      FW_COMPILE);
5182ca987d46SWarner Losh     pSys->pCStringLit =
5183ca987d46SWarner Losh     dictAppendWord(dp, "(c\")",     cstringLit,     FW_COMPILE);
5184ca987d46SWarner Losh     pSys->pBranch0 =
5185ca987d46SWarner Losh     dictAppendWord(dp, "(branch0)",      branch0,        FW_COMPILE);
5186ca987d46SWarner Losh     pSys->pBranchParen =
5187ca987d46SWarner Losh     dictAppendWord(dp, "(branch)",  branchParen,    FW_COMPILE);
5188ca987d46SWarner Losh     pSys->pDoParen =
5189ca987d46SWarner Losh     dictAppendWord(dp, "(do)",      doParen,        FW_COMPILE);
5190ca987d46SWarner Losh     pSys->pDoesParen =
5191ca987d46SWarner Losh     dictAppendWord(dp, "(does>)",   doesParen,      FW_COMPILE);
5192ca987d46SWarner Losh     pSys->pQDoParen =
5193ca987d46SWarner Losh     dictAppendWord(dp, "(?do)",     qDoParen,       FW_COMPILE);
5194ca987d46SWarner Losh     pSys->pLoopParen =
5195ca987d46SWarner Losh     dictAppendWord(dp, "(loop)",    loopParen,      FW_COMPILE);
5196ca987d46SWarner Losh     pSys->pPLoopParen =
5197ca987d46SWarner Losh     dictAppendWord(dp, "(+loop)",   plusLoopParen,  FW_COMPILE);
5198ca987d46SWarner Losh     pSys->pInterpret =
5199ca987d46SWarner Losh     dictAppendWord(dp, "interpret", interpret,      FW_DEFAULT);
5200ca987d46SWarner Losh     dictAppendWord(dp, "lookup",    lookup,         FW_DEFAULT);
5201ca987d46SWarner Losh     pSys->pOfParen =
5202ca987d46SWarner Losh     dictAppendWord(dp, "(of)",      ofParen,        FW_DEFAULT);
5203ca987d46SWarner Losh     dictAppendWord(dp, "(variable)",variableParen,  FW_COMPILE);
5204ca987d46SWarner Losh     dictAppendWord(dp, "(constant)",constantParen,  FW_COMPILE);
5205ca987d46SWarner Losh     dictAppendWord(dp, "(parse-step)",
5206ca987d46SWarner Losh                                     parseStepParen, FW_DEFAULT);
5207ca987d46SWarner Losh 	pSys->pExitInner =
5208ca987d46SWarner Losh     dictAppendWord(dp, "exit-inner",ficlExitInner,  FW_DEFAULT);
5209ca987d46SWarner Losh 
5210ca987d46SWarner Losh     /*
5211ca987d46SWarner Losh     ** Set up system's outer interpreter loop - maybe this should be in initSystem?
5212ca987d46SWarner Losh     */
5213ca987d46SWarner Losh     pSys->pInterp[0] = pSys->pInterpret;
5214ca987d46SWarner Losh     pSys->pInterp[1] = pSys->pBranchParen;
5215ca987d46SWarner Losh     pSys->pInterp[2] = (FICL_WORD *)(void *)(-2);
5216ca987d46SWarner Losh 
5217ca987d46SWarner Losh     assert(dictCellsAvail(dp) > 0);
5218ca987d46SWarner Losh 
5219ca987d46SWarner Losh     return;
5220ca987d46SWarner Losh }
5221