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