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