xref: /titanic_54/usr/src/common/ficl/vm.c (revision a1bf3f785ae05c419b339c3a2061f2b18c024f61)
1*a1bf3f78SToomas Soome /*
2*a1bf3f78SToomas Soome  * v m . c
3*a1bf3f78SToomas Soome  * Forth Inspired Command Language - virtual machine methods
4*a1bf3f78SToomas Soome  * Author: John Sadler (john_sadler@alum.mit.edu)
5*a1bf3f78SToomas Soome  * Created: 19 July 1997
6*a1bf3f78SToomas Soome  * $Id: vm.c,v 1.17 2010/09/13 18:43:04 asau Exp $
7*a1bf3f78SToomas Soome  */
8*a1bf3f78SToomas Soome /*
9*a1bf3f78SToomas Soome  * This file implements the virtual machine of Ficl. Each virtual
10*a1bf3f78SToomas Soome  * machine retains the state of an interpreter. A virtual machine
11*a1bf3f78SToomas Soome  * owns a pair of stacks for parameters and return addresses, as
12*a1bf3f78SToomas Soome  * well as a pile of state variables and the two dedicated registers
13*a1bf3f78SToomas Soome  * of the interpreter.
14*a1bf3f78SToomas Soome  */
15*a1bf3f78SToomas Soome /*
16*a1bf3f78SToomas Soome  * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
17*a1bf3f78SToomas Soome  * All rights reserved.
18*a1bf3f78SToomas Soome  *
19*a1bf3f78SToomas Soome  * Get the latest Ficl release at http://ficl.sourceforge.net
20*a1bf3f78SToomas Soome  *
21*a1bf3f78SToomas Soome  * I am interested in hearing from anyone who uses Ficl. If you have
22*a1bf3f78SToomas Soome  * a problem, a success story, a defect, an enhancement request, or
23*a1bf3f78SToomas Soome  * if you would like to contribute to the Ficl release, please
24*a1bf3f78SToomas Soome  * contact me by email at the address above.
25*a1bf3f78SToomas Soome  *
26*a1bf3f78SToomas Soome  * L I C E N S E  and  D I S C L A I M E R
27*a1bf3f78SToomas Soome  *
28*a1bf3f78SToomas Soome  * Redistribution and use in source and binary forms, with or without
29*a1bf3f78SToomas Soome  * modification, are permitted provided that the following conditions
30*a1bf3f78SToomas Soome  * are met:
31*a1bf3f78SToomas Soome  * 1. Redistributions of source code must retain the above copyright
32*a1bf3f78SToomas Soome  *    notice, this list of conditions and the following disclaimer.
33*a1bf3f78SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
34*a1bf3f78SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
35*a1bf3f78SToomas Soome  *    documentation and/or other materials provided with the distribution.
36*a1bf3f78SToomas Soome  *
37*a1bf3f78SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
38*a1bf3f78SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39*a1bf3f78SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40*a1bf3f78SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
41*a1bf3f78SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42*a1bf3f78SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43*a1bf3f78SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44*a1bf3f78SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45*a1bf3f78SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46*a1bf3f78SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47*a1bf3f78SToomas Soome  * SUCH DAMAGE.
48*a1bf3f78SToomas Soome  */
49*a1bf3f78SToomas Soome 
50*a1bf3f78SToomas Soome #include "ficl.h"
51*a1bf3f78SToomas Soome 
52*a1bf3f78SToomas Soome #if FICL_ROBUST >= 2
53*a1bf3f78SToomas Soome #define	FICL_VM_CHECK(vm)	\
54*a1bf3f78SToomas Soome 	FICL_VM_ASSERT(vm, (*(vm->ip - 1)) == vm->runningWord)
55*a1bf3f78SToomas Soome #else
56*a1bf3f78SToomas Soome #define	FICL_VM_CHECK(vm)
57*a1bf3f78SToomas Soome #endif
58*a1bf3f78SToomas Soome 
59*a1bf3f78SToomas Soome /*
60*a1bf3f78SToomas Soome  * v m B r a n c h R e l a t i v e
61*a1bf3f78SToomas Soome  */
62*a1bf3f78SToomas Soome void
63*a1bf3f78SToomas Soome ficlVmBranchRelative(ficlVm *vm, int offset)
64*a1bf3f78SToomas Soome {
65*a1bf3f78SToomas Soome 	vm->ip += offset;
66*a1bf3f78SToomas Soome }
67*a1bf3f78SToomas Soome 
68*a1bf3f78SToomas Soome /*
69*a1bf3f78SToomas Soome  * v m C r e a t e
70*a1bf3f78SToomas Soome  * Creates a virtual machine either from scratch (if vm is NULL on entry)
71*a1bf3f78SToomas Soome  * or by resizing and reinitializing an existing VM to the specified stack
72*a1bf3f78SToomas Soome  * sizes.
73*a1bf3f78SToomas Soome  */
74*a1bf3f78SToomas Soome ficlVm *
75*a1bf3f78SToomas Soome ficlVmCreate(ficlVm *vm, unsigned nPStack, unsigned nRStack)
76*a1bf3f78SToomas Soome {
77*a1bf3f78SToomas Soome 	if (vm == NULL) {
78*a1bf3f78SToomas Soome 		vm = (ficlVm *)ficlMalloc(sizeof (ficlVm));
79*a1bf3f78SToomas Soome 		FICL_ASSERT(NULL, vm);
80*a1bf3f78SToomas Soome 		memset(vm, 0, sizeof (ficlVm));
81*a1bf3f78SToomas Soome 	}
82*a1bf3f78SToomas Soome 
83*a1bf3f78SToomas Soome 	if (vm->dataStack)
84*a1bf3f78SToomas Soome 		ficlStackDestroy(vm->dataStack);
85*a1bf3f78SToomas Soome 	vm->dataStack = ficlStackCreate(vm, "data", nPStack);
86*a1bf3f78SToomas Soome 
87*a1bf3f78SToomas Soome 	if (vm->returnStack)
88*a1bf3f78SToomas Soome 		ficlStackDestroy(vm->returnStack);
89*a1bf3f78SToomas Soome 	vm->returnStack = ficlStackCreate(vm, "return", nRStack);
90*a1bf3f78SToomas Soome 
91*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
92*a1bf3f78SToomas Soome 	if (vm->floatStack)
93*a1bf3f78SToomas Soome 		ficlStackDestroy(vm->floatStack);
94*a1bf3f78SToomas Soome 	vm->floatStack = ficlStackCreate(vm, "float", nPStack);
95*a1bf3f78SToomas Soome #endif
96*a1bf3f78SToomas Soome 
97*a1bf3f78SToomas Soome 	ficlVmReset(vm);
98*a1bf3f78SToomas Soome 	return (vm);
99*a1bf3f78SToomas Soome }
100*a1bf3f78SToomas Soome 
101*a1bf3f78SToomas Soome /*
102*a1bf3f78SToomas Soome  * v m D e l e t e
103*a1bf3f78SToomas Soome  * Free all memory allocated to the specified VM and its subordinate
104*a1bf3f78SToomas Soome  * structures.
105*a1bf3f78SToomas Soome  */
106*a1bf3f78SToomas Soome void
107*a1bf3f78SToomas Soome ficlVmDestroy(ficlVm *vm)
108*a1bf3f78SToomas Soome {
109*a1bf3f78SToomas Soome 	if (vm) {
110*a1bf3f78SToomas Soome 		ficlFree(vm->dataStack);
111*a1bf3f78SToomas Soome 		ficlFree(vm->returnStack);
112*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
113*a1bf3f78SToomas Soome 		ficlFree(vm->floatStack);
114*a1bf3f78SToomas Soome #endif
115*a1bf3f78SToomas Soome 		ficlFree(vm);
116*a1bf3f78SToomas Soome 	}
117*a1bf3f78SToomas Soome }
118*a1bf3f78SToomas Soome 
119*a1bf3f78SToomas Soome /*
120*a1bf3f78SToomas Soome  * v m E x e c u t e
121*a1bf3f78SToomas Soome  * Sets up the specified word to be run by the inner interpreter.
122*a1bf3f78SToomas Soome  * Executes the word's code part immediately, but in the case of
123*a1bf3f78SToomas Soome  * colon definition, the definition itself needs the inner interpreter
124*a1bf3f78SToomas Soome  * to complete. This does not happen until control reaches ficlExec
125*a1bf3f78SToomas Soome  */
126*a1bf3f78SToomas Soome void
127*a1bf3f78SToomas Soome ficlVmExecuteWord(ficlVm *vm, ficlWord *pWord)
128*a1bf3f78SToomas Soome {
129*a1bf3f78SToomas Soome 	ficlVmInnerLoop(vm, pWord);
130*a1bf3f78SToomas Soome }
131*a1bf3f78SToomas Soome 
132*a1bf3f78SToomas Soome static void
133*a1bf3f78SToomas Soome ficlVmOptimizeJumpToJump(ficlVm *vm, ficlIp ip)
134*a1bf3f78SToomas Soome {
135*a1bf3f78SToomas Soome 	ficlIp destination;
136*a1bf3f78SToomas Soome 	switch ((ficlInstruction)(*ip)) {
137*a1bf3f78SToomas Soome 	case ficlInstructionBranchParenWithCheck:
138*a1bf3f78SToomas Soome 		*ip = (ficlWord *)ficlInstructionBranchParen;
139*a1bf3f78SToomas Soome 		goto RUNTIME_FIXUP;
140*a1bf3f78SToomas Soome 
141*a1bf3f78SToomas Soome 	case ficlInstructionBranch0ParenWithCheck:
142*a1bf3f78SToomas Soome 		*ip = (ficlWord *)ficlInstructionBranch0Paren;
143*a1bf3f78SToomas Soome RUNTIME_FIXUP:
144*a1bf3f78SToomas Soome 		ip++;
145*a1bf3f78SToomas Soome 		destination = ip + *(ficlInteger *)ip;
146*a1bf3f78SToomas Soome 		switch ((ficlInstruction)*destination) {
147*a1bf3f78SToomas Soome 		case ficlInstructionBranchParenWithCheck:
148*a1bf3f78SToomas Soome 			/* preoptimize where we're jumping to */
149*a1bf3f78SToomas Soome 			ficlVmOptimizeJumpToJump(vm, destination);
150*a1bf3f78SToomas Soome 		case ficlInstructionBranchParen:
151*a1bf3f78SToomas Soome 			destination++;
152*a1bf3f78SToomas Soome 			destination += *(ficlInteger *)destination;
153*a1bf3f78SToomas Soome 			*ip = (ficlWord *)(destination - ip);
154*a1bf3f78SToomas Soome 		break;
155*a1bf3f78SToomas Soome 		}
156*a1bf3f78SToomas Soome 	}
157*a1bf3f78SToomas Soome }
158*a1bf3f78SToomas Soome 
159*a1bf3f78SToomas Soome /*
160*a1bf3f78SToomas Soome  * v m I n n e r L o o p
161*a1bf3f78SToomas Soome  * the mysterious inner interpreter...
162*a1bf3f78SToomas Soome  * This loop is the address interpreter that makes colon definitions
163*a1bf3f78SToomas Soome  * work. Upon entry, it assumes that the IP points to an entry in
164*a1bf3f78SToomas Soome  * a definition (the body of a colon word). It runs one word at a time
165*a1bf3f78SToomas Soome  * until something does vmThrow. The catcher for this is expected to exist
166*a1bf3f78SToomas Soome  * in the calling code.
167*a1bf3f78SToomas Soome  * vmThrow gets you out of this loop with a longjmp()
168*a1bf3f78SToomas Soome  */
169*a1bf3f78SToomas Soome 
170*a1bf3f78SToomas Soome #if FICL_ROBUST <= 1
171*a1bf3f78SToomas Soome 	/* turn off stack checking for primitives */
172*a1bf3f78SToomas Soome #define	_CHECK_STACK(stack, top, pop, push)
173*a1bf3f78SToomas Soome #else
174*a1bf3f78SToomas Soome 
175*a1bf3f78SToomas Soome #define	_CHECK_STACK(stack, top, pop, push)	\
176*a1bf3f78SToomas Soome 	ficlStackCheckNospill(stack, top, pop, push)
177*a1bf3f78SToomas Soome 
178*a1bf3f78SToomas Soome FICL_PLATFORM_INLINE void
179*a1bf3f78SToomas Soome ficlStackCheckNospill(ficlStack *stack, ficlCell *top, int popCells,
180*a1bf3f78SToomas Soome     int pushCells)
181*a1bf3f78SToomas Soome {
182*a1bf3f78SToomas Soome 	/*
183*a1bf3f78SToomas Soome 	 * Why save and restore stack->top?
184*a1bf3f78SToomas Soome 	 * So the simple act of stack checking doesn't force a "register" spill,
185*a1bf3f78SToomas Soome 	 * which might mask bugs (places where we needed to spill but didn't).
186*a1bf3f78SToomas Soome 	 * --lch
187*a1bf3f78SToomas Soome 	 */
188*a1bf3f78SToomas Soome 	ficlCell *oldTop = stack->top;
189*a1bf3f78SToomas Soome 	stack->top = top;
190*a1bf3f78SToomas Soome 	ficlStackCheck(stack, popCells, pushCells);
191*a1bf3f78SToomas Soome 	stack->top = oldTop;
192*a1bf3f78SToomas Soome }
193*a1bf3f78SToomas Soome 
194*a1bf3f78SToomas Soome #endif /* FICL_ROBUST <= 1 */
195*a1bf3f78SToomas Soome 
196*a1bf3f78SToomas Soome #define	CHECK_STACK(pop, push)		\
197*a1bf3f78SToomas Soome 	_CHECK_STACK(vm->dataStack, dataTop, pop, push)
198*a1bf3f78SToomas Soome #define	CHECK_FLOAT_STACK(pop, push)	\
199*a1bf3f78SToomas Soome 	_CHECK_STACK(vm->floatStack, floatTop, pop, push)
200*a1bf3f78SToomas Soome #define	CHECK_RETURN_STACK(pop, push)	\
201*a1bf3f78SToomas Soome 	_CHECK_STACK(vm->returnStack, returnTop, pop, push)
202*a1bf3f78SToomas Soome 
203*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
204*a1bf3f78SToomas Soome #define	FLOAT_LOCAL_VARIABLE_SPILL	\
205*a1bf3f78SToomas Soome 	vm->floatStack->top = floatTop;
206*a1bf3f78SToomas Soome #define	FLOAT_LOCAL_VARIABLE_REFILL	\
207*a1bf3f78SToomas Soome 	floatTop = vm->floatStack->top;
208*a1bf3f78SToomas Soome #else
209*a1bf3f78SToomas Soome #define	FLOAT_LOCAL_VARIABLE_SPILL
210*a1bf3f78SToomas Soome #define	FLOAT_LOCAL_VARIABLE_REFILL
211*a1bf3f78SToomas Soome #endif  /* FICL_WANT_FLOAT */
212*a1bf3f78SToomas Soome 
213*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS
214*a1bf3f78SToomas Soome #define	LOCALS_LOCAL_VARIABLE_SPILL	\
215*a1bf3f78SToomas Soome 	vm->returnStack->frame = frame;
216*a1bf3f78SToomas Soome #define	LOCALS_LOCAL_VARIABLE_REFILL \
217*a1bf3f78SToomas Soome 	frame = vm->returnStack->frame;
218*a1bf3f78SToomas Soome #else
219*a1bf3f78SToomas Soome #define	LOCALS_LOCAL_VARIABLE_SPILL
220*a1bf3f78SToomas Soome #define	LOCALS_LOCAL_VARIABLE_REFILL
221*a1bf3f78SToomas Soome #endif  /* FICL_WANT_FLOAT */
222*a1bf3f78SToomas Soome 
223*a1bf3f78SToomas Soome #define	LOCAL_VARIABLE_SPILL	\
224*a1bf3f78SToomas Soome 		vm->ip = (ficlIp)ip;	\
225*a1bf3f78SToomas Soome 		vm->dataStack->top = dataTop;	\
226*a1bf3f78SToomas Soome 		vm->returnStack->top = returnTop;	\
227*a1bf3f78SToomas Soome 		FLOAT_LOCAL_VARIABLE_SPILL \
228*a1bf3f78SToomas Soome 		LOCALS_LOCAL_VARIABLE_SPILL
229*a1bf3f78SToomas Soome 
230*a1bf3f78SToomas Soome #define	LOCAL_VARIABLE_REFILL	\
231*a1bf3f78SToomas Soome 		ip = (ficlInstruction *)vm->ip; \
232*a1bf3f78SToomas Soome 		dataTop = vm->dataStack->top;	\
233*a1bf3f78SToomas Soome 		returnTop = vm->returnStack->top;	\
234*a1bf3f78SToomas Soome 		FLOAT_LOCAL_VARIABLE_REFILL	\
235*a1bf3f78SToomas Soome 		LOCALS_LOCAL_VARIABLE_REFILL
236*a1bf3f78SToomas Soome 
237*a1bf3f78SToomas Soome void
238*a1bf3f78SToomas Soome ficlVmInnerLoop(ficlVm *vm, ficlWord *fw)
239*a1bf3f78SToomas Soome {
240*a1bf3f78SToomas Soome 	register ficlInstruction *ip;
241*a1bf3f78SToomas Soome 	register ficlCell *dataTop;
242*a1bf3f78SToomas Soome 	register ficlCell *returnTop;
243*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
244*a1bf3f78SToomas Soome 	register ficlCell *floatTop;
245*a1bf3f78SToomas Soome 	ficlFloat f;
246*a1bf3f78SToomas Soome #endif  /* FICL_WANT_FLOAT */
247*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS
248*a1bf3f78SToomas Soome 	register ficlCell *frame;
249*a1bf3f78SToomas Soome #endif  /* FICL_WANT_LOCALS */
250*a1bf3f78SToomas Soome 	jmp_buf *oldExceptionHandler;
251*a1bf3f78SToomas Soome 	jmp_buf exceptionHandler;
252*a1bf3f78SToomas Soome 	int except;
253*a1bf3f78SToomas Soome 	int once;
254*a1bf3f78SToomas Soome 	int count;
255*a1bf3f78SToomas Soome 	ficlInstruction instruction;
256*a1bf3f78SToomas Soome 	ficlInteger i;
257*a1bf3f78SToomas Soome 	ficlUnsigned u;
258*a1bf3f78SToomas Soome 	ficlCell c;
259*a1bf3f78SToomas Soome 	ficlCountedString *s;
260*a1bf3f78SToomas Soome 	ficlCell *cell;
261*a1bf3f78SToomas Soome 	char *cp;
262*a1bf3f78SToomas Soome 
263*a1bf3f78SToomas Soome 	once = (fw != NULL);
264*a1bf3f78SToomas Soome 	if (once)
265*a1bf3f78SToomas Soome 		count = 1;
266*a1bf3f78SToomas Soome 
267*a1bf3f78SToomas Soome 	oldExceptionHandler = vm->exceptionHandler;
268*a1bf3f78SToomas Soome 	/* This has to come before the setjmp! */
269*a1bf3f78SToomas Soome 	vm->exceptionHandler = &exceptionHandler;
270*a1bf3f78SToomas Soome 	except = setjmp(exceptionHandler);
271*a1bf3f78SToomas Soome 
272*a1bf3f78SToomas Soome 	LOCAL_VARIABLE_REFILL;
273*a1bf3f78SToomas Soome 
274*a1bf3f78SToomas Soome 	if (except) {
275*a1bf3f78SToomas Soome 		LOCAL_VARIABLE_SPILL;
276*a1bf3f78SToomas Soome 		vm->exceptionHandler = oldExceptionHandler;
277*a1bf3f78SToomas Soome 		ficlVmThrow(vm, except);
278*a1bf3f78SToomas Soome 	}
279*a1bf3f78SToomas Soome 
280*a1bf3f78SToomas Soome 	for (;;) {
281*a1bf3f78SToomas Soome 		if (once) {
282*a1bf3f78SToomas Soome 			if (!count--)
283*a1bf3f78SToomas Soome 				break;
284*a1bf3f78SToomas Soome 			instruction = (ficlInstruction)((void *)fw);
285*a1bf3f78SToomas Soome 		} else {
286*a1bf3f78SToomas Soome 			instruction = *ip++;
287*a1bf3f78SToomas Soome 			fw = (ficlWord *)instruction;
288*a1bf3f78SToomas Soome 		}
289*a1bf3f78SToomas Soome 
290*a1bf3f78SToomas Soome AGAIN:
291*a1bf3f78SToomas Soome 		switch (instruction) {
292*a1bf3f78SToomas Soome 		case ficlInstructionInvalid:
293*a1bf3f78SToomas Soome 			ficlVmThrowError(vm,
294*a1bf3f78SToomas Soome 			    "Error: NULL instruction executed!");
295*a1bf3f78SToomas Soome 		return;
296*a1bf3f78SToomas Soome 
297*a1bf3f78SToomas Soome 		case ficlInstruction1:
298*a1bf3f78SToomas Soome 		case ficlInstruction2:
299*a1bf3f78SToomas Soome 		case ficlInstruction3:
300*a1bf3f78SToomas Soome 		case ficlInstruction4:
301*a1bf3f78SToomas Soome 		case ficlInstruction5:
302*a1bf3f78SToomas Soome 		case ficlInstruction6:
303*a1bf3f78SToomas Soome 		case ficlInstruction7:
304*a1bf3f78SToomas Soome 		case ficlInstruction8:
305*a1bf3f78SToomas Soome 		case ficlInstruction9:
306*a1bf3f78SToomas Soome 		case ficlInstruction10:
307*a1bf3f78SToomas Soome 		case ficlInstruction11:
308*a1bf3f78SToomas Soome 		case ficlInstruction12:
309*a1bf3f78SToomas Soome 		case ficlInstruction13:
310*a1bf3f78SToomas Soome 		case ficlInstruction14:
311*a1bf3f78SToomas Soome 		case ficlInstruction15:
312*a1bf3f78SToomas Soome 		case ficlInstruction16:
313*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
314*a1bf3f78SToomas Soome 			(++dataTop)->i = instruction;
315*a1bf3f78SToomas Soome 		continue;
316*a1bf3f78SToomas Soome 
317*a1bf3f78SToomas Soome 		case ficlInstruction0:
318*a1bf3f78SToomas Soome 		case ficlInstructionNeg1:
319*a1bf3f78SToomas Soome 		case ficlInstructionNeg2:
320*a1bf3f78SToomas Soome 		case ficlInstructionNeg3:
321*a1bf3f78SToomas Soome 		case ficlInstructionNeg4:
322*a1bf3f78SToomas Soome 		case ficlInstructionNeg5:
323*a1bf3f78SToomas Soome 		case ficlInstructionNeg6:
324*a1bf3f78SToomas Soome 		case ficlInstructionNeg7:
325*a1bf3f78SToomas Soome 		case ficlInstructionNeg8:
326*a1bf3f78SToomas Soome 		case ficlInstructionNeg9:
327*a1bf3f78SToomas Soome 		case ficlInstructionNeg10:
328*a1bf3f78SToomas Soome 		case ficlInstructionNeg11:
329*a1bf3f78SToomas Soome 		case ficlInstructionNeg12:
330*a1bf3f78SToomas Soome 		case ficlInstructionNeg13:
331*a1bf3f78SToomas Soome 		case ficlInstructionNeg14:
332*a1bf3f78SToomas Soome 		case ficlInstructionNeg15:
333*a1bf3f78SToomas Soome 		case ficlInstructionNeg16:
334*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
335*a1bf3f78SToomas Soome 			(++dataTop)->i = ficlInstruction0 - instruction;
336*a1bf3f78SToomas Soome 		continue;
337*a1bf3f78SToomas Soome 
338*a1bf3f78SToomas Soome 		/*
339*a1bf3f78SToomas Soome 		 * stringlit: Fetch the count from the dictionary, then push
340*a1bf3f78SToomas Soome 		 * the address and count on the stack. Finally, update ip to
341*a1bf3f78SToomas Soome 		 * point to the first aligned address after the string text.
342*a1bf3f78SToomas Soome 		 */
343*a1bf3f78SToomas Soome 		case ficlInstructionStringLiteralParen: {
344*a1bf3f78SToomas Soome 			ficlUnsigned8 length;
345*a1bf3f78SToomas Soome 			CHECK_STACK(0, 2);
346*a1bf3f78SToomas Soome 
347*a1bf3f78SToomas Soome 			s = (ficlCountedString *)(ip);
348*a1bf3f78SToomas Soome 			length = s->length;
349*a1bf3f78SToomas Soome 			cp = s->text;
350*a1bf3f78SToomas Soome 			(++dataTop)->p = cp;
351*a1bf3f78SToomas Soome 			(++dataTop)->i = length;
352*a1bf3f78SToomas Soome 
353*a1bf3f78SToomas Soome 			cp += length + 1;
354*a1bf3f78SToomas Soome 			cp = ficlAlignPointer(cp);
355*a1bf3f78SToomas Soome 			ip = (void *)cp;
356*a1bf3f78SToomas Soome 		continue;
357*a1bf3f78SToomas Soome 		}
358*a1bf3f78SToomas Soome 
359*a1bf3f78SToomas Soome 		case ficlInstructionCStringLiteralParen:
360*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
361*a1bf3f78SToomas Soome 
362*a1bf3f78SToomas Soome 			s = (ficlCountedString *)(ip);
363*a1bf3f78SToomas Soome 			cp = s->text + s->length + 1;
364*a1bf3f78SToomas Soome 			cp = ficlAlignPointer(cp);
365*a1bf3f78SToomas Soome 			ip = (void *)cp;
366*a1bf3f78SToomas Soome 			(++dataTop)->p = s;
367*a1bf3f78SToomas Soome 		continue;
368*a1bf3f78SToomas Soome 
369*a1bf3f78SToomas Soome #if FICL_WANT_OPTIMIZE == FICL_OPTIMIZE_FOR_SIZE
370*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
371*a1bf3f78SToomas Soome FLOAT_PUSH_CELL_POINTER_DOUBLE_MINIPROC:
372*a1bf3f78SToomas Soome 			*++floatTop = cell[1];
373*a1bf3f78SToomas Soome 			/* intentional fall-through */
374*a1bf3f78SToomas Soome FLOAT_PUSH_CELL_POINTER_MINIPROC:
375*a1bf3f78SToomas Soome 			*++floatTop = cell[0];
376*a1bf3f78SToomas Soome 		continue;
377*a1bf3f78SToomas Soome 
378*a1bf3f78SToomas Soome FLOAT_POP_CELL_POINTER_MINIPROC:
379*a1bf3f78SToomas Soome 			cell[0] = *floatTop--;
380*a1bf3f78SToomas Soome 		continue;
381*a1bf3f78SToomas Soome 
382*a1bf3f78SToomas Soome FLOAT_POP_CELL_POINTER_DOUBLE_MINIPROC:
383*a1bf3f78SToomas Soome 			cell[0] = *floatTop--;
384*a1bf3f78SToomas Soome 			cell[1] = *floatTop--;
385*a1bf3f78SToomas Soome 		continue;
386*a1bf3f78SToomas Soome 
387*a1bf3f78SToomas Soome #define	FLOAT_PUSH_CELL_POINTER_DOUBLE(cp)	\
388*a1bf3f78SToomas Soome 	cell = (cp); goto FLOAT_PUSH_CELL_POINTER_DOUBLE_MINIPROC
389*a1bf3f78SToomas Soome #define	FLOAT_PUSH_CELL_POINTER(cp)		\
390*a1bf3f78SToomas Soome 	cell = (cp); goto FLOAT_PUSH_CELL_POINTER_MINIPROC
391*a1bf3f78SToomas Soome #define	FLOAT_POP_CELL_POINTER_DOUBLE(cp)	\
392*a1bf3f78SToomas Soome 	cell = (cp); goto FLOAT_POP_CELL_POINTER_DOUBLE_MINIPROC
393*a1bf3f78SToomas Soome #define	FLOAT_POP_CELL_POINTER(cp)		\
394*a1bf3f78SToomas Soome 	cell = (cp); goto FLOAT_POP_CELL_POINTER_MINIPROC
395*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */
396*a1bf3f78SToomas Soome 
397*a1bf3f78SToomas Soome 		/*
398*a1bf3f78SToomas Soome 		 * Think of these as little mini-procedures.
399*a1bf3f78SToomas Soome 		 * --lch
400*a1bf3f78SToomas Soome 		 */
401*a1bf3f78SToomas Soome PUSH_CELL_POINTER_DOUBLE_MINIPROC:
402*a1bf3f78SToomas Soome 			*++dataTop = cell[1];
403*a1bf3f78SToomas Soome 			/* intentional fall-through */
404*a1bf3f78SToomas Soome PUSH_CELL_POINTER_MINIPROC:
405*a1bf3f78SToomas Soome 			*++dataTop = cell[0];
406*a1bf3f78SToomas Soome 		continue;
407*a1bf3f78SToomas Soome 
408*a1bf3f78SToomas Soome POP_CELL_POINTER_MINIPROC:
409*a1bf3f78SToomas Soome 			cell[0] = *dataTop--;
410*a1bf3f78SToomas Soome 		continue;
411*a1bf3f78SToomas Soome POP_CELL_POINTER_DOUBLE_MINIPROC:
412*a1bf3f78SToomas Soome 			cell[0] = *dataTop--;
413*a1bf3f78SToomas Soome 			cell[1] = *dataTop--;
414*a1bf3f78SToomas Soome 		continue;
415*a1bf3f78SToomas Soome 
416*a1bf3f78SToomas Soome #define	PUSH_CELL_POINTER_DOUBLE(cp)	\
417*a1bf3f78SToomas Soome 	cell = (cp); goto PUSH_CELL_POINTER_DOUBLE_MINIPROC
418*a1bf3f78SToomas Soome #define	PUSH_CELL_POINTER(cp)		\
419*a1bf3f78SToomas Soome 	cell = (cp); goto PUSH_CELL_POINTER_MINIPROC
420*a1bf3f78SToomas Soome #define	POP_CELL_POINTER_DOUBLE(cp)	\
421*a1bf3f78SToomas Soome 	cell = (cp); goto POP_CELL_POINTER_DOUBLE_MINIPROC
422*a1bf3f78SToomas Soome #define	POP_CELL_POINTER(cp)		\
423*a1bf3f78SToomas Soome 	cell = (cp); goto POP_CELL_POINTER_MINIPROC
424*a1bf3f78SToomas Soome 
425*a1bf3f78SToomas Soome BRANCH_MINIPROC:
426*a1bf3f78SToomas Soome 			ip += *(ficlInteger *)ip;
427*a1bf3f78SToomas Soome 		continue;
428*a1bf3f78SToomas Soome 
429*a1bf3f78SToomas Soome #define	BRANCH()	goto BRANCH_MINIPROC
430*a1bf3f78SToomas Soome 
431*a1bf3f78SToomas Soome EXIT_FUNCTION_MINIPROC:
432*a1bf3f78SToomas Soome 			ip = (ficlInstruction *)((returnTop--)->p);
433*a1bf3f78SToomas Soome 				continue;
434*a1bf3f78SToomas Soome 
435*a1bf3f78SToomas Soome #define	EXIT_FUNCTION	goto EXIT_FUNCTION_MINIPROC
436*a1bf3f78SToomas Soome 
437*a1bf3f78SToomas Soome #else /* FICL_WANT_SIZE */
438*a1bf3f78SToomas Soome 
439*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
440*a1bf3f78SToomas Soome #define	FLOAT_PUSH_CELL_POINTER_DOUBLE(cp)	\
441*a1bf3f78SToomas Soome 	cell = (cp); *++floatTop = cell[1]; *++floatTop = *cell; continue
442*a1bf3f78SToomas Soome #define	FLOAT_PUSH_CELL_POINTER(cp)		\
443*a1bf3f78SToomas Soome 	cell = (cp); *++floatTop = *cell; continue
444*a1bf3f78SToomas Soome #define	FLOAT_POP_CELL_POINTER_DOUBLE(cp)	\
445*a1bf3f78SToomas Soome 	cell = (cp); *cell = *floatTop--; cell[1] = *floatTop--; continue
446*a1bf3f78SToomas Soome #define	FLOAT_POP_CELL_POINTER(cp)		\
447*a1bf3f78SToomas Soome 	cell = (cp); *cell = *floatTop--; continue
448*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */
449*a1bf3f78SToomas Soome 
450*a1bf3f78SToomas Soome #define	PUSH_CELL_POINTER_DOUBLE(cp)	\
451*a1bf3f78SToomas Soome 	cell = (cp); *++dataTop = cell[1]; *++dataTop = *cell; continue
452*a1bf3f78SToomas Soome #define	PUSH_CELL_POINTER(cp)		\
453*a1bf3f78SToomas Soome 	cell = (cp); *++dataTop = *cell; continue
454*a1bf3f78SToomas Soome #define	POP_CELL_POINTER_DOUBLE(cp)	\
455*a1bf3f78SToomas Soome 	cell = (cp); *cell = *dataTop--; cell[1] = *dataTop--; continue
456*a1bf3f78SToomas Soome #define	POP_CELL_POINTER(cp)		\
457*a1bf3f78SToomas Soome 	cell = (cp); *cell = *dataTop--; continue
458*a1bf3f78SToomas Soome 
459*a1bf3f78SToomas Soome #define	BRANCH()	ip += *(ficlInteger *)ip; continue
460*a1bf3f78SToomas Soome #define	EXIT_FUNCTION()	ip = (ficlInstruction *)((returnTop--)->p); continue
461*a1bf3f78SToomas Soome 
462*a1bf3f78SToomas Soome #endif /* FICL_WANT_SIZE */
463*a1bf3f78SToomas Soome 
464*a1bf3f78SToomas Soome 
465*a1bf3f78SToomas Soome 		/*
466*a1bf3f78SToomas Soome 		 * This is the runtime for (literal). It assumes that it is
467*a1bf3f78SToomas Soome 		 * part of a colon definition, and that the next ficlCell
468*a1bf3f78SToomas Soome 		 * contains a value to be pushed on the parameter stack at
469*a1bf3f78SToomas Soome 		 * runtime. This code is compiled by "literal".
470*a1bf3f78SToomas Soome 		 */
471*a1bf3f78SToomas Soome 
472*a1bf3f78SToomas Soome 		case ficlInstructionLiteralParen:
473*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
474*a1bf3f78SToomas Soome 			(++dataTop)->i = *ip++;
475*a1bf3f78SToomas Soome 		continue;
476*a1bf3f78SToomas Soome 
477*a1bf3f78SToomas Soome 		case ficlInstruction2LiteralParen:
478*a1bf3f78SToomas Soome 			CHECK_STACK(0, 2);
479*a1bf3f78SToomas Soome 			(++dataTop)->i = ip[1];
480*a1bf3f78SToomas Soome 			(++dataTop)->i = ip[0];
481*a1bf3f78SToomas Soome 			ip += 2;
482*a1bf3f78SToomas Soome 		continue;
483*a1bf3f78SToomas Soome 
484*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS
485*a1bf3f78SToomas Soome 		/*
486*a1bf3f78SToomas Soome 		 * Link a frame on the return stack, reserving nCells of space
487*a1bf3f78SToomas Soome 		 * for locals - the value of nCells is the next ficlCell in
488*a1bf3f78SToomas Soome 		 * the instruction stream.
489*a1bf3f78SToomas Soome 		 * 1) Push frame onto returnTop
490*a1bf3f78SToomas Soome 		 * 2) frame = returnTop
491*a1bf3f78SToomas Soome 		 * 3) returnTop += nCells
492*a1bf3f78SToomas Soome 		 */
493*a1bf3f78SToomas Soome 		case ficlInstructionLinkParen: {
494*a1bf3f78SToomas Soome 			ficlInteger nCells = *ip++;
495*a1bf3f78SToomas Soome 			(++returnTop)->p = frame;
496*a1bf3f78SToomas Soome 			frame = returnTop + 1;
497*a1bf3f78SToomas Soome 			returnTop += nCells;
498*a1bf3f78SToomas Soome 		continue;
499*a1bf3f78SToomas Soome 		}
500*a1bf3f78SToomas Soome 
501*a1bf3f78SToomas Soome 		/*
502*a1bf3f78SToomas Soome 		 * Unink a stack frame previously created by stackLink
503*a1bf3f78SToomas Soome 		 * 1) dataTop = frame
504*a1bf3f78SToomas Soome 		 * 2) frame = pop()
505*a1bf3f78SToomas Soome 		 */
506*a1bf3f78SToomas Soome 		case ficlInstructionUnlinkParen:
507*a1bf3f78SToomas Soome 			returnTop = frame - 1;
508*a1bf3f78SToomas Soome 			frame = (returnTop--)->p;
509*a1bf3f78SToomas Soome 		continue;
510*a1bf3f78SToomas Soome 
511*a1bf3f78SToomas Soome 		/*
512*a1bf3f78SToomas Soome 		 * Immediate - cfa of a local while compiling - when executed,
513*a1bf3f78SToomas Soome 		 * compiles code to fetch the value of a local given the
514*a1bf3f78SToomas Soome 		 * local's index in the word's pfa
515*a1bf3f78SToomas Soome 		 */
516*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
517*a1bf3f78SToomas Soome 		case ficlInstructionGetF2LocalParen:
518*a1bf3f78SToomas Soome 			FLOAT_PUSH_CELL_POINTER_DOUBLE(frame + *ip++);
519*a1bf3f78SToomas Soome 
520*a1bf3f78SToomas Soome 		case ficlInstructionGetFLocalParen:
521*a1bf3f78SToomas Soome 			FLOAT_PUSH_CELL_POINTER(frame + *ip++);
522*a1bf3f78SToomas Soome 
523*a1bf3f78SToomas Soome 		case ficlInstructionToF2LocalParen:
524*a1bf3f78SToomas Soome 			FLOAT_POP_CELL_POINTER_DOUBLE(frame + *ip++);
525*a1bf3f78SToomas Soome 
526*a1bf3f78SToomas Soome 		case ficlInstructionToFLocalParen:
527*a1bf3f78SToomas Soome 			FLOAT_POP_CELL_POINTER(frame + *ip++);
528*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */
529*a1bf3f78SToomas Soome 
530*a1bf3f78SToomas Soome 		case ficlInstructionGet2LocalParen:
531*a1bf3f78SToomas Soome 			PUSH_CELL_POINTER_DOUBLE(frame + *ip++);
532*a1bf3f78SToomas Soome 
533*a1bf3f78SToomas Soome 		case ficlInstructionGetLocalParen:
534*a1bf3f78SToomas Soome 			PUSH_CELL_POINTER(frame + *ip++);
535*a1bf3f78SToomas Soome 
536*a1bf3f78SToomas Soome 		/*
537*a1bf3f78SToomas Soome 		 * Immediate - cfa of a local while compiling - when executed,
538*a1bf3f78SToomas Soome 		 * compiles code to store the value of a local given the
539*a1bf3f78SToomas Soome 		 * local's index in the word's pfa
540*a1bf3f78SToomas Soome 		 */
541*a1bf3f78SToomas Soome 
542*a1bf3f78SToomas Soome 		case ficlInstructionTo2LocalParen:
543*a1bf3f78SToomas Soome 			POP_CELL_POINTER_DOUBLE(frame + *ip++);
544*a1bf3f78SToomas Soome 
545*a1bf3f78SToomas Soome 		case ficlInstructionToLocalParen:
546*a1bf3f78SToomas Soome 			POP_CELL_POINTER(frame + *ip++);
547*a1bf3f78SToomas Soome 
548*a1bf3f78SToomas Soome 		/*
549*a1bf3f78SToomas Soome 		 * Silly little minor optimizations.
550*a1bf3f78SToomas Soome 		 * --lch
551*a1bf3f78SToomas Soome 		 */
552*a1bf3f78SToomas Soome 		case ficlInstructionGetLocal0:
553*a1bf3f78SToomas Soome 			PUSH_CELL_POINTER(frame);
554*a1bf3f78SToomas Soome 
555*a1bf3f78SToomas Soome 		case ficlInstructionGetLocal1:
556*a1bf3f78SToomas Soome 			PUSH_CELL_POINTER(frame + 1);
557*a1bf3f78SToomas Soome 
558*a1bf3f78SToomas Soome 		case ficlInstructionGet2Local0:
559*a1bf3f78SToomas Soome 			PUSH_CELL_POINTER_DOUBLE(frame);
560*a1bf3f78SToomas Soome 
561*a1bf3f78SToomas Soome 		case ficlInstructionToLocal0:
562*a1bf3f78SToomas Soome 			POP_CELL_POINTER(frame);
563*a1bf3f78SToomas Soome 
564*a1bf3f78SToomas Soome 		case ficlInstructionToLocal1:
565*a1bf3f78SToomas Soome 			POP_CELL_POINTER(frame + 1);
566*a1bf3f78SToomas Soome 
567*a1bf3f78SToomas Soome 		case ficlInstructionTo2Local0:
568*a1bf3f78SToomas Soome 			POP_CELL_POINTER_DOUBLE(frame);
569*a1bf3f78SToomas Soome 
570*a1bf3f78SToomas Soome #endif /* FICL_WANT_LOCALS */
571*a1bf3f78SToomas Soome 
572*a1bf3f78SToomas Soome 		case ficlInstructionPlus:
573*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
574*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
575*a1bf3f78SToomas Soome 			dataTop->i += i;
576*a1bf3f78SToomas Soome 		continue;
577*a1bf3f78SToomas Soome 
578*a1bf3f78SToomas Soome 		case ficlInstructionMinus:
579*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
580*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
581*a1bf3f78SToomas Soome 			dataTop->i -= i;
582*a1bf3f78SToomas Soome 		continue;
583*a1bf3f78SToomas Soome 
584*a1bf3f78SToomas Soome 		case ficlInstruction1Plus:
585*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
586*a1bf3f78SToomas Soome 			dataTop->i++;
587*a1bf3f78SToomas Soome 		continue;
588*a1bf3f78SToomas Soome 
589*a1bf3f78SToomas Soome 		case ficlInstruction1Minus:
590*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
591*a1bf3f78SToomas Soome 			dataTop->i--;
592*a1bf3f78SToomas Soome 		continue;
593*a1bf3f78SToomas Soome 
594*a1bf3f78SToomas Soome 		case ficlInstruction2Plus:
595*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
596*a1bf3f78SToomas Soome 			dataTop->i += 2;
597*a1bf3f78SToomas Soome 		continue;
598*a1bf3f78SToomas Soome 
599*a1bf3f78SToomas Soome 		case ficlInstruction2Minus:
600*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
601*a1bf3f78SToomas Soome 			dataTop->i -= 2;
602*a1bf3f78SToomas Soome 		continue;
603*a1bf3f78SToomas Soome 
604*a1bf3f78SToomas Soome 		case ficlInstructionDup: {
605*a1bf3f78SToomas Soome 			ficlInteger i = dataTop->i;
606*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
607*a1bf3f78SToomas Soome 			(++dataTop)->i = i;
608*a1bf3f78SToomas Soome 			continue;
609*a1bf3f78SToomas Soome 		}
610*a1bf3f78SToomas Soome 
611*a1bf3f78SToomas Soome 		case ficlInstructionQuestionDup:
612*a1bf3f78SToomas Soome 			CHECK_STACK(1, 2);
613*a1bf3f78SToomas Soome 
614*a1bf3f78SToomas Soome 			if (dataTop->i != 0) {
615*a1bf3f78SToomas Soome 				dataTop[1] = dataTop[0];
616*a1bf3f78SToomas Soome 				dataTop++;
617*a1bf3f78SToomas Soome 			}
618*a1bf3f78SToomas Soome 
619*a1bf3f78SToomas Soome 		continue;
620*a1bf3f78SToomas Soome 
621*a1bf3f78SToomas Soome 		case ficlInstructionSwap: {
622*a1bf3f78SToomas Soome 			ficlCell swap;
623*a1bf3f78SToomas Soome 			CHECK_STACK(2, 2);
624*a1bf3f78SToomas Soome 			swap = dataTop[0];
625*a1bf3f78SToomas Soome 			dataTop[0] = dataTop[-1];
626*a1bf3f78SToomas Soome 			dataTop[-1] = swap;
627*a1bf3f78SToomas Soome 		}
628*a1bf3f78SToomas Soome 		continue;
629*a1bf3f78SToomas Soome 
630*a1bf3f78SToomas Soome 		case ficlInstructionDrop:
631*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
632*a1bf3f78SToomas Soome 			dataTop--;
633*a1bf3f78SToomas Soome 		continue;
634*a1bf3f78SToomas Soome 
635*a1bf3f78SToomas Soome 		case ficlInstruction2Drop:
636*a1bf3f78SToomas Soome 			CHECK_STACK(2, 0);
637*a1bf3f78SToomas Soome 			dataTop -= 2;
638*a1bf3f78SToomas Soome 		continue;
639*a1bf3f78SToomas Soome 
640*a1bf3f78SToomas Soome 		case ficlInstruction2Dup:
641*a1bf3f78SToomas Soome 			CHECK_STACK(2, 4);
642*a1bf3f78SToomas Soome 			dataTop[1] = dataTop[-1];
643*a1bf3f78SToomas Soome 			dataTop[2] = *dataTop;
644*a1bf3f78SToomas Soome 			dataTop += 2;
645*a1bf3f78SToomas Soome 		continue;
646*a1bf3f78SToomas Soome 
647*a1bf3f78SToomas Soome 		case ficlInstructionOver:
648*a1bf3f78SToomas Soome 			CHECK_STACK(2, 3);
649*a1bf3f78SToomas Soome 			dataTop[1] = dataTop[-1];
650*a1bf3f78SToomas Soome 			dataTop++;
651*a1bf3f78SToomas Soome 		continue;
652*a1bf3f78SToomas Soome 
653*a1bf3f78SToomas Soome 		case ficlInstruction2Over:
654*a1bf3f78SToomas Soome 			CHECK_STACK(4, 6);
655*a1bf3f78SToomas Soome 			dataTop[1] = dataTop[-3];
656*a1bf3f78SToomas Soome 			dataTop[2] = dataTop[-2];
657*a1bf3f78SToomas Soome 			dataTop += 2;
658*a1bf3f78SToomas Soome 		continue;
659*a1bf3f78SToomas Soome 
660*a1bf3f78SToomas Soome 		case ficlInstructionPick:
661*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
662*a1bf3f78SToomas Soome 			i = dataTop->i;
663*a1bf3f78SToomas Soome 			if (i < 0)
664*a1bf3f78SToomas Soome 				continue;
665*a1bf3f78SToomas Soome 			CHECK_STACK(i + 2, i + 3);
666*a1bf3f78SToomas Soome 			*dataTop = dataTop[-i - 1];
667*a1bf3f78SToomas Soome 		continue;
668*a1bf3f78SToomas Soome 
669*a1bf3f78SToomas Soome 		/*
670*a1bf3f78SToomas Soome 		 * Do stack rot.
671*a1bf3f78SToomas Soome 		 * rot ( 1 2 3  -- 2 3 1 )
672*a1bf3f78SToomas Soome 		 */
673*a1bf3f78SToomas Soome 		case ficlInstructionRot:
674*a1bf3f78SToomas Soome 			i = 2;
675*a1bf3f78SToomas Soome 		goto ROLL;
676*a1bf3f78SToomas Soome 
677*a1bf3f78SToomas Soome 		/*
678*a1bf3f78SToomas Soome 		 * Do stack roll.
679*a1bf3f78SToomas Soome 		 * roll ( n -- )
680*a1bf3f78SToomas Soome 		 */
681*a1bf3f78SToomas Soome 		case ficlInstructionRoll:
682*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
683*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
684*a1bf3f78SToomas Soome 
685*a1bf3f78SToomas Soome 			if (i < 1)
686*a1bf3f78SToomas Soome 				continue;
687*a1bf3f78SToomas Soome 
688*a1bf3f78SToomas Soome ROLL:
689*a1bf3f78SToomas Soome 			CHECK_STACK(i+1, i+2);
690*a1bf3f78SToomas Soome 			c = dataTop[-i];
691*a1bf3f78SToomas Soome 			memmove(dataTop - i, dataTop - (i - 1),
692*a1bf3f78SToomas Soome 			    i * sizeof (ficlCell));
693*a1bf3f78SToomas Soome 			*dataTop = c;
694*a1bf3f78SToomas Soome 		continue;
695*a1bf3f78SToomas Soome 
696*a1bf3f78SToomas Soome 		/*
697*a1bf3f78SToomas Soome 		 * Do stack -rot.
698*a1bf3f78SToomas Soome 		 * -rot ( 1 2 3  -- 3 1 2 )
699*a1bf3f78SToomas Soome 		 */
700*a1bf3f78SToomas Soome 		case ficlInstructionMinusRot:
701*a1bf3f78SToomas Soome 			i = 2;
702*a1bf3f78SToomas Soome 		goto MINUSROLL;
703*a1bf3f78SToomas Soome 
704*a1bf3f78SToomas Soome 		/*
705*a1bf3f78SToomas Soome 		 * Do stack -roll.
706*a1bf3f78SToomas Soome 		 * -roll ( n -- )
707*a1bf3f78SToomas Soome 		 */
708*a1bf3f78SToomas Soome 		case ficlInstructionMinusRoll:
709*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
710*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
711*a1bf3f78SToomas Soome 
712*a1bf3f78SToomas Soome 			if (i < 1)
713*a1bf3f78SToomas Soome 				continue;
714*a1bf3f78SToomas Soome 
715*a1bf3f78SToomas Soome MINUSROLL:
716*a1bf3f78SToomas Soome 			CHECK_STACK(i+1, i+2);
717*a1bf3f78SToomas Soome 			c = *dataTop;
718*a1bf3f78SToomas Soome 			memmove(dataTop - (i - 1), dataTop - i,
719*a1bf3f78SToomas Soome 			    i * sizeof (ficlCell));
720*a1bf3f78SToomas Soome 			dataTop[-i] = c;
721*a1bf3f78SToomas Soome 
722*a1bf3f78SToomas Soome 		continue;
723*a1bf3f78SToomas Soome 
724*a1bf3f78SToomas Soome 		/*
725*a1bf3f78SToomas Soome 		 * Do stack 2swap
726*a1bf3f78SToomas Soome 		 * 2swap ( 1 2 3 4  -- 3 4 1 2 )
727*a1bf3f78SToomas Soome 		 */
728*a1bf3f78SToomas Soome 		case ficlInstruction2Swap: {
729*a1bf3f78SToomas Soome 			ficlCell c2;
730*a1bf3f78SToomas Soome 			CHECK_STACK(4, 4);
731*a1bf3f78SToomas Soome 
732*a1bf3f78SToomas Soome 			c = *dataTop;
733*a1bf3f78SToomas Soome 			c2 = dataTop[-1];
734*a1bf3f78SToomas Soome 
735*a1bf3f78SToomas Soome 			*dataTop = dataTop[-2];
736*a1bf3f78SToomas Soome 			dataTop[-1] = dataTop[-3];
737*a1bf3f78SToomas Soome 
738*a1bf3f78SToomas Soome 			dataTop[-2] = c;
739*a1bf3f78SToomas Soome 			dataTop[-3] = c2;
740*a1bf3f78SToomas Soome 		continue;
741*a1bf3f78SToomas Soome 		}
742*a1bf3f78SToomas Soome 
743*a1bf3f78SToomas Soome 		case ficlInstructionPlusStore: {
744*a1bf3f78SToomas Soome 			ficlCell *cell;
745*a1bf3f78SToomas Soome 			CHECK_STACK(2, 0);
746*a1bf3f78SToomas Soome 			cell = (ficlCell *)(dataTop--)->p;
747*a1bf3f78SToomas Soome 			cell->i += (dataTop--)->i;
748*a1bf3f78SToomas Soome 		continue;
749*a1bf3f78SToomas Soome 		}
750*a1bf3f78SToomas Soome 
751*a1bf3f78SToomas Soome 		case ficlInstructionQuadFetch: {
752*a1bf3f78SToomas Soome 			ficlUnsigned32 *integer32;
753*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
754*a1bf3f78SToomas Soome 			integer32 = (ficlUnsigned32 *)dataTop->i;
755*a1bf3f78SToomas Soome 			dataTop->u = (ficlUnsigned)*integer32;
756*a1bf3f78SToomas Soome 		continue;
757*a1bf3f78SToomas Soome 		}
758*a1bf3f78SToomas Soome 
759*a1bf3f78SToomas Soome 		case ficlInstructionQuadStore: {
760*a1bf3f78SToomas Soome 			ficlUnsigned32 *integer32;
761*a1bf3f78SToomas Soome 			CHECK_STACK(2, 0);
762*a1bf3f78SToomas Soome 			integer32 = (ficlUnsigned32 *)(dataTop--)->p;
763*a1bf3f78SToomas Soome 			*integer32 = (ficlUnsigned32)((dataTop--)->u);
764*a1bf3f78SToomas Soome 		continue;
765*a1bf3f78SToomas Soome 		}
766*a1bf3f78SToomas Soome 
767*a1bf3f78SToomas Soome 		case ficlInstructionWFetch: {
768*a1bf3f78SToomas Soome 			ficlUnsigned16 *integer16;
769*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
770*a1bf3f78SToomas Soome 			integer16 = (ficlUnsigned16 *)dataTop->p;
771*a1bf3f78SToomas Soome 			dataTop->u = ((ficlUnsigned)*integer16);
772*a1bf3f78SToomas Soome 		continue;
773*a1bf3f78SToomas Soome 		}
774*a1bf3f78SToomas Soome 
775*a1bf3f78SToomas Soome 		case ficlInstructionWStore: {
776*a1bf3f78SToomas Soome 			ficlUnsigned16 *integer16;
777*a1bf3f78SToomas Soome 			CHECK_STACK(2, 0);
778*a1bf3f78SToomas Soome 			integer16 = (ficlUnsigned16 *)(dataTop--)->p;
779*a1bf3f78SToomas Soome 			*integer16 = (ficlUnsigned16)((dataTop--)->u);
780*a1bf3f78SToomas Soome 		continue;
781*a1bf3f78SToomas Soome 		}
782*a1bf3f78SToomas Soome 
783*a1bf3f78SToomas Soome 		case ficlInstructionCFetch: {
784*a1bf3f78SToomas Soome 			ficlUnsigned8 *integer8;
785*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
786*a1bf3f78SToomas Soome 			integer8 = (ficlUnsigned8 *)dataTop->p;
787*a1bf3f78SToomas Soome 			dataTop->u = ((ficlUnsigned)*integer8);
788*a1bf3f78SToomas Soome 		continue;
789*a1bf3f78SToomas Soome 		}
790*a1bf3f78SToomas Soome 
791*a1bf3f78SToomas Soome 		case ficlInstructionCStore: {
792*a1bf3f78SToomas Soome 			ficlUnsigned8 *integer8;
793*a1bf3f78SToomas Soome 			CHECK_STACK(2, 0);
794*a1bf3f78SToomas Soome 			integer8 = (ficlUnsigned8 *)(dataTop--)->p;
795*a1bf3f78SToomas Soome 			*integer8 = (ficlUnsigned8)((dataTop--)->u);
796*a1bf3f78SToomas Soome 		continue;
797*a1bf3f78SToomas Soome 		}
798*a1bf3f78SToomas Soome 
799*a1bf3f78SToomas Soome 
800*a1bf3f78SToomas Soome 		/*
801*a1bf3f78SToomas Soome 		 * l o g i c   a n d   c o m p a r i s o n s
802*a1bf3f78SToomas Soome 		 */
803*a1bf3f78SToomas Soome 
804*a1bf3f78SToomas Soome 		case ficlInstruction0Equals:
805*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
806*a1bf3f78SToomas Soome 			dataTop->i = FICL_BOOL(dataTop->i == 0);
807*a1bf3f78SToomas Soome 		continue;
808*a1bf3f78SToomas Soome 
809*a1bf3f78SToomas Soome 		case ficlInstruction0Less:
810*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
811*a1bf3f78SToomas Soome 			dataTop->i = FICL_BOOL(dataTop->i < 0);
812*a1bf3f78SToomas Soome 		continue;
813*a1bf3f78SToomas Soome 
814*a1bf3f78SToomas Soome 		case ficlInstruction0Greater:
815*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
816*a1bf3f78SToomas Soome 			dataTop->i = FICL_BOOL(dataTop->i > 0);
817*a1bf3f78SToomas Soome 		continue;
818*a1bf3f78SToomas Soome 
819*a1bf3f78SToomas Soome 		case ficlInstructionEquals:
820*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
821*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
822*a1bf3f78SToomas Soome 			dataTop->i = FICL_BOOL(dataTop->i == i);
823*a1bf3f78SToomas Soome 		continue;
824*a1bf3f78SToomas Soome 
825*a1bf3f78SToomas Soome 		case ficlInstructionLess:
826*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
827*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
828*a1bf3f78SToomas Soome 			dataTop->i = FICL_BOOL(dataTop->i < i);
829*a1bf3f78SToomas Soome 		continue;
830*a1bf3f78SToomas Soome 
831*a1bf3f78SToomas Soome 		case ficlInstructionULess:
832*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
833*a1bf3f78SToomas Soome 			u = (dataTop--)->u;
834*a1bf3f78SToomas Soome 			dataTop->i = FICL_BOOL(dataTop->u < u);
835*a1bf3f78SToomas Soome 		continue;
836*a1bf3f78SToomas Soome 
837*a1bf3f78SToomas Soome 		case ficlInstructionAnd:
838*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
839*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
840*a1bf3f78SToomas Soome 			dataTop->i = dataTop->i & i;
841*a1bf3f78SToomas Soome 		continue;
842*a1bf3f78SToomas Soome 
843*a1bf3f78SToomas Soome 		case ficlInstructionOr:
844*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
845*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
846*a1bf3f78SToomas Soome 			dataTop->i = dataTop->i | i;
847*a1bf3f78SToomas Soome 		continue;
848*a1bf3f78SToomas Soome 
849*a1bf3f78SToomas Soome 		case ficlInstructionXor:
850*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
851*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
852*a1bf3f78SToomas Soome 			dataTop->i = dataTop->i ^ i;
853*a1bf3f78SToomas Soome 		continue;
854*a1bf3f78SToomas Soome 
855*a1bf3f78SToomas Soome 		case ficlInstructionInvert:
856*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
857*a1bf3f78SToomas Soome 			dataTop->i = ~dataTop->i;
858*a1bf3f78SToomas Soome 		continue;
859*a1bf3f78SToomas Soome 
860*a1bf3f78SToomas Soome 		/*
861*a1bf3f78SToomas Soome 		 * r e t u r n   s t a c k
862*a1bf3f78SToomas Soome 		 */
863*a1bf3f78SToomas Soome 		case ficlInstructionToRStack:
864*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
865*a1bf3f78SToomas Soome 			CHECK_RETURN_STACK(0, 1);
866*a1bf3f78SToomas Soome 			*++returnTop = *dataTop--;
867*a1bf3f78SToomas Soome 		continue;
868*a1bf3f78SToomas Soome 
869*a1bf3f78SToomas Soome 		case ficlInstructionFromRStack:
870*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
871*a1bf3f78SToomas Soome 			CHECK_RETURN_STACK(1, 0);
872*a1bf3f78SToomas Soome 			*++dataTop = *returnTop--;
873*a1bf3f78SToomas Soome 		continue;
874*a1bf3f78SToomas Soome 
875*a1bf3f78SToomas Soome 		case ficlInstructionFetchRStack:
876*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
877*a1bf3f78SToomas Soome 			CHECK_RETURN_STACK(1, 1);
878*a1bf3f78SToomas Soome 			*++dataTop = *returnTop;
879*a1bf3f78SToomas Soome 		continue;
880*a1bf3f78SToomas Soome 
881*a1bf3f78SToomas Soome 		case ficlInstruction2ToR:
882*a1bf3f78SToomas Soome 			CHECK_STACK(2, 0);
883*a1bf3f78SToomas Soome 			CHECK_RETURN_STACK(0, 2);
884*a1bf3f78SToomas Soome 			*++returnTop = dataTop[-1];
885*a1bf3f78SToomas Soome 			*++returnTop = dataTop[0];
886*a1bf3f78SToomas Soome 			dataTop -= 2;
887*a1bf3f78SToomas Soome 		continue;
888*a1bf3f78SToomas Soome 
889*a1bf3f78SToomas Soome 		case ficlInstruction2RFrom:
890*a1bf3f78SToomas Soome 			CHECK_STACK(0, 2);
891*a1bf3f78SToomas Soome 			CHECK_RETURN_STACK(2, 0);
892*a1bf3f78SToomas Soome 			*++dataTop = returnTop[-1];
893*a1bf3f78SToomas Soome 			*++dataTop = returnTop[0];
894*a1bf3f78SToomas Soome 			returnTop -= 2;
895*a1bf3f78SToomas Soome 		continue;
896*a1bf3f78SToomas Soome 
897*a1bf3f78SToomas Soome 		case ficlInstruction2RFetch:
898*a1bf3f78SToomas Soome 			CHECK_STACK(0, 2);
899*a1bf3f78SToomas Soome 			CHECK_RETURN_STACK(2, 2);
900*a1bf3f78SToomas Soome 			*++dataTop = returnTop[-1];
901*a1bf3f78SToomas Soome 			*++dataTop = returnTop[0];
902*a1bf3f78SToomas Soome 		continue;
903*a1bf3f78SToomas Soome 
904*a1bf3f78SToomas Soome 		/*
905*a1bf3f78SToomas Soome 		 * f i l l
906*a1bf3f78SToomas Soome 		 * CORE ( c-addr u char -- )
907*a1bf3f78SToomas Soome 		 * If u is greater than zero, store char in each of u
908*a1bf3f78SToomas Soome 		 * consecutive characters of memory beginning at c-addr.
909*a1bf3f78SToomas Soome 		 */
910*a1bf3f78SToomas Soome 		case ficlInstructionFill: {
911*a1bf3f78SToomas Soome 			char c;
912*a1bf3f78SToomas Soome 			char *memory;
913*a1bf3f78SToomas Soome 			CHECK_STACK(3, 0);
914*a1bf3f78SToomas Soome 			c = (char)(dataTop--)->i;
915*a1bf3f78SToomas Soome 			u = (dataTop--)->u;
916*a1bf3f78SToomas Soome 			memory = (char *)(dataTop--)->p;
917*a1bf3f78SToomas Soome 
918*a1bf3f78SToomas Soome 			/*
919*a1bf3f78SToomas Soome 			 * memset() is faster than the previous hand-rolled
920*a1bf3f78SToomas Soome 			 * solution.  --lch
921*a1bf3f78SToomas Soome 			 */
922*a1bf3f78SToomas Soome 			memset(memory, c, u);
923*a1bf3f78SToomas Soome 		continue;
924*a1bf3f78SToomas Soome 		}
925*a1bf3f78SToomas Soome 
926*a1bf3f78SToomas Soome 		/*
927*a1bf3f78SToomas Soome 		 * l s h i f t
928*a1bf3f78SToomas Soome 		 * l-shift CORE ( x1 u -- x2 )
929*a1bf3f78SToomas Soome 		 * Perform a logical left shift of u bit-places on x1,
930*a1bf3f78SToomas Soome 		 * giving x2. Put zeroes into the least significant bits
931*a1bf3f78SToomas Soome 		 * vacated by the shift. An ambiguous condition exists if
932*a1bf3f78SToomas Soome 		 * u is greater than or equal to the number of bits in a
933*a1bf3f78SToomas Soome 		 * ficlCell.
934*a1bf3f78SToomas Soome 		 *
935*a1bf3f78SToomas Soome 		 * r-shift CORE ( x1 u -- x2 )
936*a1bf3f78SToomas Soome 		 * Perform a logical right shift of u bit-places on x1,
937*a1bf3f78SToomas Soome 		 * giving x2. Put zeroes into the most significant bits
938*a1bf3f78SToomas Soome 		 * vacated by the shift. An ambiguous condition exists
939*a1bf3f78SToomas Soome 		 * if u is greater than or equal to the number of bits
940*a1bf3f78SToomas Soome 		 * in a ficlCell.
941*a1bf3f78SToomas Soome 		 */
942*a1bf3f78SToomas Soome 		case ficlInstructionLShift: {
943*a1bf3f78SToomas Soome 			ficlUnsigned nBits;
944*a1bf3f78SToomas Soome 			ficlUnsigned x1;
945*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
946*a1bf3f78SToomas Soome 
947*a1bf3f78SToomas Soome 			nBits = (dataTop--)->u;
948*a1bf3f78SToomas Soome 			x1 = dataTop->u;
949*a1bf3f78SToomas Soome 			dataTop->u = x1 << nBits;
950*a1bf3f78SToomas Soome 		continue;
951*a1bf3f78SToomas Soome 		}
952*a1bf3f78SToomas Soome 
953*a1bf3f78SToomas Soome 		case ficlInstructionRShift: {
954*a1bf3f78SToomas Soome 			ficlUnsigned nBits;
955*a1bf3f78SToomas Soome 			ficlUnsigned x1;
956*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
957*a1bf3f78SToomas Soome 
958*a1bf3f78SToomas Soome 			nBits = (dataTop--)->u;
959*a1bf3f78SToomas Soome 			x1 = dataTop->u;
960*a1bf3f78SToomas Soome 			dataTop->u = x1 >> nBits;
961*a1bf3f78SToomas Soome 			continue;
962*a1bf3f78SToomas Soome 		}
963*a1bf3f78SToomas Soome 
964*a1bf3f78SToomas Soome 		/*
965*a1bf3f78SToomas Soome 		 * m a x   &   m i n
966*a1bf3f78SToomas Soome 		 */
967*a1bf3f78SToomas Soome 		case ficlInstructionMax: {
968*a1bf3f78SToomas Soome 			ficlInteger n2;
969*a1bf3f78SToomas Soome 			ficlInteger n1;
970*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
971*a1bf3f78SToomas Soome 
972*a1bf3f78SToomas Soome 			n2 = (dataTop--)->i;
973*a1bf3f78SToomas Soome 			n1 = dataTop->i;
974*a1bf3f78SToomas Soome 
975*a1bf3f78SToomas Soome 			dataTop->i = ((n1 > n2) ? n1 : n2);
976*a1bf3f78SToomas Soome 		continue;
977*a1bf3f78SToomas Soome 		}
978*a1bf3f78SToomas Soome 
979*a1bf3f78SToomas Soome 		case ficlInstructionMin: {
980*a1bf3f78SToomas Soome 			ficlInteger n2;
981*a1bf3f78SToomas Soome 			ficlInteger n1;
982*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
983*a1bf3f78SToomas Soome 
984*a1bf3f78SToomas Soome 			n2 = (dataTop--)->i;
985*a1bf3f78SToomas Soome 				n1 = dataTop->i;
986*a1bf3f78SToomas Soome 
987*a1bf3f78SToomas Soome 			dataTop->i = ((n1 < n2) ? n1 : n2);
988*a1bf3f78SToomas Soome 			continue;
989*a1bf3f78SToomas Soome 		}
990*a1bf3f78SToomas Soome 
991*a1bf3f78SToomas Soome 		/*
992*a1bf3f78SToomas Soome 		 * m o v e
993*a1bf3f78SToomas Soome 		 * CORE ( addr1 addr2 u -- )
994*a1bf3f78SToomas Soome 		 * If u is greater than zero, copy the contents of u
995*a1bf3f78SToomas Soome 		 * consecutive address units at addr1 to the u consecutive
996*a1bf3f78SToomas Soome 		 * address units at addr2. After MOVE completes, the u
997*a1bf3f78SToomas Soome 		 * consecutive address units at addr2 contain exactly
998*a1bf3f78SToomas Soome 		 * what the u consecutive address units at addr1 contained
999*a1bf3f78SToomas Soome 		 * before the move.
1000*a1bf3f78SToomas Soome 		 * NOTE! This implementation assumes that a char is the same
1001*a1bf3f78SToomas Soome 		 * size as an address unit.
1002*a1bf3f78SToomas Soome 		 */
1003*a1bf3f78SToomas Soome 		case ficlInstructionMove: {
1004*a1bf3f78SToomas Soome 			ficlUnsigned u;
1005*a1bf3f78SToomas Soome 			char *addr2;
1006*a1bf3f78SToomas Soome 			char *addr1;
1007*a1bf3f78SToomas Soome 			CHECK_STACK(3, 0);
1008*a1bf3f78SToomas Soome 
1009*a1bf3f78SToomas Soome 			u = (dataTop--)->u;
1010*a1bf3f78SToomas Soome 			addr2 = (dataTop--)->p;
1011*a1bf3f78SToomas Soome 			addr1 = (dataTop--)->p;
1012*a1bf3f78SToomas Soome 
1013*a1bf3f78SToomas Soome 			if (u == 0)
1014*a1bf3f78SToomas Soome 				continue;
1015*a1bf3f78SToomas Soome 			/*
1016*a1bf3f78SToomas Soome 			 * Do the copy carefully, so as to be
1017*a1bf3f78SToomas Soome 			 * correct even if the two ranges overlap
1018*a1bf3f78SToomas Soome 			 */
1019*a1bf3f78SToomas Soome 			/* Which ANSI C's memmove() does for you! Yay!  --lch */
1020*a1bf3f78SToomas Soome 			memmove(addr2, addr1, u);
1021*a1bf3f78SToomas Soome 		continue;
1022*a1bf3f78SToomas Soome 		}
1023*a1bf3f78SToomas Soome 
1024*a1bf3f78SToomas Soome 		/*
1025*a1bf3f78SToomas Soome 		 * s t o d
1026*a1bf3f78SToomas Soome 		 * s-to-d CORE ( n -- d )
1027*a1bf3f78SToomas Soome 		 * Convert the number n to the double-ficlCell number d with
1028*a1bf3f78SToomas Soome 		 * the same numerical value.
1029*a1bf3f78SToomas Soome 		 */
1030*a1bf3f78SToomas Soome 		case ficlInstructionSToD: {
1031*a1bf3f78SToomas Soome 			ficlInteger s;
1032*a1bf3f78SToomas Soome 			CHECK_STACK(1, 2);
1033*a1bf3f78SToomas Soome 
1034*a1bf3f78SToomas Soome 			s = dataTop->i;
1035*a1bf3f78SToomas Soome 
1036*a1bf3f78SToomas Soome 			/* sign extend to 64 bits.. */
1037*a1bf3f78SToomas Soome 			(++dataTop)->i = (s < 0) ? -1 : 0;
1038*a1bf3f78SToomas Soome 		continue;
1039*a1bf3f78SToomas Soome 		}
1040*a1bf3f78SToomas Soome 
1041*a1bf3f78SToomas Soome 		/*
1042*a1bf3f78SToomas Soome 		 * c o m p a r e
1043*a1bf3f78SToomas Soome 		 * STRING ( c-addr1 u1 c-addr2 u2 -- n )
1044*a1bf3f78SToomas Soome 		 * Compare the string specified by c-addr1 u1 to the string
1045*a1bf3f78SToomas Soome 		 * specified by c-addr2 u2. The strings are compared, beginning
1046*a1bf3f78SToomas Soome 		 * at the given addresses, character by character, up to the
1047*a1bf3f78SToomas Soome 		 * length of the shorter string or until a difference is found.
1048*a1bf3f78SToomas Soome 		 * If the two strings are identical, n is zero. If the two
1049*a1bf3f78SToomas Soome 		 * strings are identical up to the length of the shorter string,
1050*a1bf3f78SToomas Soome 		 * n is minus-one (-1) if u1 is less than u2 and one (1)
1051*a1bf3f78SToomas Soome 		 * otherwise. If the two strings are not identical up to the
1052*a1bf3f78SToomas Soome 		 * length of the shorter string, n is minus-one (-1) if the
1053*a1bf3f78SToomas Soome 		 * first non-matching character in the string specified by
1054*a1bf3f78SToomas Soome 		 * c-addr1 u1 has a lesser numeric value than the corresponding
1055*a1bf3f78SToomas Soome 		 * character in the string specified by c-addr2 u2 and
1056*a1bf3f78SToomas Soome 		 * one (1) otherwise.
1057*a1bf3f78SToomas Soome 		 */
1058*a1bf3f78SToomas Soome 		case ficlInstructionCompare:
1059*a1bf3f78SToomas Soome 			i = FICL_FALSE;
1060*a1bf3f78SToomas Soome 		goto COMPARE;
1061*a1bf3f78SToomas Soome 
1062*a1bf3f78SToomas Soome 
1063*a1bf3f78SToomas Soome 		case ficlInstructionCompareInsensitive:
1064*a1bf3f78SToomas Soome 			i = FICL_TRUE;
1065*a1bf3f78SToomas Soome 		goto COMPARE;
1066*a1bf3f78SToomas Soome 
1067*a1bf3f78SToomas Soome COMPARE:
1068*a1bf3f78SToomas Soome 		{
1069*a1bf3f78SToomas Soome 			char *cp1, *cp2;
1070*a1bf3f78SToomas Soome 			ficlUnsigned u1, u2, uMin;
1071*a1bf3f78SToomas Soome 			int n = 0;
1072*a1bf3f78SToomas Soome 
1073*a1bf3f78SToomas Soome 			CHECK_STACK(4, 1);
1074*a1bf3f78SToomas Soome 			u2  = (dataTop--)->u;
1075*a1bf3f78SToomas Soome 			cp2 = (char *)(dataTop--)->p;
1076*a1bf3f78SToomas Soome 			u1  = (dataTop--)->u;
1077*a1bf3f78SToomas Soome 			cp1 = (char *)(dataTop--)->p;
1078*a1bf3f78SToomas Soome 
1079*a1bf3f78SToomas Soome 			uMin = (u1 < u2)? u1 : u2;
1080*a1bf3f78SToomas Soome 			for (; (uMin > 0) && (n == 0); uMin--) {
1081*a1bf3f78SToomas Soome 				int c1 = (unsigned char)*cp1++;
1082*a1bf3f78SToomas Soome 				int c2 = (unsigned char)*cp2++;
1083*a1bf3f78SToomas Soome 
1084*a1bf3f78SToomas Soome 				if (i) {
1085*a1bf3f78SToomas Soome 					c1 = tolower(c1);
1086*a1bf3f78SToomas Soome 					c2 = tolower(c2);
1087*a1bf3f78SToomas Soome 				}
1088*a1bf3f78SToomas Soome 				n = (c1 - c2);
1089*a1bf3f78SToomas Soome 			}
1090*a1bf3f78SToomas Soome 
1091*a1bf3f78SToomas Soome 			if (n == 0)
1092*a1bf3f78SToomas Soome 				n = (int)(u1 - u2);
1093*a1bf3f78SToomas Soome 
1094*a1bf3f78SToomas Soome 			if (n < 0)
1095*a1bf3f78SToomas Soome 				n = -1;
1096*a1bf3f78SToomas Soome 			else if (n > 0)
1097*a1bf3f78SToomas Soome 				n = 1;
1098*a1bf3f78SToomas Soome 
1099*a1bf3f78SToomas Soome 			(++dataTop)->i = n;
1100*a1bf3f78SToomas Soome 		continue;
1101*a1bf3f78SToomas Soome 		}
1102*a1bf3f78SToomas Soome 
1103*a1bf3f78SToomas Soome 		/*
1104*a1bf3f78SToomas Soome 		 * r a n d o m
1105*a1bf3f78SToomas Soome 		 * Ficl-specific
1106*a1bf3f78SToomas Soome 		 */
1107*a1bf3f78SToomas Soome 		case ficlInstructionRandom:
1108*a1bf3f78SToomas Soome 			(++dataTop)->i = random();
1109*a1bf3f78SToomas Soome 		continue;
1110*a1bf3f78SToomas Soome 
1111*a1bf3f78SToomas Soome 		/*
1112*a1bf3f78SToomas Soome 		 * s e e d - r a n d o m
1113*a1bf3f78SToomas Soome 		 * Ficl-specific
1114*a1bf3f78SToomas Soome 		 */
1115*a1bf3f78SToomas Soome 		case ficlInstructionSeedRandom:
1116*a1bf3f78SToomas Soome 			srandom((dataTop--)->i);
1117*a1bf3f78SToomas Soome 		continue;
1118*a1bf3f78SToomas Soome 
1119*a1bf3f78SToomas Soome 		case ficlInstructionGreaterThan: {
1120*a1bf3f78SToomas Soome 			ficlInteger x, y;
1121*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
1122*a1bf3f78SToomas Soome 			y = (dataTop--)->i;
1123*a1bf3f78SToomas Soome 			x = dataTop->i;
1124*a1bf3f78SToomas Soome 			dataTop->i = FICL_BOOL(x > y);
1125*a1bf3f78SToomas Soome 		continue;
1126*a1bf3f78SToomas Soome 		}
1127*a1bf3f78SToomas Soome 
1128*a1bf3f78SToomas Soome 		/*
1129*a1bf3f78SToomas Soome 		 * This function simply pops the previous instruction
1130*a1bf3f78SToomas Soome 		 * pointer and returns to the "next" loop. Used for exiting
1131*a1bf3f78SToomas Soome 		 * from within a definition. Note that exitParen is identical
1132*a1bf3f78SToomas Soome 		 * to semiParen - they are in two different functions so that
1133*a1bf3f78SToomas Soome 		 * "see" can correctly identify the end of a colon definition,
1134*a1bf3f78SToomas Soome 		 * even if it uses "exit".
1135*a1bf3f78SToomas Soome 		 */
1136*a1bf3f78SToomas Soome 		case ficlInstructionExitParen:
1137*a1bf3f78SToomas Soome 		case ficlInstructionSemiParen:
1138*a1bf3f78SToomas Soome 			EXIT_FUNCTION();
1139*a1bf3f78SToomas Soome 
1140*a1bf3f78SToomas Soome 		/*
1141*a1bf3f78SToomas Soome 		 * The first time we run "(branch)", perform a "peephole
1142*a1bf3f78SToomas Soome 		 * optimization" to see if we're jumping to another
1143*a1bf3f78SToomas Soome 		 * unconditional jump.  If so, just jump directly there.
1144*a1bf3f78SToomas Soome 		 */
1145*a1bf3f78SToomas Soome 		case ficlInstructionBranchParenWithCheck:
1146*a1bf3f78SToomas Soome 			LOCAL_VARIABLE_SPILL;
1147*a1bf3f78SToomas Soome 			ficlVmOptimizeJumpToJump(vm, vm->ip - 1);
1148*a1bf3f78SToomas Soome 			LOCAL_VARIABLE_REFILL;
1149*a1bf3f78SToomas Soome 		goto BRANCH_PAREN;
1150*a1bf3f78SToomas Soome 
1151*a1bf3f78SToomas Soome 		/*
1152*a1bf3f78SToomas Soome 		 * Same deal with branch0.
1153*a1bf3f78SToomas Soome 		 */
1154*a1bf3f78SToomas Soome 		case ficlInstructionBranch0ParenWithCheck:
1155*a1bf3f78SToomas Soome 			LOCAL_VARIABLE_SPILL;
1156*a1bf3f78SToomas Soome 			ficlVmOptimizeJumpToJump(vm, vm->ip - 1);
1157*a1bf3f78SToomas Soome 			LOCAL_VARIABLE_REFILL;
1158*a1bf3f78SToomas Soome 			/* intentional fall-through */
1159*a1bf3f78SToomas Soome 
1160*a1bf3f78SToomas Soome 		/*
1161*a1bf3f78SToomas Soome 		 * Runtime code for "(branch0)"; pop a flag from the stack,
1162*a1bf3f78SToomas Soome 		 * branch if 0. fall through otherwise.
1163*a1bf3f78SToomas Soome 		 * The heart of "if" and "until".
1164*a1bf3f78SToomas Soome 		 */
1165*a1bf3f78SToomas Soome 		case ficlInstructionBranch0Paren:
1166*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1167*a1bf3f78SToomas Soome 
1168*a1bf3f78SToomas Soome 			if ((dataTop--)->i) {
1169*a1bf3f78SToomas Soome 				/*
1170*a1bf3f78SToomas Soome 				 * don't branch, but skip over branch
1171*a1bf3f78SToomas Soome 				 * relative address
1172*a1bf3f78SToomas Soome 				 */
1173*a1bf3f78SToomas Soome 				ip += 1;
1174*a1bf3f78SToomas Soome 				continue;
1175*a1bf3f78SToomas Soome 			}
1176*a1bf3f78SToomas Soome 			/* otherwise, take branch (to else/endif/begin) */
1177*a1bf3f78SToomas Soome 			/* intentional fall-through! */
1178*a1bf3f78SToomas Soome 
1179*a1bf3f78SToomas Soome 		/*
1180*a1bf3f78SToomas Soome 		 * Runtime for "(branch)" -- expects a literal offset in the
1181*a1bf3f78SToomas Soome 		 * next compilation address, and branches to that location.
1182*a1bf3f78SToomas Soome 		 */
1183*a1bf3f78SToomas Soome 		case ficlInstructionBranchParen:
1184*a1bf3f78SToomas Soome BRANCH_PAREN:
1185*a1bf3f78SToomas Soome 			BRANCH();
1186*a1bf3f78SToomas Soome 
1187*a1bf3f78SToomas Soome 		case ficlInstructionOfParen: {
1188*a1bf3f78SToomas Soome 			ficlUnsigned a, b;
1189*a1bf3f78SToomas Soome 
1190*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
1191*a1bf3f78SToomas Soome 
1192*a1bf3f78SToomas Soome 			a = (dataTop--)->u;
1193*a1bf3f78SToomas Soome 			b = dataTop->u;
1194*a1bf3f78SToomas Soome 
1195*a1bf3f78SToomas Soome 			if (a == b) {
1196*a1bf3f78SToomas Soome 				/* fall through */
1197*a1bf3f78SToomas Soome 				ip++;
1198*a1bf3f78SToomas Soome 				/* remove CASE argument */
1199*a1bf3f78SToomas Soome 				dataTop--;
1200*a1bf3f78SToomas Soome 			} else {
1201*a1bf3f78SToomas Soome 				/* take branch to next of or endcase */
1202*a1bf3f78SToomas Soome 				BRANCH();
1203*a1bf3f78SToomas Soome 			}
1204*a1bf3f78SToomas Soome 
1205*a1bf3f78SToomas Soome 		continue;
1206*a1bf3f78SToomas Soome 		}
1207*a1bf3f78SToomas Soome 
1208*a1bf3f78SToomas Soome 		case ficlInstructionDoParen: {
1209*a1bf3f78SToomas Soome 			ficlCell index, limit;
1210*a1bf3f78SToomas Soome 
1211*a1bf3f78SToomas Soome 			CHECK_STACK(2, 0);
1212*a1bf3f78SToomas Soome 
1213*a1bf3f78SToomas Soome 			index = *dataTop--;
1214*a1bf3f78SToomas Soome 			limit = *dataTop--;
1215*a1bf3f78SToomas Soome 
1216*a1bf3f78SToomas Soome 			/* copy "leave" target addr to stack */
1217*a1bf3f78SToomas Soome 			(++returnTop)->i = *(ip++);
1218*a1bf3f78SToomas Soome 			*++returnTop = limit;
1219*a1bf3f78SToomas Soome 			*++returnTop = index;
1220*a1bf3f78SToomas Soome 
1221*a1bf3f78SToomas Soome 		continue;
1222*a1bf3f78SToomas Soome 		}
1223*a1bf3f78SToomas Soome 
1224*a1bf3f78SToomas Soome 		case ficlInstructionQDoParen: {
1225*a1bf3f78SToomas Soome 			ficlCell index, limit, leave;
1226*a1bf3f78SToomas Soome 
1227*a1bf3f78SToomas Soome 			CHECK_STACK(2, 0);
1228*a1bf3f78SToomas Soome 
1229*a1bf3f78SToomas Soome 			index = *dataTop--;
1230*a1bf3f78SToomas Soome 			limit = *dataTop--;
1231*a1bf3f78SToomas Soome 
1232*a1bf3f78SToomas Soome 			leave.i = *ip;
1233*a1bf3f78SToomas Soome 
1234*a1bf3f78SToomas Soome 			if (limit.u == index.u) {
1235*a1bf3f78SToomas Soome 				ip = leave.p;
1236*a1bf3f78SToomas Soome 			} else {
1237*a1bf3f78SToomas Soome 				ip++;
1238*a1bf3f78SToomas Soome 				*++returnTop = leave;
1239*a1bf3f78SToomas Soome 				*++returnTop = limit;
1240*a1bf3f78SToomas Soome 				*++returnTop = index;
1241*a1bf3f78SToomas Soome 			}
1242*a1bf3f78SToomas Soome 
1243*a1bf3f78SToomas Soome 		continue;
1244*a1bf3f78SToomas Soome 		}
1245*a1bf3f78SToomas Soome 
1246*a1bf3f78SToomas Soome 		case ficlInstructionLoopParen:
1247*a1bf3f78SToomas Soome 		case ficlInstructionPlusLoopParen: {
1248*a1bf3f78SToomas Soome 			ficlInteger index;
1249*a1bf3f78SToomas Soome 			ficlInteger limit;
1250*a1bf3f78SToomas Soome 			int direction = 0;
1251*a1bf3f78SToomas Soome 
1252*a1bf3f78SToomas Soome 			index = returnTop->i;
1253*a1bf3f78SToomas Soome 			limit = returnTop[-1].i;
1254*a1bf3f78SToomas Soome 
1255*a1bf3f78SToomas Soome 			if (instruction == ficlInstructionLoopParen)
1256*a1bf3f78SToomas Soome 				index++;
1257*a1bf3f78SToomas Soome 			else {
1258*a1bf3f78SToomas Soome 				ficlInteger increment;
1259*a1bf3f78SToomas Soome 				CHECK_STACK(1, 0);
1260*a1bf3f78SToomas Soome 				increment = (dataTop--)->i;
1261*a1bf3f78SToomas Soome 				index += increment;
1262*a1bf3f78SToomas Soome 				direction = (increment < 0);
1263*a1bf3f78SToomas Soome 			}
1264*a1bf3f78SToomas Soome 
1265*a1bf3f78SToomas Soome 			if (direction ^ (index >= limit)) {
1266*a1bf3f78SToomas Soome 				/* nuke the loop indices & "leave" addr */
1267*a1bf3f78SToomas Soome 				returnTop -= 3;
1268*a1bf3f78SToomas Soome 				ip++;  /* fall through the loop */
1269*a1bf3f78SToomas Soome 			} else {	/* update index, branch to loop head */
1270*a1bf3f78SToomas Soome 				returnTop->i = index;
1271*a1bf3f78SToomas Soome 				BRANCH();
1272*a1bf3f78SToomas Soome 			}
1273*a1bf3f78SToomas Soome 
1274*a1bf3f78SToomas Soome 		continue;
1275*a1bf3f78SToomas Soome 		}
1276*a1bf3f78SToomas Soome 
1277*a1bf3f78SToomas Soome 
1278*a1bf3f78SToomas Soome 		/*
1279*a1bf3f78SToomas Soome 		 * Runtime code to break out of a do..loop construct
1280*a1bf3f78SToomas Soome 		 * Drop the loop control variables; the branch address
1281*a1bf3f78SToomas Soome 		 * past "loop" is next on the return stack.
1282*a1bf3f78SToomas Soome 		 */
1283*a1bf3f78SToomas Soome 		case ficlInstructionLeave:
1284*a1bf3f78SToomas Soome 			/* almost unloop */
1285*a1bf3f78SToomas Soome 			returnTop -= 2;
1286*a1bf3f78SToomas Soome 			/* exit */
1287*a1bf3f78SToomas Soome 			EXIT_FUNCTION();
1288*a1bf3f78SToomas Soome 
1289*a1bf3f78SToomas Soome 		case ficlInstructionUnloop:
1290*a1bf3f78SToomas Soome 			returnTop -= 3;
1291*a1bf3f78SToomas Soome 		continue;
1292*a1bf3f78SToomas Soome 
1293*a1bf3f78SToomas Soome 		case ficlInstructionI:
1294*a1bf3f78SToomas Soome 			*++dataTop = *returnTop;
1295*a1bf3f78SToomas Soome 		continue;
1296*a1bf3f78SToomas Soome 
1297*a1bf3f78SToomas Soome 		case ficlInstructionJ:
1298*a1bf3f78SToomas Soome 			*++dataTop = returnTop[-3];
1299*a1bf3f78SToomas Soome 		continue;
1300*a1bf3f78SToomas Soome 
1301*a1bf3f78SToomas Soome 		case ficlInstructionK:
1302*a1bf3f78SToomas Soome 			*++dataTop = returnTop[-6];
1303*a1bf3f78SToomas Soome 		continue;
1304*a1bf3f78SToomas Soome 
1305*a1bf3f78SToomas Soome 		case ficlInstructionDoesParen: {
1306*a1bf3f78SToomas Soome 			ficlDictionary *dictionary = ficlVmGetDictionary(vm);
1307*a1bf3f78SToomas Soome 			dictionary->smudge->code =
1308*a1bf3f78SToomas Soome 			    (ficlPrimitive)ficlInstructionDoDoes;
1309*a1bf3f78SToomas Soome 			dictionary->smudge->param[0].p = ip;
1310*a1bf3f78SToomas Soome 			ip = (ficlInstruction *)((returnTop--)->p);
1311*a1bf3f78SToomas Soome 		continue;
1312*a1bf3f78SToomas Soome 		}
1313*a1bf3f78SToomas Soome 
1314*a1bf3f78SToomas Soome 		case ficlInstructionDoDoes: {
1315*a1bf3f78SToomas Soome 			ficlCell *cell;
1316*a1bf3f78SToomas Soome 			ficlIp tempIP;
1317*a1bf3f78SToomas Soome 
1318*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
1319*a1bf3f78SToomas Soome 
1320*a1bf3f78SToomas Soome 			cell = fw->param;
1321*a1bf3f78SToomas Soome 			tempIP = (ficlIp)((*cell).p);
1322*a1bf3f78SToomas Soome 			(++dataTop)->p = (cell + 1);
1323*a1bf3f78SToomas Soome 			(++returnTop)->p = (void *)ip;
1324*a1bf3f78SToomas Soome 			ip = (ficlInstruction *)tempIP;
1325*a1bf3f78SToomas Soome 		continue;
1326*a1bf3f78SToomas Soome 		}
1327*a1bf3f78SToomas Soome 
1328*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
1329*a1bf3f78SToomas Soome 		case ficlInstructionF2Fetch:
1330*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(0, 2);
1331*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1332*a1bf3f78SToomas Soome 			FLOAT_PUSH_CELL_POINTER_DOUBLE((dataTop--)->p);
1333*a1bf3f78SToomas Soome 
1334*a1bf3f78SToomas Soome 		case ficlInstructionFFetch:
1335*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(0, 1);
1336*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1337*a1bf3f78SToomas Soome 			FLOAT_PUSH_CELL_POINTER((dataTop--)->p);
1338*a1bf3f78SToomas Soome 
1339*a1bf3f78SToomas Soome 		case ficlInstructionF2Store:
1340*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 0);
1341*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1342*a1bf3f78SToomas Soome 			FLOAT_POP_CELL_POINTER_DOUBLE((dataTop--)->p);
1343*a1bf3f78SToomas Soome 
1344*a1bf3f78SToomas Soome 		case ficlInstructionFStore:
1345*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 0);
1346*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1347*a1bf3f78SToomas Soome 			FLOAT_POP_CELL_POINTER((dataTop--)->p);
1348*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */
1349*a1bf3f78SToomas Soome 
1350*a1bf3f78SToomas Soome 		/*
1351*a1bf3f78SToomas Soome 		 * two-fetch CORE ( a-addr -- x1 x2 )
1352*a1bf3f78SToomas Soome 		 *
1353*a1bf3f78SToomas Soome 		 * Fetch the ficlCell pair x1 x2 stored at a-addr.
1354*a1bf3f78SToomas Soome 		 * x2 is stored at a-addr and x1 at the next consecutive
1355*a1bf3f78SToomas Soome 		 * ficlCell. It is equivalent to the sequence
1356*a1bf3f78SToomas Soome 		 * DUP ficlCell+ @ SWAP @ .
1357*a1bf3f78SToomas Soome 		 */
1358*a1bf3f78SToomas Soome 		case ficlInstruction2Fetch:
1359*a1bf3f78SToomas Soome 			CHECK_STACK(1, 2);
1360*a1bf3f78SToomas Soome 			PUSH_CELL_POINTER_DOUBLE((dataTop--)->p);
1361*a1bf3f78SToomas Soome 
1362*a1bf3f78SToomas Soome 		/*
1363*a1bf3f78SToomas Soome 		 * fetch CORE ( a-addr -- x )
1364*a1bf3f78SToomas Soome 		 *
1365*a1bf3f78SToomas Soome 		 * x is the value stored at a-addr.
1366*a1bf3f78SToomas Soome 		 */
1367*a1bf3f78SToomas Soome 		case ficlInstructionFetch:
1368*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
1369*a1bf3f78SToomas Soome 			PUSH_CELL_POINTER((dataTop--)->p);
1370*a1bf3f78SToomas Soome 
1371*a1bf3f78SToomas Soome 		/*
1372*a1bf3f78SToomas Soome 		 * two-store    CORE ( x1 x2 a-addr -- )
1373*a1bf3f78SToomas Soome 		 * Store the ficlCell pair x1 x2 at a-addr, with x2 at a-addr
1374*a1bf3f78SToomas Soome 		 * and x1 at the next consecutive ficlCell. It is equivalent
1375*a1bf3f78SToomas Soome 		 * to the sequence SWAP OVER ! ficlCell+ !
1376*a1bf3f78SToomas Soome 		 */
1377*a1bf3f78SToomas Soome 		case ficlInstruction2Store:
1378*a1bf3f78SToomas Soome 			CHECK_STACK(3, 0);
1379*a1bf3f78SToomas Soome 			POP_CELL_POINTER_DOUBLE((dataTop--)->p);
1380*a1bf3f78SToomas Soome 
1381*a1bf3f78SToomas Soome 		/*
1382*a1bf3f78SToomas Soome 		 * store	CORE ( x a-addr -- )
1383*a1bf3f78SToomas Soome 		 * Store x at a-addr.
1384*a1bf3f78SToomas Soome 		 */
1385*a1bf3f78SToomas Soome 		case ficlInstructionStore:
1386*a1bf3f78SToomas Soome 			CHECK_STACK(2, 0);
1387*a1bf3f78SToomas Soome 			POP_CELL_POINTER((dataTop--)->p);
1388*a1bf3f78SToomas Soome 
1389*a1bf3f78SToomas Soome 		case ficlInstructionComma: {
1390*a1bf3f78SToomas Soome 			ficlDictionary *dictionary;
1391*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1392*a1bf3f78SToomas Soome 
1393*a1bf3f78SToomas Soome 			dictionary = ficlVmGetDictionary(vm);
1394*a1bf3f78SToomas Soome 			ficlDictionaryAppendCell(dictionary, *dataTop--);
1395*a1bf3f78SToomas Soome 		continue;
1396*a1bf3f78SToomas Soome 		}
1397*a1bf3f78SToomas Soome 
1398*a1bf3f78SToomas Soome 		case ficlInstructionCComma: {
1399*a1bf3f78SToomas Soome 			ficlDictionary *dictionary;
1400*a1bf3f78SToomas Soome 			char c;
1401*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1402*a1bf3f78SToomas Soome 
1403*a1bf3f78SToomas Soome 			dictionary = ficlVmGetDictionary(vm);
1404*a1bf3f78SToomas Soome 			c = (char)(dataTop--)->i;
1405*a1bf3f78SToomas Soome 			ficlDictionaryAppendCharacter(dictionary, c);
1406*a1bf3f78SToomas Soome 		continue;
1407*a1bf3f78SToomas Soome 		}
1408*a1bf3f78SToomas Soome 
1409*a1bf3f78SToomas Soome 		case ficlInstructionCells:
1410*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
1411*a1bf3f78SToomas Soome 			dataTop->i *= sizeof (ficlCell);
1412*a1bf3f78SToomas Soome 		continue;
1413*a1bf3f78SToomas Soome 
1414*a1bf3f78SToomas Soome 		case ficlInstructionCellPlus:
1415*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
1416*a1bf3f78SToomas Soome 			dataTop->i += sizeof (ficlCell);
1417*a1bf3f78SToomas Soome 		continue;
1418*a1bf3f78SToomas Soome 
1419*a1bf3f78SToomas Soome 		case ficlInstructionStar:
1420*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
1421*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
1422*a1bf3f78SToomas Soome 			dataTop->i *= i;
1423*a1bf3f78SToomas Soome 		continue;
1424*a1bf3f78SToomas Soome 
1425*a1bf3f78SToomas Soome 		case ficlInstructionNegate:
1426*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
1427*a1bf3f78SToomas Soome 			dataTop->i = - dataTop->i;
1428*a1bf3f78SToomas Soome 		continue;
1429*a1bf3f78SToomas Soome 
1430*a1bf3f78SToomas Soome 		case ficlInstructionSlash:
1431*a1bf3f78SToomas Soome 			CHECK_STACK(2, 1);
1432*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
1433*a1bf3f78SToomas Soome 			dataTop->i /= i;
1434*a1bf3f78SToomas Soome 		continue;
1435*a1bf3f78SToomas Soome 
1436*a1bf3f78SToomas Soome 		/*
1437*a1bf3f78SToomas Soome 		 * slash-mod	CORE ( n1 n2 -- n3 n4 )
1438*a1bf3f78SToomas Soome 		 * Divide n1 by n2, giving the single-ficlCell remainder n3
1439*a1bf3f78SToomas Soome 		 * and the single-ficlCell quotient n4. An ambiguous condition
1440*a1bf3f78SToomas Soome 		 * exists if n2 is zero. If n1 and n2 differ in sign, the
1441*a1bf3f78SToomas Soome 		 * implementation-defined result returned will be the
1442*a1bf3f78SToomas Soome 		 * same as that returned by either the phrase
1443*a1bf3f78SToomas Soome 		 * >R S>D R> FM/MOD or the phrase >R S>D R> SM/REM.
1444*a1bf3f78SToomas Soome 		 * NOTE: Ficl complies with the second phrase
1445*a1bf3f78SToomas Soome 		 * (symmetric division)
1446*a1bf3f78SToomas Soome 		 */
1447*a1bf3f78SToomas Soome 		case ficlInstructionSlashMod: {
1448*a1bf3f78SToomas Soome 			ficl2Integer n1;
1449*a1bf3f78SToomas Soome 			ficlInteger n2;
1450*a1bf3f78SToomas Soome 			ficl2IntegerQR qr;
1451*a1bf3f78SToomas Soome 
1452*a1bf3f78SToomas Soome 			CHECK_STACK(2, 2);
1453*a1bf3f78SToomas Soome 			n2    = dataTop[0].i;
1454*a1bf3f78SToomas Soome 			FICL_INTEGER_TO_2INTEGER(dataTop[-1].i, n1);
1455*a1bf3f78SToomas Soome 
1456*a1bf3f78SToomas Soome 			qr = ficl2IntegerDivideSymmetric(n1, n2);
1457*a1bf3f78SToomas Soome 			dataTop[-1].i = qr.remainder;
1458*a1bf3f78SToomas Soome 			dataTop[0].i = FICL_2UNSIGNED_GET_LOW(qr.quotient);
1459*a1bf3f78SToomas Soome 		continue;
1460*a1bf3f78SToomas Soome 		}
1461*a1bf3f78SToomas Soome 
1462*a1bf3f78SToomas Soome 		case ficlInstruction2Star:
1463*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
1464*a1bf3f78SToomas Soome 			dataTop->i <<= 1;
1465*a1bf3f78SToomas Soome 		continue;
1466*a1bf3f78SToomas Soome 
1467*a1bf3f78SToomas Soome 		case ficlInstruction2Slash:
1468*a1bf3f78SToomas Soome 			CHECK_STACK(1, 1);
1469*a1bf3f78SToomas Soome 			dataTop->i >>= 1;
1470*a1bf3f78SToomas Soome 		continue;
1471*a1bf3f78SToomas Soome 
1472*a1bf3f78SToomas Soome 		case ficlInstructionStarSlash: {
1473*a1bf3f78SToomas Soome 			ficlInteger x, y, z;
1474*a1bf3f78SToomas Soome 			ficl2Integer prod;
1475*a1bf3f78SToomas Soome 			CHECK_STACK(3, 1);
1476*a1bf3f78SToomas Soome 
1477*a1bf3f78SToomas Soome 			z = (dataTop--)->i;
1478*a1bf3f78SToomas Soome 			y = (dataTop--)->i;
1479*a1bf3f78SToomas Soome 			x = dataTop->i;
1480*a1bf3f78SToomas Soome 
1481*a1bf3f78SToomas Soome 			prod = ficl2IntegerMultiply(x, y);
1482*a1bf3f78SToomas Soome 			dataTop->i = FICL_2UNSIGNED_GET_LOW(
1483*a1bf3f78SToomas Soome 			    ficl2IntegerDivideSymmetric(prod, z).quotient);
1484*a1bf3f78SToomas Soome 		continue;
1485*a1bf3f78SToomas Soome 		}
1486*a1bf3f78SToomas Soome 
1487*a1bf3f78SToomas Soome 		case ficlInstructionStarSlashMod: {
1488*a1bf3f78SToomas Soome 			ficlInteger x, y, z;
1489*a1bf3f78SToomas Soome 			ficl2Integer prod;
1490*a1bf3f78SToomas Soome 			ficl2IntegerQR qr;
1491*a1bf3f78SToomas Soome 
1492*a1bf3f78SToomas Soome 			CHECK_STACK(3, 2);
1493*a1bf3f78SToomas Soome 
1494*a1bf3f78SToomas Soome 			z = (dataTop--)->i;
1495*a1bf3f78SToomas Soome 			y = dataTop[0].i;
1496*a1bf3f78SToomas Soome 			x = dataTop[-1].i;
1497*a1bf3f78SToomas Soome 
1498*a1bf3f78SToomas Soome 			prod = ficl2IntegerMultiply(x, y);
1499*a1bf3f78SToomas Soome 			qr   = ficl2IntegerDivideSymmetric(prod, z);
1500*a1bf3f78SToomas Soome 
1501*a1bf3f78SToomas Soome 			dataTop[-1].i = qr.remainder;
1502*a1bf3f78SToomas Soome 			dataTop[0].i = FICL_2UNSIGNED_GET_LOW(qr.quotient);
1503*a1bf3f78SToomas Soome 			continue;
1504*a1bf3f78SToomas Soome 		}
1505*a1bf3f78SToomas Soome 
1506*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
1507*a1bf3f78SToomas Soome 		case ficlInstructionF0:
1508*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(0, 1);
1509*a1bf3f78SToomas Soome 			(++floatTop)->f = 0.0f;
1510*a1bf3f78SToomas Soome 		continue;
1511*a1bf3f78SToomas Soome 
1512*a1bf3f78SToomas Soome 		case ficlInstructionF1:
1513*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(0, 1);
1514*a1bf3f78SToomas Soome 			(++floatTop)->f = 1.0f;
1515*a1bf3f78SToomas Soome 		continue;
1516*a1bf3f78SToomas Soome 
1517*a1bf3f78SToomas Soome 		case ficlInstructionFNeg1:
1518*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(0, 1);
1519*a1bf3f78SToomas Soome 			(++floatTop)->f = -1.0f;
1520*a1bf3f78SToomas Soome 		continue;
1521*a1bf3f78SToomas Soome 
1522*a1bf3f78SToomas Soome 		/*
1523*a1bf3f78SToomas Soome 		 * Floating point literal execution word.
1524*a1bf3f78SToomas Soome 		 */
1525*a1bf3f78SToomas Soome 		case ficlInstructionFLiteralParen:
1526*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(0, 1);
1527*a1bf3f78SToomas Soome 
1528*a1bf3f78SToomas Soome 			/*
1529*a1bf3f78SToomas Soome 			 * Yes, I'm using ->i here,
1530*a1bf3f78SToomas Soome 			 * but it's really a float.  --lch
1531*a1bf3f78SToomas Soome 			 */
1532*a1bf3f78SToomas Soome 			(++floatTop)->i = *ip++;
1533*a1bf3f78SToomas Soome 				continue;
1534*a1bf3f78SToomas Soome 
1535*a1bf3f78SToomas Soome 		/*
1536*a1bf3f78SToomas Soome 		 * Do float addition r1 + r2.
1537*a1bf3f78SToomas Soome 		 * f+ ( r1 r2 -- r )
1538*a1bf3f78SToomas Soome 		 */
1539*a1bf3f78SToomas Soome 		case ficlInstructionFPlus:
1540*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 1);
1541*a1bf3f78SToomas Soome 
1542*a1bf3f78SToomas Soome 			f = (floatTop--)->f;
1543*a1bf3f78SToomas Soome 			floatTop->f += f;
1544*a1bf3f78SToomas Soome 		continue;
1545*a1bf3f78SToomas Soome 
1546*a1bf3f78SToomas Soome 		/*
1547*a1bf3f78SToomas Soome 		 * Do float subtraction r1 - r2.
1548*a1bf3f78SToomas Soome 		 * f- ( r1 r2 -- r )
1549*a1bf3f78SToomas Soome 		 */
1550*a1bf3f78SToomas Soome 		case ficlInstructionFMinus:
1551*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 1);
1552*a1bf3f78SToomas Soome 
1553*a1bf3f78SToomas Soome 			f = (floatTop--)->f;
1554*a1bf3f78SToomas Soome 			floatTop->f -= f;
1555*a1bf3f78SToomas Soome 		continue;
1556*a1bf3f78SToomas Soome 
1557*a1bf3f78SToomas Soome 		/*
1558*a1bf3f78SToomas Soome 		 * Do float multiplication r1 * r2.
1559*a1bf3f78SToomas Soome 		 * f* ( r1 r2 -- r )
1560*a1bf3f78SToomas Soome 		 */
1561*a1bf3f78SToomas Soome 		case ficlInstructionFStar:
1562*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 1);
1563*a1bf3f78SToomas Soome 
1564*a1bf3f78SToomas Soome 			f = (floatTop--)->f;
1565*a1bf3f78SToomas Soome 			floatTop->f *= f;
1566*a1bf3f78SToomas Soome 		continue;
1567*a1bf3f78SToomas Soome 
1568*a1bf3f78SToomas Soome 		/*
1569*a1bf3f78SToomas Soome 		 * Do float negation.
1570*a1bf3f78SToomas Soome 		 * fnegate ( r -- r )
1571*a1bf3f78SToomas Soome 		 */
1572*a1bf3f78SToomas Soome 		case ficlInstructionFNegate:
1573*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 1);
1574*a1bf3f78SToomas Soome 
1575*a1bf3f78SToomas Soome 			floatTop->f = -(floatTop->f);
1576*a1bf3f78SToomas Soome 		continue;
1577*a1bf3f78SToomas Soome 
1578*a1bf3f78SToomas Soome 		/*
1579*a1bf3f78SToomas Soome 		 * Do float division r1 / r2.
1580*a1bf3f78SToomas Soome 		 * f/ ( r1 r2 -- r )
1581*a1bf3f78SToomas Soome 		 */
1582*a1bf3f78SToomas Soome 		case ficlInstructionFSlash:
1583*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 1);
1584*a1bf3f78SToomas Soome 
1585*a1bf3f78SToomas Soome 			f = (floatTop--)->f;
1586*a1bf3f78SToomas Soome 			floatTop->f /= f;
1587*a1bf3f78SToomas Soome 		continue;
1588*a1bf3f78SToomas Soome 
1589*a1bf3f78SToomas Soome 		/*
1590*a1bf3f78SToomas Soome 		 * Do float + integer r + n.
1591*a1bf3f78SToomas Soome 		 * f+i ( r n -- r )
1592*a1bf3f78SToomas Soome 		 */
1593*a1bf3f78SToomas Soome 		case ficlInstructionFPlusI:
1594*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 1);
1595*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1596*a1bf3f78SToomas Soome 
1597*a1bf3f78SToomas Soome 			f = (ficlFloat)(dataTop--)->f;
1598*a1bf3f78SToomas Soome 			floatTop->f += f;
1599*a1bf3f78SToomas Soome 		continue;
1600*a1bf3f78SToomas Soome 
1601*a1bf3f78SToomas Soome 		/*
1602*a1bf3f78SToomas Soome 		 * Do float - integer r - n.
1603*a1bf3f78SToomas Soome 		 * f-i ( r n -- r )
1604*a1bf3f78SToomas Soome 		 */
1605*a1bf3f78SToomas Soome 		case ficlInstructionFMinusI:
1606*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 1);
1607*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1608*a1bf3f78SToomas Soome 
1609*a1bf3f78SToomas Soome 			f = (ficlFloat)(dataTop--)->f;
1610*a1bf3f78SToomas Soome 			floatTop->f -= f;
1611*a1bf3f78SToomas Soome 		continue;
1612*a1bf3f78SToomas Soome 
1613*a1bf3f78SToomas Soome 		/*
1614*a1bf3f78SToomas Soome 		 * Do float * integer r * n.
1615*a1bf3f78SToomas Soome 		 * f*i ( r n -- r )
1616*a1bf3f78SToomas Soome 		 */
1617*a1bf3f78SToomas Soome 		case ficlInstructionFStarI:
1618*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 1);
1619*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1620*a1bf3f78SToomas Soome 
1621*a1bf3f78SToomas Soome 			f = (ficlFloat)(dataTop--)->f;
1622*a1bf3f78SToomas Soome 			floatTop->f *= f;
1623*a1bf3f78SToomas Soome 		continue;
1624*a1bf3f78SToomas Soome 
1625*a1bf3f78SToomas Soome 		/*
1626*a1bf3f78SToomas Soome 		 * Do float / integer r / n.
1627*a1bf3f78SToomas Soome 		 * f/i ( r n -- r )
1628*a1bf3f78SToomas Soome 		 */
1629*a1bf3f78SToomas Soome 		case ficlInstructionFSlashI:
1630*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 1);
1631*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1632*a1bf3f78SToomas Soome 
1633*a1bf3f78SToomas Soome 			f = (ficlFloat)(dataTop--)->f;
1634*a1bf3f78SToomas Soome 			floatTop->f /= f;
1635*a1bf3f78SToomas Soome 			continue;
1636*a1bf3f78SToomas Soome 
1637*a1bf3f78SToomas Soome 		/*
1638*a1bf3f78SToomas Soome 		 * Do integer - float n - r.
1639*a1bf3f78SToomas Soome 		 * i-f ( n r -- r )
1640*a1bf3f78SToomas Soome 		 */
1641*a1bf3f78SToomas Soome 		case ficlInstructionIMinusF:
1642*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 1);
1643*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1644*a1bf3f78SToomas Soome 
1645*a1bf3f78SToomas Soome 			f = (ficlFloat)(dataTop--)->f;
1646*a1bf3f78SToomas Soome 			floatTop->f = f - floatTop->f;
1647*a1bf3f78SToomas Soome 		continue;
1648*a1bf3f78SToomas Soome 
1649*a1bf3f78SToomas Soome 		/*
1650*a1bf3f78SToomas Soome 		 * Do integer / float n / r.
1651*a1bf3f78SToomas Soome 		 * i/f ( n r -- r )
1652*a1bf3f78SToomas Soome 		 */
1653*a1bf3f78SToomas Soome 		case ficlInstructionISlashF:
1654*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 1);
1655*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1656*a1bf3f78SToomas Soome 
1657*a1bf3f78SToomas Soome 			f = (ficlFloat)(dataTop--)->f;
1658*a1bf3f78SToomas Soome 			floatTop->f = f / floatTop->f;
1659*a1bf3f78SToomas Soome 		continue;
1660*a1bf3f78SToomas Soome 
1661*a1bf3f78SToomas Soome 		/*
1662*a1bf3f78SToomas Soome 		 * Do integer to float conversion.
1663*a1bf3f78SToomas Soome 		 * int>float ( n -- r )
1664*a1bf3f78SToomas Soome 		 */
1665*a1bf3f78SToomas Soome 		case ficlInstructionIntToFloat:
1666*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1667*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(0, 1);
1668*a1bf3f78SToomas Soome 
1669*a1bf3f78SToomas Soome 			(++floatTop)->f = ((dataTop--)->f);
1670*a1bf3f78SToomas Soome 		continue;
1671*a1bf3f78SToomas Soome 
1672*a1bf3f78SToomas Soome 		/*
1673*a1bf3f78SToomas Soome 		 * Do float to integer conversion.
1674*a1bf3f78SToomas Soome 		 * float>int ( r -- n )
1675*a1bf3f78SToomas Soome 		 */
1676*a1bf3f78SToomas Soome 		case ficlInstructionFloatToInt:
1677*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
1678*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 0);
1679*a1bf3f78SToomas Soome 
1680*a1bf3f78SToomas Soome 			(++dataTop)->i = ((floatTop--)->i);
1681*a1bf3f78SToomas Soome 		continue;
1682*a1bf3f78SToomas Soome 
1683*a1bf3f78SToomas Soome 		/*
1684*a1bf3f78SToomas Soome 		 * Add a floating point number to contents of a variable.
1685*a1bf3f78SToomas Soome 		 * f+! ( r n -- )
1686*a1bf3f78SToomas Soome 		 */
1687*a1bf3f78SToomas Soome 		case ficlInstructionFPlusStore: {
1688*a1bf3f78SToomas Soome 			ficlCell *cell;
1689*a1bf3f78SToomas Soome 
1690*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1691*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 0);
1692*a1bf3f78SToomas Soome 
1693*a1bf3f78SToomas Soome 			cell = (ficlCell *)(dataTop--)->p;
1694*a1bf3f78SToomas Soome 			cell->f += (floatTop--)->f;
1695*a1bf3f78SToomas Soome 		continue;
1696*a1bf3f78SToomas Soome 		}
1697*a1bf3f78SToomas Soome 
1698*a1bf3f78SToomas Soome 		/*
1699*a1bf3f78SToomas Soome 		 * Do float stack drop.
1700*a1bf3f78SToomas Soome 		 * fdrop ( r -- )
1701*a1bf3f78SToomas Soome 		 */
1702*a1bf3f78SToomas Soome 		case ficlInstructionFDrop:
1703*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 0);
1704*a1bf3f78SToomas Soome 			floatTop--;
1705*a1bf3f78SToomas Soome 		continue;
1706*a1bf3f78SToomas Soome 
1707*a1bf3f78SToomas Soome 		/*
1708*a1bf3f78SToomas Soome 		 * Do float stack ?dup.
1709*a1bf3f78SToomas Soome 		 * f?dup ( r -- r )
1710*a1bf3f78SToomas Soome 		 */
1711*a1bf3f78SToomas Soome 		case ficlInstructionFQuestionDup:
1712*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 2);
1713*a1bf3f78SToomas Soome 
1714*a1bf3f78SToomas Soome 			if (floatTop->f != 0)
1715*a1bf3f78SToomas Soome 				goto FDUP;
1716*a1bf3f78SToomas Soome 
1717*a1bf3f78SToomas Soome 		continue;
1718*a1bf3f78SToomas Soome 
1719*a1bf3f78SToomas Soome 		/*
1720*a1bf3f78SToomas Soome 		 * Do float stack dup.
1721*a1bf3f78SToomas Soome 		 * fdup ( r -- r r )
1722*a1bf3f78SToomas Soome 		 */
1723*a1bf3f78SToomas Soome 		case ficlInstructionFDup:
1724*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 2);
1725*a1bf3f78SToomas Soome 
1726*a1bf3f78SToomas Soome FDUP:
1727*a1bf3f78SToomas Soome 			floatTop[1] = floatTop[0];
1728*a1bf3f78SToomas Soome 			floatTop++;
1729*a1bf3f78SToomas Soome 			continue;
1730*a1bf3f78SToomas Soome 
1731*a1bf3f78SToomas Soome 		/*
1732*a1bf3f78SToomas Soome 		 * Do float stack swap.
1733*a1bf3f78SToomas Soome 		 * fswap ( r1 r2 -- r2 r1 )
1734*a1bf3f78SToomas Soome 		 */
1735*a1bf3f78SToomas Soome 		case ficlInstructionFSwap:
1736*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 2);
1737*a1bf3f78SToomas Soome 
1738*a1bf3f78SToomas Soome 			c = floatTop[0];
1739*a1bf3f78SToomas Soome 			floatTop[0] = floatTop[-1];
1740*a1bf3f78SToomas Soome 			floatTop[-1] = c;
1741*a1bf3f78SToomas Soome 		continue;
1742*a1bf3f78SToomas Soome 
1743*a1bf3f78SToomas Soome 		/*
1744*a1bf3f78SToomas Soome 		 * Do float stack 2drop.
1745*a1bf3f78SToomas Soome 		 * f2drop ( r r -- )
1746*a1bf3f78SToomas Soome 		 */
1747*a1bf3f78SToomas Soome 		case ficlInstructionF2Drop:
1748*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 0);
1749*a1bf3f78SToomas Soome 
1750*a1bf3f78SToomas Soome 			floatTop -= 2;
1751*a1bf3f78SToomas Soome 		continue;
1752*a1bf3f78SToomas Soome 
1753*a1bf3f78SToomas Soome 		/*
1754*a1bf3f78SToomas Soome 		 * Do float stack 2dup.
1755*a1bf3f78SToomas Soome 		 * f2dup ( r1 r2 -- r1 r2 r1 r2 )
1756*a1bf3f78SToomas Soome 		 */
1757*a1bf3f78SToomas Soome 		case ficlInstructionF2Dup:
1758*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 4);
1759*a1bf3f78SToomas Soome 
1760*a1bf3f78SToomas Soome 			floatTop[1] = floatTop[-1];
1761*a1bf3f78SToomas Soome 			floatTop[2] = *floatTop;
1762*a1bf3f78SToomas Soome 			floatTop += 2;
1763*a1bf3f78SToomas Soome 		continue;
1764*a1bf3f78SToomas Soome 
1765*a1bf3f78SToomas Soome 		/*
1766*a1bf3f78SToomas Soome 		 * Do float stack over.
1767*a1bf3f78SToomas Soome 		 * fover ( r1 r2 -- r1 r2 r1 )
1768*a1bf3f78SToomas Soome 		 */
1769*a1bf3f78SToomas Soome 		case ficlInstructionFOver:
1770*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 3);
1771*a1bf3f78SToomas Soome 
1772*a1bf3f78SToomas Soome 			floatTop[1] = floatTop[-1];
1773*a1bf3f78SToomas Soome 			floatTop++;
1774*a1bf3f78SToomas Soome 		continue;
1775*a1bf3f78SToomas Soome 
1776*a1bf3f78SToomas Soome 		/*
1777*a1bf3f78SToomas Soome 		 * Do float stack 2over.
1778*a1bf3f78SToomas Soome 		 * f2over ( r1 r2 r3 -- r1 r2 r3 r1 r2 )
1779*a1bf3f78SToomas Soome 		 */
1780*a1bf3f78SToomas Soome 		case ficlInstructionF2Over:
1781*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(4, 6);
1782*a1bf3f78SToomas Soome 
1783*a1bf3f78SToomas Soome 			floatTop[1] = floatTop[-2];
1784*a1bf3f78SToomas Soome 			floatTop[2] = floatTop[-1];
1785*a1bf3f78SToomas Soome 			floatTop += 2;
1786*a1bf3f78SToomas Soome 		continue;
1787*a1bf3f78SToomas Soome 
1788*a1bf3f78SToomas Soome 		/*
1789*a1bf3f78SToomas Soome 		 * Do float stack pick.
1790*a1bf3f78SToomas Soome 		 * fpick ( n -- r )
1791*a1bf3f78SToomas Soome 		 */
1792*a1bf3f78SToomas Soome 		case ficlInstructionFPick:
1793*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1794*a1bf3f78SToomas Soome 			c = *dataTop--;
1795*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(c.i+2, c.i+3);
1796*a1bf3f78SToomas Soome 
1797*a1bf3f78SToomas Soome 			floatTop[1] = floatTop[- c.i - 1];
1798*a1bf3f78SToomas Soome 		continue;
1799*a1bf3f78SToomas Soome 
1800*a1bf3f78SToomas Soome 		/*
1801*a1bf3f78SToomas Soome 		 * Do float stack rot.
1802*a1bf3f78SToomas Soome 		 * frot ( r1 r2 r3  -- r2 r3 r1 )
1803*a1bf3f78SToomas Soome 		 */
1804*a1bf3f78SToomas Soome 		case ficlInstructionFRot:
1805*a1bf3f78SToomas Soome 			i = 2;
1806*a1bf3f78SToomas Soome 		goto FROLL;
1807*a1bf3f78SToomas Soome 
1808*a1bf3f78SToomas Soome 		/*
1809*a1bf3f78SToomas Soome 		 * Do float stack roll.
1810*a1bf3f78SToomas Soome 		 * froll ( n -- )
1811*a1bf3f78SToomas Soome 		 */
1812*a1bf3f78SToomas Soome 		case ficlInstructionFRoll:
1813*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1814*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
1815*a1bf3f78SToomas Soome 
1816*a1bf3f78SToomas Soome 			if (i < 1)
1817*a1bf3f78SToomas Soome 				continue;
1818*a1bf3f78SToomas Soome 
1819*a1bf3f78SToomas Soome FROLL:
1820*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(i+1, i+2);
1821*a1bf3f78SToomas Soome 			c = floatTop[-i];
1822*a1bf3f78SToomas Soome 			memmove(floatTop - i, floatTop - (i - 1),
1823*a1bf3f78SToomas Soome 			    i * sizeof (ficlCell));
1824*a1bf3f78SToomas Soome 			*floatTop = c;
1825*a1bf3f78SToomas Soome 
1826*a1bf3f78SToomas Soome 		continue;
1827*a1bf3f78SToomas Soome 
1828*a1bf3f78SToomas Soome 		/*
1829*a1bf3f78SToomas Soome 		 * Do float stack -rot.
1830*a1bf3f78SToomas Soome 		 * f-rot ( r1 r2 r3  -- r3 r1 r2 )
1831*a1bf3f78SToomas Soome 		 */
1832*a1bf3f78SToomas Soome 		case ficlInstructionFMinusRot:
1833*a1bf3f78SToomas Soome 			i = 2;
1834*a1bf3f78SToomas Soome 			goto FMINUSROLL;
1835*a1bf3f78SToomas Soome 
1836*a1bf3f78SToomas Soome 
1837*a1bf3f78SToomas Soome 		/*
1838*a1bf3f78SToomas Soome 		 * Do float stack -roll.
1839*a1bf3f78SToomas Soome 		 * f-roll ( n -- )
1840*a1bf3f78SToomas Soome 		 */
1841*a1bf3f78SToomas Soome 		case ficlInstructionFMinusRoll:
1842*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1843*a1bf3f78SToomas Soome 			i = (dataTop--)->i;
1844*a1bf3f78SToomas Soome 
1845*a1bf3f78SToomas Soome 			if (i < 1)
1846*a1bf3f78SToomas Soome 				continue;
1847*a1bf3f78SToomas Soome 
1848*a1bf3f78SToomas Soome FMINUSROLL:
1849*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(i+1, i+2);
1850*a1bf3f78SToomas Soome 			c = *floatTop;
1851*a1bf3f78SToomas Soome 			memmove(floatTop - (i - 1), floatTop - i,
1852*a1bf3f78SToomas Soome 			    i * sizeof (ficlCell));
1853*a1bf3f78SToomas Soome 			floatTop[-i] = c;
1854*a1bf3f78SToomas Soome 
1855*a1bf3f78SToomas Soome 		continue;
1856*a1bf3f78SToomas Soome 
1857*a1bf3f78SToomas Soome 		/*
1858*a1bf3f78SToomas Soome 		 * Do float stack 2swap
1859*a1bf3f78SToomas Soome 		 * f2swap ( r1 r2 r3 r4  -- r3 r4 r1 r2 )
1860*a1bf3f78SToomas Soome 		 */
1861*a1bf3f78SToomas Soome 		case ficlInstructionF2Swap: {
1862*a1bf3f78SToomas Soome 			ficlCell c2;
1863*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(4, 4);
1864*a1bf3f78SToomas Soome 
1865*a1bf3f78SToomas Soome 			c = *floatTop;
1866*a1bf3f78SToomas Soome 			c2 = floatTop[-1];
1867*a1bf3f78SToomas Soome 
1868*a1bf3f78SToomas Soome 			*floatTop = floatTop[-2];
1869*a1bf3f78SToomas Soome 			floatTop[-1] = floatTop[-3];
1870*a1bf3f78SToomas Soome 
1871*a1bf3f78SToomas Soome 			floatTop[-2] = c;
1872*a1bf3f78SToomas Soome 			floatTop[-3] = c2;
1873*a1bf3f78SToomas Soome 		continue;
1874*a1bf3f78SToomas Soome 		}
1875*a1bf3f78SToomas Soome 
1876*a1bf3f78SToomas Soome 		/*
1877*a1bf3f78SToomas Soome 		 * Do float 0= comparison r = 0.0.
1878*a1bf3f78SToomas Soome 		 * f0= ( r -- T/F )
1879*a1bf3f78SToomas Soome 		 */
1880*a1bf3f78SToomas Soome 		case ficlInstructionF0Equals:
1881*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 0);
1882*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
1883*a1bf3f78SToomas Soome 
1884*a1bf3f78SToomas Soome 			(++dataTop)->i = FICL_BOOL((floatTop--)->f != 0.0f);
1885*a1bf3f78SToomas Soome 		continue;
1886*a1bf3f78SToomas Soome 
1887*a1bf3f78SToomas Soome 		/*
1888*a1bf3f78SToomas Soome 		 * Do float 0< comparison r < 0.0.
1889*a1bf3f78SToomas Soome 		 * f0< ( r -- T/F )
1890*a1bf3f78SToomas Soome 		 */
1891*a1bf3f78SToomas Soome 		case ficlInstructionF0Less:
1892*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 0);
1893*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
1894*a1bf3f78SToomas Soome 
1895*a1bf3f78SToomas Soome 			(++dataTop)->i = FICL_BOOL((floatTop--)->f < 0.0f);
1896*a1bf3f78SToomas Soome 		continue;
1897*a1bf3f78SToomas Soome 
1898*a1bf3f78SToomas Soome 		/*
1899*a1bf3f78SToomas Soome 		 * Do float 0> comparison r > 0.0.
1900*a1bf3f78SToomas Soome 		 * f0> ( r -- T/F )
1901*a1bf3f78SToomas Soome 		 */
1902*a1bf3f78SToomas Soome 		case ficlInstructionF0Greater:
1903*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 0);
1904*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
1905*a1bf3f78SToomas Soome 
1906*a1bf3f78SToomas Soome 			(++dataTop)->i = FICL_BOOL((floatTop--)->f > 0.0f);
1907*a1bf3f78SToomas Soome 		continue;
1908*a1bf3f78SToomas Soome 
1909*a1bf3f78SToomas Soome 		/*
1910*a1bf3f78SToomas Soome 		 * Do float = comparison r1 = r2.
1911*a1bf3f78SToomas Soome 		 * f= ( r1 r2 -- T/F )
1912*a1bf3f78SToomas Soome 		 */
1913*a1bf3f78SToomas Soome 		case ficlInstructionFEquals:
1914*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 0);
1915*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
1916*a1bf3f78SToomas Soome 
1917*a1bf3f78SToomas Soome 			f = (floatTop--)->f;
1918*a1bf3f78SToomas Soome 			(++dataTop)->i = FICL_BOOL((floatTop--)->f == f);
1919*a1bf3f78SToomas Soome 		continue;
1920*a1bf3f78SToomas Soome 
1921*a1bf3f78SToomas Soome 		/*
1922*a1bf3f78SToomas Soome 		 * Do float < comparison r1 < r2.
1923*a1bf3f78SToomas Soome 		 * f< ( r1 r2 -- T/F )
1924*a1bf3f78SToomas Soome 		 */
1925*a1bf3f78SToomas Soome 		case ficlInstructionFLess:
1926*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 0);
1927*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
1928*a1bf3f78SToomas Soome 
1929*a1bf3f78SToomas Soome 			f = (floatTop--)->f;
1930*a1bf3f78SToomas Soome 			(++dataTop)->i = FICL_BOOL((floatTop--)->f < f);
1931*a1bf3f78SToomas Soome 		continue;
1932*a1bf3f78SToomas Soome 
1933*a1bf3f78SToomas Soome 		/*
1934*a1bf3f78SToomas Soome 		 * Do float > comparison r1 > r2.
1935*a1bf3f78SToomas Soome 		 * f> ( r1 r2 -- T/F )
1936*a1bf3f78SToomas Soome 		 */
1937*a1bf3f78SToomas Soome 		case ficlInstructionFGreater:
1938*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(2, 0);
1939*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
1940*a1bf3f78SToomas Soome 
1941*a1bf3f78SToomas Soome 			f = (floatTop--)->f;
1942*a1bf3f78SToomas Soome 			(++dataTop)->i = FICL_BOOL((floatTop--)->f > f);
1943*a1bf3f78SToomas Soome 		continue;
1944*a1bf3f78SToomas Soome 
1945*a1bf3f78SToomas Soome 
1946*a1bf3f78SToomas Soome 		/*
1947*a1bf3f78SToomas Soome 		 * Move float to param stack (assumes they both fit in a
1948*a1bf3f78SToomas Soome 		 * single ficlCell) f>s
1949*a1bf3f78SToomas Soome 		 */
1950*a1bf3f78SToomas Soome 		case ficlInstructionFFrom:
1951*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(1, 0);
1952*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
1953*a1bf3f78SToomas Soome 
1954*a1bf3f78SToomas Soome 			*++dataTop = *floatTop--;
1955*a1bf3f78SToomas Soome 		continue;
1956*a1bf3f78SToomas Soome 
1957*a1bf3f78SToomas Soome 		case ficlInstructionToF:
1958*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(0, 1);
1959*a1bf3f78SToomas Soome 			CHECK_STACK(1, 0);
1960*a1bf3f78SToomas Soome 
1961*a1bf3f78SToomas Soome 			*++floatTop = *dataTop--;
1962*a1bf3f78SToomas Soome 		continue;
1963*a1bf3f78SToomas Soome 
1964*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */
1965*a1bf3f78SToomas Soome 
1966*a1bf3f78SToomas Soome 		/*
1967*a1bf3f78SToomas Soome 		 * c o l o n P a r e n
1968*a1bf3f78SToomas Soome 		 * This is the code that executes a colon definition. It
1969*a1bf3f78SToomas Soome 		 * assumes that the virtual machine is running a "next" loop
1970*a1bf3f78SToomas Soome 		 * (See the vm.c for its implementation of member function
1971*a1bf3f78SToomas Soome 		 * vmExecute()). The colon code simply copies the address of
1972*a1bf3f78SToomas Soome 		 * the first word in the list of words to interpret into IP
1973*a1bf3f78SToomas Soome 		 * after saving its old value. When we return to the "next"
1974*a1bf3f78SToomas Soome 		 * loop, the virtual machine will call the code for each
1975*a1bf3f78SToomas Soome 		 * word in turn.
1976*a1bf3f78SToomas Soome 		 */
1977*a1bf3f78SToomas Soome 		case ficlInstructionColonParen:
1978*a1bf3f78SToomas Soome 			(++returnTop)->p = (void *)ip;
1979*a1bf3f78SToomas Soome 			ip = (ficlInstruction *)(fw->param);
1980*a1bf3f78SToomas Soome 		continue;
1981*a1bf3f78SToomas Soome 
1982*a1bf3f78SToomas Soome 		case ficlInstructionCreateParen:
1983*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
1984*a1bf3f78SToomas Soome 			(++dataTop)->p = (fw->param + 1);
1985*a1bf3f78SToomas Soome 		continue;
1986*a1bf3f78SToomas Soome 
1987*a1bf3f78SToomas Soome 		case ficlInstructionVariableParen:
1988*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
1989*a1bf3f78SToomas Soome 			(++dataTop)->p = fw->param;
1990*a1bf3f78SToomas Soome 		continue;
1991*a1bf3f78SToomas Soome 
1992*a1bf3f78SToomas Soome 		/*
1993*a1bf3f78SToomas Soome 		 * c o n s t a n t P a r e n
1994*a1bf3f78SToomas Soome 		 * This is the run-time code for "constant". It simply returns
1995*a1bf3f78SToomas Soome 		 * the contents of its word's first data ficlCell.
1996*a1bf3f78SToomas Soome 		 */
1997*a1bf3f78SToomas Soome 
1998*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
1999*a1bf3f78SToomas Soome 		case ficlInstructionF2ConstantParen:
2000*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(0, 2);
2001*a1bf3f78SToomas Soome 			FLOAT_PUSH_CELL_POINTER_DOUBLE(fw->param);
2002*a1bf3f78SToomas Soome 
2003*a1bf3f78SToomas Soome 		case ficlInstructionFConstantParen:
2004*a1bf3f78SToomas Soome 			CHECK_FLOAT_STACK(0, 1);
2005*a1bf3f78SToomas Soome 			FLOAT_PUSH_CELL_POINTER(fw->param);
2006*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */
2007*a1bf3f78SToomas Soome 
2008*a1bf3f78SToomas Soome 		case ficlInstruction2ConstantParen:
2009*a1bf3f78SToomas Soome 			CHECK_STACK(0, 2);
2010*a1bf3f78SToomas Soome 			PUSH_CELL_POINTER_DOUBLE(fw->param);
2011*a1bf3f78SToomas Soome 
2012*a1bf3f78SToomas Soome 		case ficlInstructionConstantParen:
2013*a1bf3f78SToomas Soome 			CHECK_STACK(0, 1);
2014*a1bf3f78SToomas Soome 			PUSH_CELL_POINTER(fw->param);
2015*a1bf3f78SToomas Soome 
2016*a1bf3f78SToomas Soome #if FICL_WANT_USER
2017*a1bf3f78SToomas Soome 		case ficlInstructionUserParen: {
2018*a1bf3f78SToomas Soome 			ficlInteger i = fw->param[0].i;
2019*a1bf3f78SToomas Soome 			(++dataTop)->p = &vm->user[i];
2020*a1bf3f78SToomas Soome 		continue;
2021*a1bf3f78SToomas Soome 		}
2022*a1bf3f78SToomas Soome #endif
2023*a1bf3f78SToomas Soome 
2024*a1bf3f78SToomas Soome 		default:
2025*a1bf3f78SToomas Soome 		/*
2026*a1bf3f78SToomas Soome 		 * Clever hack, or evil coding?  You be the judge.
2027*a1bf3f78SToomas Soome 		 *
2028*a1bf3f78SToomas Soome 		 * If the word we've been asked to execute is in fact
2029*a1bf3f78SToomas Soome 		 * an *instruction*, we grab the instruction, stow it
2030*a1bf3f78SToomas Soome 		 * in "i" (our local cache of *ip), and *jump* to the
2031*a1bf3f78SToomas Soome 		 * top of the switch statement.  --lch
2032*a1bf3f78SToomas Soome 		 */
2033*a1bf3f78SToomas Soome 			if (((ficlInstruction)fw->code >
2034*a1bf3f78SToomas Soome 			    ficlInstructionInvalid) &&
2035*a1bf3f78SToomas Soome 			    ((ficlInstruction)fw->code < ficlInstructionLast)) {
2036*a1bf3f78SToomas Soome 				instruction = (ficlInstruction)fw->code;
2037*a1bf3f78SToomas Soome 				goto AGAIN;
2038*a1bf3f78SToomas Soome 			}
2039*a1bf3f78SToomas Soome 
2040*a1bf3f78SToomas Soome 			LOCAL_VARIABLE_SPILL;
2041*a1bf3f78SToomas Soome 			(vm)->runningWord = fw;
2042*a1bf3f78SToomas Soome 			fw->code(vm);
2043*a1bf3f78SToomas Soome 			LOCAL_VARIABLE_REFILL;
2044*a1bf3f78SToomas Soome 		continue;
2045*a1bf3f78SToomas Soome 		}
2046*a1bf3f78SToomas Soome 	}
2047*a1bf3f78SToomas Soome 
2048*a1bf3f78SToomas Soome 	LOCAL_VARIABLE_SPILL;
2049*a1bf3f78SToomas Soome 	vm->exceptionHandler = oldExceptionHandler;
2050*a1bf3f78SToomas Soome }
2051*a1bf3f78SToomas Soome 
2052*a1bf3f78SToomas Soome /*
2053*a1bf3f78SToomas Soome  * v m G e t D i c t
2054*a1bf3f78SToomas Soome  * Returns the address dictionary for this VM's system
2055*a1bf3f78SToomas Soome  */
2056*a1bf3f78SToomas Soome ficlDictionary *
2057*a1bf3f78SToomas Soome ficlVmGetDictionary(ficlVm *vm)
2058*a1bf3f78SToomas Soome {
2059*a1bf3f78SToomas Soome 	FICL_VM_ASSERT(vm, vm);
2060*a1bf3f78SToomas Soome 	return (vm->callback.system->dictionary);
2061*a1bf3f78SToomas Soome }
2062*a1bf3f78SToomas Soome 
2063*a1bf3f78SToomas Soome /*
2064*a1bf3f78SToomas Soome  * v m G e t S t r i n g
2065*a1bf3f78SToomas Soome  * Parses a string out of the VM input buffer and copies up to the first
2066*a1bf3f78SToomas Soome  * FICL_COUNTED_STRING_MAX characters to the supplied destination buffer, a
2067*a1bf3f78SToomas Soome  * ficlCountedString. The destination string is NULL terminated.
2068*a1bf3f78SToomas Soome  *
2069*a1bf3f78SToomas Soome  * Returns the address of the first unused character in the dest buffer.
2070*a1bf3f78SToomas Soome  */
2071*a1bf3f78SToomas Soome char *
2072*a1bf3f78SToomas Soome ficlVmGetString(ficlVm *vm, ficlCountedString *counted, char delimiter)
2073*a1bf3f78SToomas Soome {
2074*a1bf3f78SToomas Soome 	ficlString s = ficlVmParseStringEx(vm, delimiter, 0);
2075*a1bf3f78SToomas Soome 
2076*a1bf3f78SToomas Soome 	if (FICL_STRING_GET_LENGTH(s) > FICL_COUNTED_STRING_MAX) {
2077*a1bf3f78SToomas Soome 		FICL_STRING_SET_LENGTH(s, FICL_COUNTED_STRING_MAX);
2078*a1bf3f78SToomas Soome 	}
2079*a1bf3f78SToomas Soome 
2080*a1bf3f78SToomas Soome 	strncpy(counted->text, FICL_STRING_GET_POINTER(s),
2081*a1bf3f78SToomas Soome 	    FICL_STRING_GET_LENGTH(s));
2082*a1bf3f78SToomas Soome 	counted->text[FICL_STRING_GET_LENGTH(s)] = '\0';
2083*a1bf3f78SToomas Soome 	counted->length = (ficlUnsigned8)FICL_STRING_GET_LENGTH(s);
2084*a1bf3f78SToomas Soome 
2085*a1bf3f78SToomas Soome 	return (counted->text + FICL_STRING_GET_LENGTH(s) + 1);
2086*a1bf3f78SToomas Soome }
2087*a1bf3f78SToomas Soome 
2088*a1bf3f78SToomas Soome /*
2089*a1bf3f78SToomas Soome  * v m G e t W o r d
2090*a1bf3f78SToomas Soome  * vmGetWord calls vmGetWord0 repeatedly until it gets a string with
2091*a1bf3f78SToomas Soome  * non-zero length.
2092*a1bf3f78SToomas Soome  */
2093*a1bf3f78SToomas Soome ficlString
2094*a1bf3f78SToomas Soome ficlVmGetWord(ficlVm *vm)
2095*a1bf3f78SToomas Soome {
2096*a1bf3f78SToomas Soome 	ficlString s = ficlVmGetWord0(vm);
2097*a1bf3f78SToomas Soome 
2098*a1bf3f78SToomas Soome 	if (FICL_STRING_GET_LENGTH(s) == 0) {
2099*a1bf3f78SToomas Soome 		ficlVmThrow(vm, FICL_VM_STATUS_RESTART);
2100*a1bf3f78SToomas Soome 	}
2101*a1bf3f78SToomas Soome 
2102*a1bf3f78SToomas Soome 	return (s);
2103*a1bf3f78SToomas Soome }
2104*a1bf3f78SToomas Soome 
2105*a1bf3f78SToomas Soome /*
2106*a1bf3f78SToomas Soome  * v m G e t W o r d 0
2107*a1bf3f78SToomas Soome  * Skip leading whitespace and parse a space delimited word from the tib.
2108*a1bf3f78SToomas Soome  * Returns the start address and length of the word. Updates the tib
2109*a1bf3f78SToomas Soome  * to reflect characters consumed, including the trailing delimiter.
2110*a1bf3f78SToomas Soome  * If there's nothing of interest in the tib, returns zero. This function
2111*a1bf3f78SToomas Soome  * does not use vmParseString because it uses isspace() rather than a
2112*a1bf3f78SToomas Soome  * single  delimiter character.
2113*a1bf3f78SToomas Soome  */
2114*a1bf3f78SToomas Soome ficlString
2115*a1bf3f78SToomas Soome ficlVmGetWord0(ficlVm *vm)
2116*a1bf3f78SToomas Soome {
2117*a1bf3f78SToomas Soome 	char *trace = ficlVmGetInBuf(vm);
2118*a1bf3f78SToomas Soome 	char *stop = ficlVmGetInBufEnd(vm);
2119*a1bf3f78SToomas Soome 	ficlString s;
2120*a1bf3f78SToomas Soome 	ficlUnsigned length = 0;
2121*a1bf3f78SToomas Soome 	char c = 0;
2122*a1bf3f78SToomas Soome 
2123*a1bf3f78SToomas Soome 	trace = ficlStringSkipSpace(trace, stop);
2124*a1bf3f78SToomas Soome 	FICL_STRING_SET_POINTER(s, trace);
2125*a1bf3f78SToomas Soome 
2126*a1bf3f78SToomas Soome 	/* Please leave this loop this way; it makes Purify happier.  --lch */
2127*a1bf3f78SToomas Soome 	for (;;) {
2128*a1bf3f78SToomas Soome 		if (trace == stop)
2129*a1bf3f78SToomas Soome 			break;
2130*a1bf3f78SToomas Soome 		c = *trace;
2131*a1bf3f78SToomas Soome 		if (isspace((unsigned char)c))
2132*a1bf3f78SToomas Soome 			break;
2133*a1bf3f78SToomas Soome 		length++;
2134*a1bf3f78SToomas Soome 		trace++;
2135*a1bf3f78SToomas Soome 	}
2136*a1bf3f78SToomas Soome 
2137*a1bf3f78SToomas Soome 	FICL_STRING_SET_LENGTH(s, length);
2138*a1bf3f78SToomas Soome 
2139*a1bf3f78SToomas Soome 	/* skip one trailing delimiter */
2140*a1bf3f78SToomas Soome 	if ((trace != stop) && isspace((unsigned char)c))
2141*a1bf3f78SToomas Soome 		trace++;
2142*a1bf3f78SToomas Soome 
2143*a1bf3f78SToomas Soome 	ficlVmUpdateTib(vm, trace);
2144*a1bf3f78SToomas Soome 
2145*a1bf3f78SToomas Soome 	return (s);
2146*a1bf3f78SToomas Soome }
2147*a1bf3f78SToomas Soome 
2148*a1bf3f78SToomas Soome /*
2149*a1bf3f78SToomas Soome  * v m G e t W o r d T o P a d
2150*a1bf3f78SToomas Soome  * Does vmGetWord and copies the result to the pad as a NULL terminated
2151*a1bf3f78SToomas Soome  * string. Returns the length of the string. If the string is too long
2152*a1bf3f78SToomas Soome  * to fit in the pad, it is truncated.
2153*a1bf3f78SToomas Soome  */
2154*a1bf3f78SToomas Soome int
2155*a1bf3f78SToomas Soome ficlVmGetWordToPad(ficlVm *vm)
2156*a1bf3f78SToomas Soome {
2157*a1bf3f78SToomas Soome 	ficlString s;
2158*a1bf3f78SToomas Soome 	char *pad = (char *)vm->pad;
2159*a1bf3f78SToomas Soome 	s = ficlVmGetWord(vm);
2160*a1bf3f78SToomas Soome 
2161*a1bf3f78SToomas Soome 	if (FICL_STRING_GET_LENGTH(s) > FICL_PAD_SIZE)
2162*a1bf3f78SToomas Soome 		FICL_STRING_SET_LENGTH(s, FICL_PAD_SIZE);
2163*a1bf3f78SToomas Soome 
2164*a1bf3f78SToomas Soome 	strncpy(pad, FICL_STRING_GET_POINTER(s), FICL_STRING_GET_LENGTH(s));
2165*a1bf3f78SToomas Soome 	pad[FICL_STRING_GET_LENGTH(s)] = '\0';
2166*a1bf3f78SToomas Soome 	return ((int)(FICL_STRING_GET_LENGTH(s)));
2167*a1bf3f78SToomas Soome }
2168*a1bf3f78SToomas Soome 
2169*a1bf3f78SToomas Soome /*
2170*a1bf3f78SToomas Soome  * v m P a r s e S t r i n g
2171*a1bf3f78SToomas Soome  * Parses a string out of the input buffer using the delimiter
2172*a1bf3f78SToomas Soome  * specified. Skips leading delimiters, marks the start of the string,
2173*a1bf3f78SToomas Soome  * and counts characters to the next delimiter it encounters. It then
2174*a1bf3f78SToomas Soome  * updates the vm input buffer to consume all these chars, including the
2175*a1bf3f78SToomas Soome  * trailing delimiter.
2176*a1bf3f78SToomas Soome  * Returns the address and length of the parsed string, not including the
2177*a1bf3f78SToomas Soome  * trailing delimiter.
2178*a1bf3f78SToomas Soome  */
2179*a1bf3f78SToomas Soome ficlString
2180*a1bf3f78SToomas Soome ficlVmParseString(ficlVm *vm, char delimiter)
2181*a1bf3f78SToomas Soome {
2182*a1bf3f78SToomas Soome 	return (ficlVmParseStringEx(vm, delimiter, 1));
2183*a1bf3f78SToomas Soome }
2184*a1bf3f78SToomas Soome 
2185*a1bf3f78SToomas Soome ficlString
2186*a1bf3f78SToomas Soome ficlVmParseStringEx(ficlVm *vm, char delimiter, char skipLeadingDelimiters)
2187*a1bf3f78SToomas Soome {
2188*a1bf3f78SToomas Soome 	ficlString s;
2189*a1bf3f78SToomas Soome 	char *trace = ficlVmGetInBuf(vm);
2190*a1bf3f78SToomas Soome 	char *stop = ficlVmGetInBufEnd(vm);
2191*a1bf3f78SToomas Soome 	char c;
2192*a1bf3f78SToomas Soome 
2193*a1bf3f78SToomas Soome 	if (skipLeadingDelimiters) {
2194*a1bf3f78SToomas Soome 		while ((trace != stop) && (*trace == delimiter))
2195*a1bf3f78SToomas Soome 			trace++;
2196*a1bf3f78SToomas Soome 	}
2197*a1bf3f78SToomas Soome 
2198*a1bf3f78SToomas Soome 	FICL_STRING_SET_POINTER(s, trace);    /* mark start of text */
2199*a1bf3f78SToomas Soome 
2200*a1bf3f78SToomas Soome 	/* find next delimiter or end of line */
2201*a1bf3f78SToomas Soome 	for (c = *trace;
2202*a1bf3f78SToomas Soome 	    (trace != stop) && (c != delimiter) && (c != '\r') && (c != '\n');
2203*a1bf3f78SToomas Soome 	    c = *++trace) {
2204*a1bf3f78SToomas Soome 		;
2205*a1bf3f78SToomas Soome 	}
2206*a1bf3f78SToomas Soome 
2207*a1bf3f78SToomas Soome 	/* set length of result */
2208*a1bf3f78SToomas Soome 	FICL_STRING_SET_LENGTH(s, trace - FICL_STRING_GET_POINTER(s));
2209*a1bf3f78SToomas Soome 
2210*a1bf3f78SToomas Soome 	/* gobble trailing delimiter */
2211*a1bf3f78SToomas Soome 	if ((trace != stop) && (*trace == delimiter))
2212*a1bf3f78SToomas Soome 		trace++;
2213*a1bf3f78SToomas Soome 
2214*a1bf3f78SToomas Soome 	ficlVmUpdateTib(vm, trace);
2215*a1bf3f78SToomas Soome 	return (s);
2216*a1bf3f78SToomas Soome }
2217*a1bf3f78SToomas Soome 
2218*a1bf3f78SToomas Soome 
2219*a1bf3f78SToomas Soome /*
2220*a1bf3f78SToomas Soome  * v m P o p
2221*a1bf3f78SToomas Soome  */
2222*a1bf3f78SToomas Soome ficlCell
2223*a1bf3f78SToomas Soome ficlVmPop(ficlVm *vm)
2224*a1bf3f78SToomas Soome {
2225*a1bf3f78SToomas Soome 	return (ficlStackPop(vm->dataStack));
2226*a1bf3f78SToomas Soome }
2227*a1bf3f78SToomas Soome 
2228*a1bf3f78SToomas Soome /*
2229*a1bf3f78SToomas Soome  * v m P u s h
2230*a1bf3f78SToomas Soome  */
2231*a1bf3f78SToomas Soome void
2232*a1bf3f78SToomas Soome ficlVmPush(ficlVm *vm, ficlCell c)
2233*a1bf3f78SToomas Soome {
2234*a1bf3f78SToomas Soome 	ficlStackPush(vm->dataStack, c);
2235*a1bf3f78SToomas Soome }
2236*a1bf3f78SToomas Soome 
2237*a1bf3f78SToomas Soome /*
2238*a1bf3f78SToomas Soome  * v m P o p I P
2239*a1bf3f78SToomas Soome  */
2240*a1bf3f78SToomas Soome void
2241*a1bf3f78SToomas Soome ficlVmPopIP(ficlVm *vm)
2242*a1bf3f78SToomas Soome {
2243*a1bf3f78SToomas Soome 	vm->ip = (ficlIp)(ficlStackPopPointer(vm->returnStack));
2244*a1bf3f78SToomas Soome }
2245*a1bf3f78SToomas Soome 
2246*a1bf3f78SToomas Soome /*
2247*a1bf3f78SToomas Soome  * v m P u s h I P
2248*a1bf3f78SToomas Soome  */
2249*a1bf3f78SToomas Soome void
2250*a1bf3f78SToomas Soome ficlVmPushIP(ficlVm *vm, ficlIp newIP)
2251*a1bf3f78SToomas Soome {
2252*a1bf3f78SToomas Soome 	ficlStackPushPointer(vm->returnStack, (void *)vm->ip);
2253*a1bf3f78SToomas Soome 	vm->ip = newIP;
2254*a1bf3f78SToomas Soome }
2255*a1bf3f78SToomas Soome 
2256*a1bf3f78SToomas Soome /*
2257*a1bf3f78SToomas Soome  * v m P u s h T i b
2258*a1bf3f78SToomas Soome  * Binds the specified input string to the VM and clears >IN (the index)
2259*a1bf3f78SToomas Soome  */
2260*a1bf3f78SToomas Soome void
2261*a1bf3f78SToomas Soome ficlVmPushTib(ficlVm *vm, char *text, ficlInteger nChars, ficlTIB *pSaveTib)
2262*a1bf3f78SToomas Soome {
2263*a1bf3f78SToomas Soome 	if (pSaveTib) {
2264*a1bf3f78SToomas Soome 		*pSaveTib = vm->tib;
2265*a1bf3f78SToomas Soome 	}
2266*a1bf3f78SToomas Soome 	vm->tib.text = text;
2267*a1bf3f78SToomas Soome 	vm->tib.end = text + nChars;
2268*a1bf3f78SToomas Soome 	vm->tib.index = 0;
2269*a1bf3f78SToomas Soome }
2270*a1bf3f78SToomas Soome 
2271*a1bf3f78SToomas Soome void
2272*a1bf3f78SToomas Soome ficlVmPopTib(ficlVm *vm, ficlTIB *pTib)
2273*a1bf3f78SToomas Soome {
2274*a1bf3f78SToomas Soome 	if (pTib) {
2275*a1bf3f78SToomas Soome 		vm->tib = *pTib;
2276*a1bf3f78SToomas Soome 	}
2277*a1bf3f78SToomas Soome }
2278*a1bf3f78SToomas Soome 
2279*a1bf3f78SToomas Soome /*
2280*a1bf3f78SToomas Soome  * v m Q u i t
2281*a1bf3f78SToomas Soome  */
2282*a1bf3f78SToomas Soome void
2283*a1bf3f78SToomas Soome ficlVmQuit(ficlVm *vm)
2284*a1bf3f78SToomas Soome {
2285*a1bf3f78SToomas Soome 	ficlStackReset(vm->returnStack);
2286*a1bf3f78SToomas Soome 	vm->restart = 0;
2287*a1bf3f78SToomas Soome 	vm->ip = NULL;
2288*a1bf3f78SToomas Soome 	vm->runningWord = NULL;
2289*a1bf3f78SToomas Soome 	vm->state = FICL_VM_STATE_INTERPRET;
2290*a1bf3f78SToomas Soome 	vm->tib.text = NULL;
2291*a1bf3f78SToomas Soome 	vm->tib.end = NULL;
2292*a1bf3f78SToomas Soome 	vm->tib.index = 0;
2293*a1bf3f78SToomas Soome 	vm->pad[0] = '\0';
2294*a1bf3f78SToomas Soome 	vm->sourceId.i = 0;
2295*a1bf3f78SToomas Soome }
2296*a1bf3f78SToomas Soome 
2297*a1bf3f78SToomas Soome /*
2298*a1bf3f78SToomas Soome  * v m R e s e t
2299*a1bf3f78SToomas Soome  */
2300*a1bf3f78SToomas Soome void
2301*a1bf3f78SToomas Soome ficlVmReset(ficlVm *vm)
2302*a1bf3f78SToomas Soome {
2303*a1bf3f78SToomas Soome 	ficlVmQuit(vm);
2304*a1bf3f78SToomas Soome 	ficlStackReset(vm->dataStack);
2305*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
2306*a1bf3f78SToomas Soome 	ficlStackReset(vm->floatStack);
2307*a1bf3f78SToomas Soome #endif
2308*a1bf3f78SToomas Soome 	vm->base = 10;
2309*a1bf3f78SToomas Soome }
2310*a1bf3f78SToomas Soome 
2311*a1bf3f78SToomas Soome /*
2312*a1bf3f78SToomas Soome  * v m S e t T e x t O u t
2313*a1bf3f78SToomas Soome  * Binds the specified output callback to the vm. If you pass NULL,
2314*a1bf3f78SToomas Soome  * binds the default output function (ficlTextOut)
2315*a1bf3f78SToomas Soome  */
2316*a1bf3f78SToomas Soome void
2317*a1bf3f78SToomas Soome ficlVmSetTextOut(ficlVm *vm, ficlOutputFunction textOut)
2318*a1bf3f78SToomas Soome {
2319*a1bf3f78SToomas Soome 	vm->callback.textOut = textOut;
2320*a1bf3f78SToomas Soome }
2321*a1bf3f78SToomas Soome 
2322*a1bf3f78SToomas Soome void
2323*a1bf3f78SToomas Soome ficlVmTextOut(ficlVm *vm, char *text)
2324*a1bf3f78SToomas Soome {
2325*a1bf3f78SToomas Soome 	ficlCallbackTextOut((ficlCallback *)vm, text);
2326*a1bf3f78SToomas Soome }
2327*a1bf3f78SToomas Soome 
2328*a1bf3f78SToomas Soome 
2329*a1bf3f78SToomas Soome void
2330*a1bf3f78SToomas Soome ficlVmErrorOut(ficlVm *vm, char *text)
2331*a1bf3f78SToomas Soome {
2332*a1bf3f78SToomas Soome 	ficlCallbackErrorOut((ficlCallback *)vm, text);
2333*a1bf3f78SToomas Soome }
2334*a1bf3f78SToomas Soome 
2335*a1bf3f78SToomas Soome 
2336*a1bf3f78SToomas Soome /*
2337*a1bf3f78SToomas Soome  * v m T h r o w
2338*a1bf3f78SToomas Soome  */
2339*a1bf3f78SToomas Soome void
2340*a1bf3f78SToomas Soome ficlVmThrow(ficlVm *vm, int except)
2341*a1bf3f78SToomas Soome {
2342*a1bf3f78SToomas Soome 	if (vm->exceptionHandler)
2343*a1bf3f78SToomas Soome 		longjmp(*(vm->exceptionHandler), except);
2344*a1bf3f78SToomas Soome }
2345*a1bf3f78SToomas Soome 
2346*a1bf3f78SToomas Soome void
2347*a1bf3f78SToomas Soome ficlVmThrowError(ficlVm *vm, char *fmt, ...)
2348*a1bf3f78SToomas Soome {
2349*a1bf3f78SToomas Soome 	va_list list;
2350*a1bf3f78SToomas Soome 
2351*a1bf3f78SToomas Soome 	va_start(list, fmt);
2352*a1bf3f78SToomas Soome 	vsprintf(vm->pad, fmt, list);
2353*a1bf3f78SToomas Soome 	va_end(list);
2354*a1bf3f78SToomas Soome 	strcat(vm->pad, "\n");
2355*a1bf3f78SToomas Soome 
2356*a1bf3f78SToomas Soome 	ficlVmErrorOut(vm, vm->pad);
2357*a1bf3f78SToomas Soome 	longjmp(*(vm->exceptionHandler), FICL_VM_STATUS_ERROR_EXIT);
2358*a1bf3f78SToomas Soome }
2359*a1bf3f78SToomas Soome 
2360*a1bf3f78SToomas Soome void
2361*a1bf3f78SToomas Soome ficlVmThrowErrorVararg(ficlVm *vm, char *fmt, va_list list)
2362*a1bf3f78SToomas Soome {
2363*a1bf3f78SToomas Soome 	vsprintf(vm->pad, fmt, list);
2364*a1bf3f78SToomas Soome 	/*
2365*a1bf3f78SToomas Soome 	 * well, we can try anyway, we're certainly not
2366*a1bf3f78SToomas Soome 	 * returning to our caller!
2367*a1bf3f78SToomas Soome 	 */
2368*a1bf3f78SToomas Soome 	va_end(list);
2369*a1bf3f78SToomas Soome 	strcat(vm->pad, "\n");
2370*a1bf3f78SToomas Soome 
2371*a1bf3f78SToomas Soome 	ficlVmErrorOut(vm, vm->pad);
2372*a1bf3f78SToomas Soome 	longjmp(*(vm->exceptionHandler), FICL_VM_STATUS_ERROR_EXIT);
2373*a1bf3f78SToomas Soome }
2374*a1bf3f78SToomas Soome 
2375*a1bf3f78SToomas Soome /*
2376*a1bf3f78SToomas Soome  * f i c l E v a l u a t e
2377*a1bf3f78SToomas Soome  * Wrapper for ficlExec() which sets SOURCE-ID to -1.
2378*a1bf3f78SToomas Soome  */
2379*a1bf3f78SToomas Soome int
2380*a1bf3f78SToomas Soome ficlVmEvaluate(ficlVm *vm, char *s)
2381*a1bf3f78SToomas Soome {
2382*a1bf3f78SToomas Soome 	int returnValue;
2383*a1bf3f78SToomas Soome 	ficlCell id = vm->sourceId;
2384*a1bf3f78SToomas Soome 	ficlString string;
2385*a1bf3f78SToomas Soome 	vm->sourceId.i = -1;
2386*a1bf3f78SToomas Soome 	FICL_STRING_SET_FROM_CSTRING(string, s);
2387*a1bf3f78SToomas Soome 	returnValue = ficlVmExecuteString(vm, string);
2388*a1bf3f78SToomas Soome 	vm->sourceId = id;
2389*a1bf3f78SToomas Soome 	return (returnValue);
2390*a1bf3f78SToomas Soome }
2391*a1bf3f78SToomas Soome 
2392*a1bf3f78SToomas Soome /*
2393*a1bf3f78SToomas Soome  * f i c l E x e c
2394*a1bf3f78SToomas Soome  * Evaluates a block of input text in the context of the
2395*a1bf3f78SToomas Soome  * specified interpreter. Emits any requested output to the
2396*a1bf3f78SToomas Soome  * interpreter's output function.
2397*a1bf3f78SToomas Soome  *
2398*a1bf3f78SToomas Soome  * Contains the "inner interpreter" code in a tight loop
2399*a1bf3f78SToomas Soome  *
2400*a1bf3f78SToomas Soome  * Returns one of the VM_XXXX codes defined in ficl.h:
2401*a1bf3f78SToomas Soome  * VM_OUTOFTEXT is the normal exit condition
2402*a1bf3f78SToomas Soome  * VM_ERREXIT means that the interpreter encountered a syntax error
2403*a1bf3f78SToomas Soome  *      and the vm has been reset to recover (some or all
2404*a1bf3f78SToomas Soome  *      of the text block got ignored
2405*a1bf3f78SToomas Soome  * VM_USEREXIT means that the user executed the "bye" command
2406*a1bf3f78SToomas Soome  *      to shut down the interpreter. This would be a good
2407*a1bf3f78SToomas Soome  *      time to delete the vm, etc -- or you can ignore this
2408*a1bf3f78SToomas Soome  *      signal.
2409*a1bf3f78SToomas Soome  */
2410*a1bf3f78SToomas Soome int
2411*a1bf3f78SToomas Soome ficlVmExecuteString(ficlVm *vm, ficlString s)
2412*a1bf3f78SToomas Soome {
2413*a1bf3f78SToomas Soome 	ficlSystem *system = vm->callback.system;
2414*a1bf3f78SToomas Soome 	ficlDictionary *dictionary = system->dictionary;
2415*a1bf3f78SToomas Soome 
2416*a1bf3f78SToomas Soome 	int except;
2417*a1bf3f78SToomas Soome 	jmp_buf vmState;
2418*a1bf3f78SToomas Soome 	jmp_buf *oldState;
2419*a1bf3f78SToomas Soome 	ficlTIB saveficlTIB;
2420*a1bf3f78SToomas Soome 
2421*a1bf3f78SToomas Soome 	FICL_VM_ASSERT(vm, vm);
2422*a1bf3f78SToomas Soome 	FICL_VM_ASSERT(vm, system->interpreterLoop[0]);
2423*a1bf3f78SToomas Soome 
2424*a1bf3f78SToomas Soome 	ficlVmPushTib(vm, FICL_STRING_GET_POINTER(s),
2425*a1bf3f78SToomas Soome 	    FICL_STRING_GET_LENGTH(s), &saveficlTIB);
2426*a1bf3f78SToomas Soome 
2427*a1bf3f78SToomas Soome 	/*
2428*a1bf3f78SToomas Soome 	 * Save and restore VM's jmp_buf to enable nested calls to ficlExec
2429*a1bf3f78SToomas Soome 	 */
2430*a1bf3f78SToomas Soome 	oldState = vm->exceptionHandler;
2431*a1bf3f78SToomas Soome 
2432*a1bf3f78SToomas Soome 	/* This has to come before the setjmp! */
2433*a1bf3f78SToomas Soome 	vm->exceptionHandler = &vmState;
2434*a1bf3f78SToomas Soome 	except = setjmp(vmState);
2435*a1bf3f78SToomas Soome 
2436*a1bf3f78SToomas Soome 	switch (except) {
2437*a1bf3f78SToomas Soome 	case 0:
2438*a1bf3f78SToomas Soome 		if (vm->restart) {
2439*a1bf3f78SToomas Soome 			vm->runningWord->code(vm);
2440*a1bf3f78SToomas Soome 			vm->restart = 0;
2441*a1bf3f78SToomas Soome 		} else {	/* set VM up to interpret text */
2442*a1bf3f78SToomas Soome 			ficlVmPushIP(vm, &(system->interpreterLoop[0]));
2443*a1bf3f78SToomas Soome 		}
2444*a1bf3f78SToomas Soome 
2445*a1bf3f78SToomas Soome 		ficlVmInnerLoop(vm, 0);
2446*a1bf3f78SToomas Soome 	break;
2447*a1bf3f78SToomas Soome 
2448*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_RESTART:
2449*a1bf3f78SToomas Soome 		vm->restart = 1;
2450*a1bf3f78SToomas Soome 		except = FICL_VM_STATUS_OUT_OF_TEXT;
2451*a1bf3f78SToomas Soome 	break;
2452*a1bf3f78SToomas Soome 
2453*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_OUT_OF_TEXT:
2454*a1bf3f78SToomas Soome 		ficlVmPopIP(vm);
2455*a1bf3f78SToomas Soome #if 0	/* we dont output prompt in loader */
2456*a1bf3f78SToomas Soome 		if ((vm->state != FICL_VM_STATE_COMPILE) &&
2457*a1bf3f78SToomas Soome 		    (vm->sourceId.i == 0))
2458*a1bf3f78SToomas Soome 			ficlVmTextOut(vm, FICL_PROMPT);
2459*a1bf3f78SToomas Soome #endif
2460*a1bf3f78SToomas Soome 	break;
2461*a1bf3f78SToomas Soome 
2462*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_USER_EXIT:
2463*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_INNER_EXIT:
2464*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_BREAK:
2465*a1bf3f78SToomas Soome 	break;
2466*a1bf3f78SToomas Soome 
2467*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_QUIT:
2468*a1bf3f78SToomas Soome 		if (vm->state == FICL_VM_STATE_COMPILE) {
2469*a1bf3f78SToomas Soome 			ficlDictionaryAbortDefinition(dictionary);
2470*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS
2471*a1bf3f78SToomas Soome 			ficlDictionaryEmpty(system->locals,
2472*a1bf3f78SToomas Soome 			    system->locals->forthWordlist->size);
2473*a1bf3f78SToomas Soome #endif
2474*a1bf3f78SToomas Soome 		}
2475*a1bf3f78SToomas Soome 		ficlVmQuit(vm);
2476*a1bf3f78SToomas Soome 	break;
2477*a1bf3f78SToomas Soome 
2478*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_ERROR_EXIT:
2479*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_ABORT:
2480*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_ABORTQ:
2481*a1bf3f78SToomas Soome 	default:		/* user defined exit code?? */
2482*a1bf3f78SToomas Soome 		if (vm->state == FICL_VM_STATE_COMPILE) {
2483*a1bf3f78SToomas Soome 			ficlDictionaryAbortDefinition(dictionary);
2484*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS
2485*a1bf3f78SToomas Soome 			ficlDictionaryEmpty(system->locals,
2486*a1bf3f78SToomas Soome 			    system->locals->forthWordlist->size);
2487*a1bf3f78SToomas Soome #endif
2488*a1bf3f78SToomas Soome 		}
2489*a1bf3f78SToomas Soome 		ficlDictionaryResetSearchOrder(dictionary);
2490*a1bf3f78SToomas Soome 		ficlVmReset(vm);
2491*a1bf3f78SToomas Soome 	break;
2492*a1bf3f78SToomas Soome 	}
2493*a1bf3f78SToomas Soome 
2494*a1bf3f78SToomas Soome 	vm->exceptionHandler = oldState;
2495*a1bf3f78SToomas Soome 	ficlVmPopTib(vm, &saveficlTIB);
2496*a1bf3f78SToomas Soome 	return (except);
2497*a1bf3f78SToomas Soome }
2498*a1bf3f78SToomas Soome 
2499*a1bf3f78SToomas Soome /*
2500*a1bf3f78SToomas Soome  * f i c l E x e c X T
2501*a1bf3f78SToomas Soome  * Given a pointer to a ficlWord, push an inner interpreter and
2502*a1bf3f78SToomas Soome  * execute the word to completion. This is in contrast with vmExecute,
2503*a1bf3f78SToomas Soome  * which does not guarantee that the word will have completed when
2504*a1bf3f78SToomas Soome  * the function returns (ie in the case of colon definitions, which
2505*a1bf3f78SToomas Soome  * need an inner interpreter to finish)
2506*a1bf3f78SToomas Soome  *
2507*a1bf3f78SToomas Soome  * Returns one of the VM_XXXX exception codes listed in ficl.h. Normal
2508*a1bf3f78SToomas Soome  * exit condition is VM_INNEREXIT, Ficl's private signal to exit the
2509*a1bf3f78SToomas Soome  * inner loop under normal circumstances. If another code is thrown to
2510*a1bf3f78SToomas Soome  * exit the loop, this function will re-throw it if it's nested under
2511*a1bf3f78SToomas Soome  * itself or ficlExec.
2512*a1bf3f78SToomas Soome  *
2513*a1bf3f78SToomas Soome  * NOTE: this function is intended so that C code can execute ficlWords
2514*a1bf3f78SToomas Soome  * given their address in the dictionary (xt).
2515*a1bf3f78SToomas Soome  */
2516*a1bf3f78SToomas Soome int
2517*a1bf3f78SToomas Soome ficlVmExecuteXT(ficlVm *vm, ficlWord *pWord)
2518*a1bf3f78SToomas Soome {
2519*a1bf3f78SToomas Soome 	int except;
2520*a1bf3f78SToomas Soome 	jmp_buf vmState;
2521*a1bf3f78SToomas Soome 	jmp_buf *oldState;
2522*a1bf3f78SToomas Soome 	ficlWord *oldRunningWord;
2523*a1bf3f78SToomas Soome 
2524*a1bf3f78SToomas Soome 	FICL_VM_ASSERT(vm, vm);
2525*a1bf3f78SToomas Soome 	FICL_VM_ASSERT(vm, vm->callback.system->exitInnerWord);
2526*a1bf3f78SToomas Soome 
2527*a1bf3f78SToomas Soome 	/*
2528*a1bf3f78SToomas Soome 	 * Save the runningword so that RESTART behaves correctly
2529*a1bf3f78SToomas Soome 	 * over nested calls.
2530*a1bf3f78SToomas Soome 	 */
2531*a1bf3f78SToomas Soome 	oldRunningWord = vm->runningWord;
2532*a1bf3f78SToomas Soome 	/*
2533*a1bf3f78SToomas Soome 	 * Save and restore VM's jmp_buf to enable nested calls
2534*a1bf3f78SToomas Soome 	 */
2535*a1bf3f78SToomas Soome 	oldState = vm->exceptionHandler;
2536*a1bf3f78SToomas Soome 	/* This has to come before the setjmp! */
2537*a1bf3f78SToomas Soome 	vm->exceptionHandler = &vmState;
2538*a1bf3f78SToomas Soome 	except = setjmp(vmState);
2539*a1bf3f78SToomas Soome 
2540*a1bf3f78SToomas Soome 	if (except)
2541*a1bf3f78SToomas Soome 		ficlVmPopIP(vm);
2542*a1bf3f78SToomas Soome 	else
2543*a1bf3f78SToomas Soome 		ficlVmPushIP(vm, &(vm->callback.system->exitInnerWord));
2544*a1bf3f78SToomas Soome 
2545*a1bf3f78SToomas Soome 	switch (except) {
2546*a1bf3f78SToomas Soome 	case 0:
2547*a1bf3f78SToomas Soome 		ficlVmExecuteWord(vm, pWord);
2548*a1bf3f78SToomas Soome 		ficlVmInnerLoop(vm, 0);
2549*a1bf3f78SToomas Soome 	break;
2550*a1bf3f78SToomas Soome 
2551*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_INNER_EXIT:
2552*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_BREAK:
2553*a1bf3f78SToomas Soome 	break;
2554*a1bf3f78SToomas Soome 
2555*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_RESTART:
2556*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_OUT_OF_TEXT:
2557*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_USER_EXIT:
2558*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_QUIT:
2559*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_ERROR_EXIT:
2560*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_ABORT:
2561*a1bf3f78SToomas Soome 	case FICL_VM_STATUS_ABORTQ:
2562*a1bf3f78SToomas Soome 	default:		/* user defined exit code?? */
2563*a1bf3f78SToomas Soome 		if (oldState) {
2564*a1bf3f78SToomas Soome 			vm->exceptionHandler = oldState;
2565*a1bf3f78SToomas Soome 			ficlVmThrow(vm, except);
2566*a1bf3f78SToomas Soome 		}
2567*a1bf3f78SToomas Soome 	break;
2568*a1bf3f78SToomas Soome 	}
2569*a1bf3f78SToomas Soome 
2570*a1bf3f78SToomas Soome 	vm->exceptionHandler = oldState;
2571*a1bf3f78SToomas Soome 	vm->runningWord = oldRunningWord;
2572*a1bf3f78SToomas Soome 	return (except);
2573*a1bf3f78SToomas Soome }
2574*a1bf3f78SToomas Soome 
2575*a1bf3f78SToomas Soome /*
2576*a1bf3f78SToomas Soome  * f i c l P a r s e N u m b e r
2577*a1bf3f78SToomas Soome  * Attempts to convert the NULL terminated string in the VM's pad to
2578*a1bf3f78SToomas Soome  * a number using the VM's current base. If successful, pushes the number
2579*a1bf3f78SToomas Soome  * onto the param stack and returns FICL_TRUE. Otherwise, returns FICL_FALSE.
2580*a1bf3f78SToomas Soome  * (jws 8/01) Trailing decimal point causes a zero ficlCell to be pushed. (See
2581*a1bf3f78SToomas Soome  * the standard for DOUBLE wordset.
2582*a1bf3f78SToomas Soome  */
2583*a1bf3f78SToomas Soome int
2584*a1bf3f78SToomas Soome ficlVmParseNumber(ficlVm *vm, ficlString s)
2585*a1bf3f78SToomas Soome {
2586*a1bf3f78SToomas Soome 	ficlInteger accumulator = 0;
2587*a1bf3f78SToomas Soome 	char isNegative = 0;
2588*a1bf3f78SToomas Soome 	char isDouble = 0;
2589*a1bf3f78SToomas Soome 	unsigned base = vm->base;
2590*a1bf3f78SToomas Soome 	char *trace = FICL_STRING_GET_POINTER(s);
2591*a1bf3f78SToomas Soome 	ficlUnsigned8 length = (ficlUnsigned8)FICL_STRING_GET_LENGTH(s);
2592*a1bf3f78SToomas Soome 	unsigned c;
2593*a1bf3f78SToomas Soome 	unsigned digit;
2594*a1bf3f78SToomas Soome 
2595*a1bf3f78SToomas Soome 	if (length > 1) {
2596*a1bf3f78SToomas Soome 		switch (*trace) {
2597*a1bf3f78SToomas Soome 		case '-':
2598*a1bf3f78SToomas Soome 			trace++;
2599*a1bf3f78SToomas Soome 			length--;
2600*a1bf3f78SToomas Soome 			isNegative = 1;
2601*a1bf3f78SToomas Soome 		break;
2602*a1bf3f78SToomas Soome 		case '+':
2603*a1bf3f78SToomas Soome 			trace++;
2604*a1bf3f78SToomas Soome 			length--;
2605*a1bf3f78SToomas Soome 			isNegative = 0;
2606*a1bf3f78SToomas Soome 		break;
2607*a1bf3f78SToomas Soome 		default:
2608*a1bf3f78SToomas Soome 		break;
2609*a1bf3f78SToomas Soome 		}
2610*a1bf3f78SToomas Soome 	}
2611*a1bf3f78SToomas Soome 
2612*a1bf3f78SToomas Soome 	/* detect & remove trailing decimal */
2613*a1bf3f78SToomas Soome 	if ((length > 0) && (trace[length - 1] == '.')) {
2614*a1bf3f78SToomas Soome 		isDouble = 1;
2615*a1bf3f78SToomas Soome 		length--;
2616*a1bf3f78SToomas Soome 	}
2617*a1bf3f78SToomas Soome 
2618*a1bf3f78SToomas Soome 	if (length == 0)		/* detect "+", "-", ".", "+." etc */
2619*a1bf3f78SToomas Soome 		return (0);		/* false */
2620*a1bf3f78SToomas Soome 
2621*a1bf3f78SToomas Soome 	while ((length--) && ((c = *trace++) != '\0')) {
2622*a1bf3f78SToomas Soome 		if (!isalnum(c))
2623*a1bf3f78SToomas Soome 			return (0);	/* false */
2624*a1bf3f78SToomas Soome 
2625*a1bf3f78SToomas Soome 		digit = c - '0';
2626*a1bf3f78SToomas Soome 
2627*a1bf3f78SToomas Soome 		if (digit > 9)
2628*a1bf3f78SToomas Soome 			digit = tolower(c) - 'a' + 10;
2629*a1bf3f78SToomas Soome 
2630*a1bf3f78SToomas Soome 		if (digit >= base)
2631*a1bf3f78SToomas Soome 			return (0);	/* false */
2632*a1bf3f78SToomas Soome 
2633*a1bf3f78SToomas Soome 		accumulator = accumulator * base + digit;
2634*a1bf3f78SToomas Soome 	}
2635*a1bf3f78SToomas Soome 
2636*a1bf3f78SToomas Soome 	if (isNegative)
2637*a1bf3f78SToomas Soome 		accumulator = -accumulator;
2638*a1bf3f78SToomas Soome 
2639*a1bf3f78SToomas Soome 	ficlStackPushInteger(vm->dataStack, accumulator);
2640*a1bf3f78SToomas Soome 	if (vm->state == FICL_VM_STATE_COMPILE)
2641*a1bf3f78SToomas Soome 		ficlPrimitiveLiteralIm(vm);
2642*a1bf3f78SToomas Soome 
2643*a1bf3f78SToomas Soome 	if (isDouble) {			/* simple (required) DOUBLE support */
2644*a1bf3f78SToomas Soome 		if (isNegative)
2645*a1bf3f78SToomas Soome 			ficlStackPushInteger(vm->dataStack, -1);
2646*a1bf3f78SToomas Soome 		else
2647*a1bf3f78SToomas Soome 			ficlStackPushInteger(vm->dataStack, 0);
2648*a1bf3f78SToomas Soome 		if (vm->state == FICL_VM_STATE_COMPILE)
2649*a1bf3f78SToomas Soome 			ficlPrimitiveLiteralIm(vm);
2650*a1bf3f78SToomas Soome 	}
2651*a1bf3f78SToomas Soome 
2652*a1bf3f78SToomas Soome 	return (1); /* true */
2653*a1bf3f78SToomas Soome }
2654*a1bf3f78SToomas Soome 
2655*a1bf3f78SToomas Soome /*
2656*a1bf3f78SToomas Soome  * d i c t C h e c k
2657*a1bf3f78SToomas Soome  * Checks the dictionary for corruption and throws appropriate
2658*a1bf3f78SToomas Soome  * errors.
2659*a1bf3f78SToomas Soome  * Input: +n number of ADDRESS UNITS (not ficlCells) proposed to allot
2660*a1bf3f78SToomas Soome  *        -n number of ADDRESS UNITS proposed to de-allot
2661*a1bf3f78SToomas Soome  *         0 just do a consistency check
2662*a1bf3f78SToomas Soome  */
2663*a1bf3f78SToomas Soome void
2664*a1bf3f78SToomas Soome ficlVmDictionarySimpleCheck(ficlVm *vm, ficlDictionary *dictionary, int cells)
2665*a1bf3f78SToomas Soome {
2666*a1bf3f78SToomas Soome #if FICL_ROBUST >= 1
2667*a1bf3f78SToomas Soome 	if ((cells >= 0) &&
2668*a1bf3f78SToomas Soome 	    (ficlDictionaryCellsAvailable(dictionary) *
2669*a1bf3f78SToomas Soome 	    (int)sizeof (ficlCell) < cells)) {
2670*a1bf3f78SToomas Soome 		ficlVmThrowError(vm, "Error: dictionary full");
2671*a1bf3f78SToomas Soome 	}
2672*a1bf3f78SToomas Soome 
2673*a1bf3f78SToomas Soome 	if ((cells <= 0) &&
2674*a1bf3f78SToomas Soome 	    (ficlDictionaryCellsUsed(dictionary) *
2675*a1bf3f78SToomas Soome 	    (int)sizeof (ficlCell) < -cells)) {
2676*a1bf3f78SToomas Soome 		ficlVmThrowError(vm, "Error: dictionary underflow");
2677*a1bf3f78SToomas Soome 	}
2678*a1bf3f78SToomas Soome #else /* FICL_ROBUST >= 1 */
2679*a1bf3f78SToomas Soome 	FICL_IGNORE(vm);
2680*a1bf3f78SToomas Soome 	FICL_IGNORE(dictionary);
2681*a1bf3f78SToomas Soome 	FICL_IGNORE(cells);
2682*a1bf3f78SToomas Soome #endif /* FICL_ROBUST >= 1 */
2683*a1bf3f78SToomas Soome }
2684*a1bf3f78SToomas Soome 
2685*a1bf3f78SToomas Soome void
2686*a1bf3f78SToomas Soome ficlVmDictionaryCheck(ficlVm *vm, ficlDictionary *dictionary, int cells)
2687*a1bf3f78SToomas Soome {
2688*a1bf3f78SToomas Soome #if FICL_ROBUST >= 1
2689*a1bf3f78SToomas Soome 	ficlVmDictionarySimpleCheck(vm, dictionary, cells);
2690*a1bf3f78SToomas Soome 
2691*a1bf3f78SToomas Soome 	if (dictionary->wordlistCount > FICL_MAX_WORDLISTS) {
2692*a1bf3f78SToomas Soome 		ficlDictionaryResetSearchOrder(dictionary);
2693*a1bf3f78SToomas Soome 		ficlVmThrowError(vm, "Error: search order overflow");
2694*a1bf3f78SToomas Soome 	} else if (dictionary->wordlistCount < 0) {
2695*a1bf3f78SToomas Soome 		ficlDictionaryResetSearchOrder(dictionary);
2696*a1bf3f78SToomas Soome 		ficlVmThrowError(vm, "Error: search order underflow");
2697*a1bf3f78SToomas Soome 	}
2698*a1bf3f78SToomas Soome #else /* FICL_ROBUST >= 1 */
2699*a1bf3f78SToomas Soome 	FICL_IGNORE(vm);
2700*a1bf3f78SToomas Soome 	FICL_IGNORE(dictionary);
2701*a1bf3f78SToomas Soome 	FICL_IGNORE(cells);
2702*a1bf3f78SToomas Soome #endif /* FICL_ROBUST >= 1 */
2703*a1bf3f78SToomas Soome }
2704*a1bf3f78SToomas Soome 
2705*a1bf3f78SToomas Soome void
2706*a1bf3f78SToomas Soome ficlVmDictionaryAllot(ficlVm *vm, ficlDictionary *dictionary, int n)
2707*a1bf3f78SToomas Soome {
2708*a1bf3f78SToomas Soome 	FICL_VM_DICTIONARY_SIMPLE_CHECK(vm, dictionary, n);
2709*a1bf3f78SToomas Soome 	FICL_IGNORE(vm);
2710*a1bf3f78SToomas Soome 	ficlDictionaryAllot(dictionary, n);
2711*a1bf3f78SToomas Soome }
2712*a1bf3f78SToomas Soome 
2713*a1bf3f78SToomas Soome void
2714*a1bf3f78SToomas Soome ficlVmDictionaryAllotCells(ficlVm *vm, ficlDictionary *dictionary, int cells)
2715*a1bf3f78SToomas Soome {
2716*a1bf3f78SToomas Soome 	FICL_VM_DICTIONARY_SIMPLE_CHECK(vm, dictionary, cells);
2717*a1bf3f78SToomas Soome 	FICL_IGNORE(vm);
2718*a1bf3f78SToomas Soome 	ficlDictionaryAllotCells(dictionary, cells);
2719*a1bf3f78SToomas Soome }
2720*a1bf3f78SToomas Soome 
2721*a1bf3f78SToomas Soome /*
2722*a1bf3f78SToomas Soome  * f i c l P a r s e W o r d
2723*a1bf3f78SToomas Soome  * From the standard, section 3.4
2724*a1bf3f78SToomas Soome  * b) Search the dictionary name space (see 3.4.2). If a definition name
2725*a1bf3f78SToomas Soome  * matching the string is found:
2726*a1bf3f78SToomas Soome  *  1.if interpreting, perform the interpretation semantics of the definition
2727*a1bf3f78SToomas Soome  *  (see 3.4.3.2), and continue at a);
2728*a1bf3f78SToomas Soome  *  2.if compiling, perform the compilation semantics of the definition
2729*a1bf3f78SToomas Soome  *  (see 3.4.3.3), and continue at a).
2730*a1bf3f78SToomas Soome  *
2731*a1bf3f78SToomas Soome  * c) If a definition name matching the string is not found, attempt to
2732*a1bf3f78SToomas Soome  * convert the string to a number (see 3.4.1.3). If successful:
2733*a1bf3f78SToomas Soome  *  1.if interpreting, place the number on the data stack, and continue at a);
2734*a1bf3f78SToomas Soome  *  2.if compiling, FICL_VM_STATE_COMPILE code that when executed will place
2735*a1bf3f78SToomas Soome  *  the number on the stack (see 6.1.1780 LITERAL), and continue at a);
2736*a1bf3f78SToomas Soome  *
2737*a1bf3f78SToomas Soome  * d) If unsuccessful, an ambiguous condition exists (see 3.4.4).
2738*a1bf3f78SToomas Soome  *
2739*a1bf3f78SToomas Soome  * (jws 4/01) Modified to be a ficlParseStep
2740*a1bf3f78SToomas Soome  */
2741*a1bf3f78SToomas Soome int
2742*a1bf3f78SToomas Soome ficlVmParseWord(ficlVm *vm, ficlString name)
2743*a1bf3f78SToomas Soome {
2744*a1bf3f78SToomas Soome 	ficlDictionary *dictionary = ficlVmGetDictionary(vm);
2745*a1bf3f78SToomas Soome 	ficlWord *tempFW;
2746*a1bf3f78SToomas Soome 
2747*a1bf3f78SToomas Soome 	FICL_VM_DICTIONARY_CHECK(vm, dictionary, 0);
2748*a1bf3f78SToomas Soome 	FICL_STACK_CHECK(vm->dataStack, 0, 0);
2749*a1bf3f78SToomas Soome 
2750*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS
2751*a1bf3f78SToomas Soome 	if (vm->callback.system->localsCount > 0) {
2752*a1bf3f78SToomas Soome 		tempFW = ficlSystemLookupLocal(vm->callback.system, name);
2753*a1bf3f78SToomas Soome 	} else
2754*a1bf3f78SToomas Soome #endif
2755*a1bf3f78SToomas Soome 		tempFW = ficlDictionaryLookup(dictionary, name);
2756*a1bf3f78SToomas Soome 
2757*a1bf3f78SToomas Soome 	if (vm->state == FICL_VM_STATE_INTERPRET) {
2758*a1bf3f78SToomas Soome 		if (tempFW != NULL) {
2759*a1bf3f78SToomas Soome 			if (ficlWordIsCompileOnly(tempFW)) {
2760*a1bf3f78SToomas Soome 				ficlVmThrowError(vm,
2761*a1bf3f78SToomas Soome 				    "Error: FICL_VM_STATE_COMPILE only!");
2762*a1bf3f78SToomas Soome 			}
2763*a1bf3f78SToomas Soome 
2764*a1bf3f78SToomas Soome 			ficlVmExecuteWord(vm, tempFW);
2765*a1bf3f78SToomas Soome 			return (1); /* true */
2766*a1bf3f78SToomas Soome 		}
2767*a1bf3f78SToomas Soome 	} else {	/* (vm->state == FICL_VM_STATE_COMPILE) */
2768*a1bf3f78SToomas Soome 		if (tempFW != NULL) {
2769*a1bf3f78SToomas Soome 			if (ficlWordIsImmediate(tempFW)) {
2770*a1bf3f78SToomas Soome 				ficlVmExecuteWord(vm, tempFW);
2771*a1bf3f78SToomas Soome 			} else {
2772*a1bf3f78SToomas Soome 				ficlCell c;
2773*a1bf3f78SToomas Soome 				c.p = tempFW;
2774*a1bf3f78SToomas Soome 				if (tempFW->flags & FICL_WORD_INSTRUCTION)
2775*a1bf3f78SToomas Soome 					ficlDictionaryAppendUnsigned(dictionary,
2776*a1bf3f78SToomas Soome 					    (ficlInteger)tempFW->code);
2777*a1bf3f78SToomas Soome 				else
2778*a1bf3f78SToomas Soome 					ficlDictionaryAppendCell(dictionary, c);
2779*a1bf3f78SToomas Soome 			}
2780*a1bf3f78SToomas Soome 			return (1); /* true */
2781*a1bf3f78SToomas Soome 		}
2782*a1bf3f78SToomas Soome 	}
2783*a1bf3f78SToomas Soome 
2784*a1bf3f78SToomas Soome 	return (0); /* false */
2785*a1bf3f78SToomas Soome }
2786