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