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