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