1*a1bf3f78SToomas Soome /* 2*a1bf3f78SToomas Soome * w o r d s . c 3*a1bf3f78SToomas Soome * Forth Inspired Command Language 4*a1bf3f78SToomas Soome * ANS Forth CORE word-set written in C 5*a1bf3f78SToomas Soome * Author: John Sadler (john_sadler@alum.mit.edu) 6*a1bf3f78SToomas Soome * Created: 19 July 1997 7*a1bf3f78SToomas Soome * $Id: primitives.c,v 1.4 2010/09/13 18:43:04 asau Exp $ 8*a1bf3f78SToomas Soome */ 9*a1bf3f78SToomas Soome /* 10*a1bf3f78SToomas Soome * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) 11*a1bf3f78SToomas Soome * All rights reserved. 12*a1bf3f78SToomas Soome * 13*a1bf3f78SToomas Soome * Get the latest Ficl release at http://ficl.sourceforge.net 14*a1bf3f78SToomas Soome * 15*a1bf3f78SToomas Soome * I am interested in hearing from anyone who uses Ficl. If you have 16*a1bf3f78SToomas Soome * a problem, a success story, a defect, an enhancement request, or 17*a1bf3f78SToomas Soome * if you would like to contribute to the Ficl release, please 18*a1bf3f78SToomas Soome * contact me by email at the address above. 19*a1bf3f78SToomas Soome * 20*a1bf3f78SToomas Soome * L I C E N S E and D I S C L A I M E R 21*a1bf3f78SToomas Soome * 22*a1bf3f78SToomas Soome * Redistribution and use in source and binary forms, with or without 23*a1bf3f78SToomas Soome * modification, are permitted provided that the following conditions 24*a1bf3f78SToomas Soome * are met: 25*a1bf3f78SToomas Soome * 1. Redistributions of source code must retain the above copyright 26*a1bf3f78SToomas Soome * notice, this list of conditions and the following disclaimer. 27*a1bf3f78SToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 28*a1bf3f78SToomas Soome * notice, this list of conditions and the following disclaimer in the 29*a1bf3f78SToomas Soome * documentation and/or other materials provided with the distribution. 30*a1bf3f78SToomas Soome * 31*a1bf3f78SToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 32*a1bf3f78SToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33*a1bf3f78SToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34*a1bf3f78SToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 35*a1bf3f78SToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36*a1bf3f78SToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37*a1bf3f78SToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38*a1bf3f78SToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39*a1bf3f78SToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 40*a1bf3f78SToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 41*a1bf3f78SToomas Soome * SUCH DAMAGE. 42*a1bf3f78SToomas Soome */ 43*a1bf3f78SToomas Soome 44*a1bf3f78SToomas Soome #include "ficl.h" 45*a1bf3f78SToomas Soome #include <limits.h> 46*a1bf3f78SToomas Soome 47*a1bf3f78SToomas Soome /* 48*a1bf3f78SToomas Soome * Control structure building words use these 49*a1bf3f78SToomas Soome * strings' addresses as markers on the stack to 50*a1bf3f78SToomas Soome * check for structure completion. 51*a1bf3f78SToomas Soome */ 52*a1bf3f78SToomas Soome static char doTag[] = "do"; 53*a1bf3f78SToomas Soome static char colonTag[] = "colon"; 54*a1bf3f78SToomas Soome static char leaveTag[] = "leave"; 55*a1bf3f78SToomas Soome 56*a1bf3f78SToomas Soome static char destTag[] = "target"; 57*a1bf3f78SToomas Soome static char origTag[] = "origin"; 58*a1bf3f78SToomas Soome 59*a1bf3f78SToomas Soome static char caseTag[] = "case"; 60*a1bf3f78SToomas Soome static char ofTag[] = "of"; 61*a1bf3f78SToomas Soome static char fallthroughTag[] = "fallthrough"; 62*a1bf3f78SToomas Soome 63*a1bf3f78SToomas Soome /* 64*a1bf3f78SToomas Soome * C O N T R O L S T R U C T U R E B U I L D E R S 65*a1bf3f78SToomas Soome * 66*a1bf3f78SToomas Soome * Push current dictionary location for later branch resolution. 67*a1bf3f78SToomas Soome * The location may be either a branch target or a patch address... 68*a1bf3f78SToomas Soome */ 69*a1bf3f78SToomas Soome static void 70*a1bf3f78SToomas Soome markBranch(ficlDictionary *dictionary, ficlVm *vm, char *tag) 71*a1bf3f78SToomas Soome { 72*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, dictionary->here); 73*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, tag); 74*a1bf3f78SToomas Soome } 75*a1bf3f78SToomas Soome 76*a1bf3f78SToomas Soome static void 77*a1bf3f78SToomas Soome markControlTag(ficlVm *vm, char *tag) 78*a1bf3f78SToomas Soome { 79*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, tag); 80*a1bf3f78SToomas Soome } 81*a1bf3f78SToomas Soome 82*a1bf3f78SToomas Soome static void 83*a1bf3f78SToomas Soome matchControlTag(ficlVm *vm, char *wantTag) 84*a1bf3f78SToomas Soome { 85*a1bf3f78SToomas Soome char *tag; 86*a1bf3f78SToomas Soome 87*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 88*a1bf3f78SToomas Soome 89*a1bf3f78SToomas Soome tag = (char *)ficlStackPopPointer(vm->dataStack); 90*a1bf3f78SToomas Soome 91*a1bf3f78SToomas Soome /* 92*a1bf3f78SToomas Soome * Changed the code below to compare the pointers first 93*a1bf3f78SToomas Soome * (by popular demand) 94*a1bf3f78SToomas Soome */ 95*a1bf3f78SToomas Soome if ((tag != wantTag) && strcmp(tag, wantTag)) { 96*a1bf3f78SToomas Soome ficlVmThrowError(vm, 97*a1bf3f78SToomas Soome "Error -- unmatched control structure \"%s\"", wantTag); 98*a1bf3f78SToomas Soome } 99*a1bf3f78SToomas Soome } 100*a1bf3f78SToomas Soome 101*a1bf3f78SToomas Soome /* 102*a1bf3f78SToomas Soome * Expect a branch target address on the param stack, 103*a1bf3f78SToomas Soome * FICL_VM_STATE_COMPILE a literal offset from the current dictionary location 104*a1bf3f78SToomas Soome * to the target address 105*a1bf3f78SToomas Soome */ 106*a1bf3f78SToomas Soome static void 107*a1bf3f78SToomas Soome resolveBackBranch(ficlDictionary *dictionary, ficlVm *vm, char *tag) 108*a1bf3f78SToomas Soome { 109*a1bf3f78SToomas Soome ficlCell *patchAddr, c; 110*a1bf3f78SToomas Soome 111*a1bf3f78SToomas Soome matchControlTag(vm, tag); 112*a1bf3f78SToomas Soome 113*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 114*a1bf3f78SToomas Soome 115*a1bf3f78SToomas Soome patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack); 116*a1bf3f78SToomas Soome c.i = patchAddr - dictionary->here; 117*a1bf3f78SToomas Soome 118*a1bf3f78SToomas Soome ficlDictionaryAppendCell(dictionary, c); 119*a1bf3f78SToomas Soome } 120*a1bf3f78SToomas Soome 121*a1bf3f78SToomas Soome /* 122*a1bf3f78SToomas Soome * Expect a branch patch address on the param stack, 123*a1bf3f78SToomas Soome * FICL_VM_STATE_COMPILE a literal offset from the patch location 124*a1bf3f78SToomas Soome * to the current dictionary location 125*a1bf3f78SToomas Soome */ 126*a1bf3f78SToomas Soome static void 127*a1bf3f78SToomas Soome resolveForwardBranch(ficlDictionary *dictionary, ficlVm *vm, char *tag) 128*a1bf3f78SToomas Soome { 129*a1bf3f78SToomas Soome ficlInteger offset; 130*a1bf3f78SToomas Soome ficlCell *patchAddr; 131*a1bf3f78SToomas Soome 132*a1bf3f78SToomas Soome matchControlTag(vm, tag); 133*a1bf3f78SToomas Soome 134*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 135*a1bf3f78SToomas Soome 136*a1bf3f78SToomas Soome patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack); 137*a1bf3f78SToomas Soome offset = dictionary->here - patchAddr; 138*a1bf3f78SToomas Soome (*patchAddr).i = offset; 139*a1bf3f78SToomas Soome } 140*a1bf3f78SToomas Soome 141*a1bf3f78SToomas Soome /* 142*a1bf3f78SToomas Soome * Match the tag to the top of the stack. If success, 143*a1bf3f78SToomas Soome * sopy "here" address into the ficlCell whose address is next 144*a1bf3f78SToomas Soome * on the stack. Used by do..leave..loop. 145*a1bf3f78SToomas Soome */ 146*a1bf3f78SToomas Soome static void 147*a1bf3f78SToomas Soome resolveAbsBranch(ficlDictionary *dictionary, ficlVm *vm, char *wantTag) 148*a1bf3f78SToomas Soome { 149*a1bf3f78SToomas Soome ficlCell *patchAddr; 150*a1bf3f78SToomas Soome char *tag; 151*a1bf3f78SToomas Soome 152*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 0); 153*a1bf3f78SToomas Soome 154*a1bf3f78SToomas Soome tag = ficlStackPopPointer(vm->dataStack); 155*a1bf3f78SToomas Soome 156*a1bf3f78SToomas Soome /* 157*a1bf3f78SToomas Soome * Changed the comparison below to compare the pointers first 158*a1bf3f78SToomas Soome * (by popular demand) 159*a1bf3f78SToomas Soome */ 160*a1bf3f78SToomas Soome if ((tag != wantTag) && strcmp(tag, wantTag)) { 161*a1bf3f78SToomas Soome ficlVmTextOut(vm, "Warning -- Unmatched control word: "); 162*a1bf3f78SToomas Soome ficlVmTextOut(vm, wantTag); 163*a1bf3f78SToomas Soome ficlVmTextOut(vm, "\n"); 164*a1bf3f78SToomas Soome } 165*a1bf3f78SToomas Soome 166*a1bf3f78SToomas Soome patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack); 167*a1bf3f78SToomas Soome (*patchAddr).p = dictionary->here; 168*a1bf3f78SToomas Soome } 169*a1bf3f78SToomas Soome 170*a1bf3f78SToomas Soome /* 171*a1bf3f78SToomas Soome * c o l o n d e f i n i t i o n s 172*a1bf3f78SToomas Soome * Code to begin compiling a colon definition 173*a1bf3f78SToomas Soome * This function sets the state to FICL_VM_STATE_COMPILE, then creates a 174*a1bf3f78SToomas Soome * new word whose name is the next word in the input stream 175*a1bf3f78SToomas Soome * and whose code is colonParen. 176*a1bf3f78SToomas Soome */ 177*a1bf3f78SToomas Soome static void 178*a1bf3f78SToomas Soome ficlPrimitiveColon(ficlVm *vm) 179*a1bf3f78SToomas Soome { 180*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 181*a1bf3f78SToomas Soome ficlString name = ficlVmGetWord(vm); 182*a1bf3f78SToomas Soome 183*a1bf3f78SToomas Soome vm->state = FICL_VM_STATE_COMPILE; 184*a1bf3f78SToomas Soome markControlTag(vm, colonTag); 185*a1bf3f78SToomas Soome ficlDictionaryAppendWord(dictionary, name, 186*a1bf3f78SToomas Soome (ficlPrimitive)ficlInstructionColonParen, 187*a1bf3f78SToomas Soome FICL_WORD_DEFAULT | FICL_WORD_SMUDGED); 188*a1bf3f78SToomas Soome 189*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 190*a1bf3f78SToomas Soome vm->callback.system->localsCount = 0; 191*a1bf3f78SToomas Soome #endif 192*a1bf3f78SToomas Soome } 193*a1bf3f78SToomas Soome 194*a1bf3f78SToomas Soome static void 195*a1bf3f78SToomas Soome ficlPrimitiveSemicolonCoIm(ficlVm *vm) 196*a1bf3f78SToomas Soome { 197*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 198*a1bf3f78SToomas Soome 199*a1bf3f78SToomas Soome matchControlTag(vm, colonTag); 200*a1bf3f78SToomas Soome 201*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 202*a1bf3f78SToomas Soome if (vm->callback.system->localsCount > 0) { 203*a1bf3f78SToomas Soome ficlDictionary *locals; 204*a1bf3f78SToomas Soome locals = ficlSystemGetLocals(vm->callback.system); 205*a1bf3f78SToomas Soome ficlDictionaryEmpty(locals, locals->forthWordlist->size); 206*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 207*a1bf3f78SToomas Soome ficlInstructionUnlinkParen); 208*a1bf3f78SToomas Soome } 209*a1bf3f78SToomas Soome vm->callback.system->localsCount = 0; 210*a1bf3f78SToomas Soome #endif 211*a1bf3f78SToomas Soome 212*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, ficlInstructionSemiParen); 213*a1bf3f78SToomas Soome vm->state = FICL_VM_STATE_INTERPRET; 214*a1bf3f78SToomas Soome ficlDictionaryUnsmudge(dictionary); 215*a1bf3f78SToomas Soome } 216*a1bf3f78SToomas Soome 217*a1bf3f78SToomas Soome /* 218*a1bf3f78SToomas Soome * e x i t 219*a1bf3f78SToomas Soome * CORE 220*a1bf3f78SToomas Soome * This function simply pops the previous instruction 221*a1bf3f78SToomas Soome * pointer and returns to the "next" loop. Used for exiting from within 222*a1bf3f78SToomas Soome * a definition. Note that exitParen is identical to semiParen - they 223*a1bf3f78SToomas Soome * are in two different functions so that "see" can correctly identify 224*a1bf3f78SToomas Soome * the end of a colon definition, even if it uses "exit". 225*a1bf3f78SToomas Soome */ 226*a1bf3f78SToomas Soome static void 227*a1bf3f78SToomas Soome ficlPrimitiveExitCoIm(ficlVm *vm) 228*a1bf3f78SToomas Soome { 229*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 230*a1bf3f78SToomas Soome FICL_IGNORE(vm); 231*a1bf3f78SToomas Soome 232*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 233*a1bf3f78SToomas Soome if (vm->callback.system->localsCount > 0) { 234*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 235*a1bf3f78SToomas Soome ficlInstructionUnlinkParen); 236*a1bf3f78SToomas Soome } 237*a1bf3f78SToomas Soome #endif 238*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, ficlInstructionExitParen); 239*a1bf3f78SToomas Soome } 240*a1bf3f78SToomas Soome 241*a1bf3f78SToomas Soome /* 242*a1bf3f78SToomas Soome * c o n s t a n t 243*a1bf3f78SToomas Soome * IMMEDIATE 244*a1bf3f78SToomas Soome * Compiles a constant into the dictionary. Constants return their 245*a1bf3f78SToomas Soome * value when invoked. Expects a value on top of the parm stack. 246*a1bf3f78SToomas Soome */ 247*a1bf3f78SToomas Soome static void 248*a1bf3f78SToomas Soome ficlPrimitiveConstant(ficlVm *vm) 249*a1bf3f78SToomas Soome { 250*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 251*a1bf3f78SToomas Soome ficlString name = ficlVmGetWord(vm); 252*a1bf3f78SToomas Soome 253*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 254*a1bf3f78SToomas Soome 255*a1bf3f78SToomas Soome ficlDictionaryAppendConstantInstruction(dictionary, name, 256*a1bf3f78SToomas Soome ficlInstructionConstantParen, ficlStackPopInteger(vm->dataStack)); 257*a1bf3f78SToomas Soome } 258*a1bf3f78SToomas Soome 259*a1bf3f78SToomas Soome static void 260*a1bf3f78SToomas Soome ficlPrimitive2Constant(ficlVm *vm) 261*a1bf3f78SToomas Soome { 262*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 263*a1bf3f78SToomas Soome ficlString name = ficlVmGetWord(vm); 264*a1bf3f78SToomas Soome 265*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 0); 266*a1bf3f78SToomas Soome 267*a1bf3f78SToomas Soome ficlDictionaryAppend2ConstantInstruction(dictionary, name, 268*a1bf3f78SToomas Soome ficlInstruction2ConstantParen, ficlStackPop2Integer(vm->dataStack)); 269*a1bf3f78SToomas Soome } 270*a1bf3f78SToomas Soome 271*a1bf3f78SToomas Soome /* 272*a1bf3f78SToomas Soome * d i s p l a y C e l l 273*a1bf3f78SToomas Soome * Drop and print the contents of the ficlCell at the top of the param 274*a1bf3f78SToomas Soome * stack 275*a1bf3f78SToomas Soome */ 276*a1bf3f78SToomas Soome static void 277*a1bf3f78SToomas Soome ficlPrimitiveDot(ficlVm *vm) 278*a1bf3f78SToomas Soome { 279*a1bf3f78SToomas Soome ficlCell c; 280*a1bf3f78SToomas Soome 281*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 282*a1bf3f78SToomas Soome 283*a1bf3f78SToomas Soome c = ficlStackPop(vm->dataStack); 284*a1bf3f78SToomas Soome ficlLtoa((c).i, vm->pad, vm->base); 285*a1bf3f78SToomas Soome strcat(vm->pad, " "); 286*a1bf3f78SToomas Soome ficlVmTextOut(vm, vm->pad); 287*a1bf3f78SToomas Soome } 288*a1bf3f78SToomas Soome 289*a1bf3f78SToomas Soome static void 290*a1bf3f78SToomas Soome ficlPrimitiveUDot(ficlVm *vm) 291*a1bf3f78SToomas Soome { 292*a1bf3f78SToomas Soome ficlUnsigned u; 293*a1bf3f78SToomas Soome 294*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 295*a1bf3f78SToomas Soome 296*a1bf3f78SToomas Soome u = ficlStackPopUnsigned(vm->dataStack); 297*a1bf3f78SToomas Soome ficlUltoa(u, vm->pad, vm->base); 298*a1bf3f78SToomas Soome strcat(vm->pad, " "); 299*a1bf3f78SToomas Soome ficlVmTextOut(vm, vm->pad); 300*a1bf3f78SToomas Soome } 301*a1bf3f78SToomas Soome 302*a1bf3f78SToomas Soome static void 303*a1bf3f78SToomas Soome ficlPrimitiveHexDot(ficlVm *vm) 304*a1bf3f78SToomas Soome { 305*a1bf3f78SToomas Soome ficlUnsigned u; 306*a1bf3f78SToomas Soome 307*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 308*a1bf3f78SToomas Soome 309*a1bf3f78SToomas Soome u = ficlStackPopUnsigned(vm->dataStack); 310*a1bf3f78SToomas Soome ficlUltoa(u, vm->pad, 16); 311*a1bf3f78SToomas Soome strcat(vm->pad, " "); 312*a1bf3f78SToomas Soome ficlVmTextOut(vm, vm->pad); 313*a1bf3f78SToomas Soome } 314*a1bf3f78SToomas Soome 315*a1bf3f78SToomas Soome /* 316*a1bf3f78SToomas Soome * s t r l e n 317*a1bf3f78SToomas Soome * Ficl ( c-string -- length ) 318*a1bf3f78SToomas Soome * 319*a1bf3f78SToomas Soome * Returns the length of a C-style (zero-terminated) string. 320*a1bf3f78SToomas Soome * 321*a1bf3f78SToomas Soome * --lch 322*a1bf3f78SToomas Soome */ 323*a1bf3f78SToomas Soome static void 324*a1bf3f78SToomas Soome ficlPrimitiveStrlen(ficlVm *vm) 325*a1bf3f78SToomas Soome { 326*a1bf3f78SToomas Soome char *address = (char *)ficlStackPopPointer(vm->dataStack); 327*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, strlen(address)); 328*a1bf3f78SToomas Soome } 329*a1bf3f78SToomas Soome 330*a1bf3f78SToomas Soome /* 331*a1bf3f78SToomas Soome * s p r i n t f 332*a1bf3f78SToomas Soome * Ficl ( i*x c-addr-fmt u-fmt c-addr-buffer u-buffer -- 333*a1bf3f78SToomas Soome * c-addr-buffer u-written success-flag ) 334*a1bf3f78SToomas Soome * Similar to the C sprintf() function. It formats into a buffer based on 335*a1bf3f78SToomas Soome * a "format" string. Each character in the format string is copied verbatim 336*a1bf3f78SToomas Soome * to the output buffer, until SPRINTF encounters a percent sign ("%"). 337*a1bf3f78SToomas Soome * SPRINTF then skips the percent sign, and examines the next character 338*a1bf3f78SToomas Soome * (the "format character"). Here are the valid format characters: 339*a1bf3f78SToomas Soome * s - read a C-ADDR U-LENGTH string from the stack and copy it to 340*a1bf3f78SToomas Soome * the buffer 341*a1bf3f78SToomas Soome * d - read a ficlCell from the stack, format it as a string (base-10, 342*a1bf3f78SToomas Soome * signed), and copy it to the buffer 343*a1bf3f78SToomas Soome * x - same as d, except in base-16 344*a1bf3f78SToomas Soome * u - same as d, but unsigned 345*a1bf3f78SToomas Soome * % - output a literal percent-sign to the buffer 346*a1bf3f78SToomas Soome * SPRINTF returns the c-addr-buffer argument unchanged, the number of bytes 347*a1bf3f78SToomas Soome * written, and a flag indicating whether or not it ran out of space while 348*a1bf3f78SToomas Soome * writing to the output buffer (FICL_TRUE if it ran out of space). 349*a1bf3f78SToomas Soome * 350*a1bf3f78SToomas Soome * If SPRINTF runs out of space in the buffer to store the formatted string, 351*a1bf3f78SToomas Soome * it still continues parsing, in an effort to preserve your stack (otherwise 352*a1bf3f78SToomas Soome * it might leave uneaten arguments behind). 353*a1bf3f78SToomas Soome * 354*a1bf3f78SToomas Soome * --lch 355*a1bf3f78SToomas Soome */ 356*a1bf3f78SToomas Soome static void 357*a1bf3f78SToomas Soome ficlPrimitiveSprintf(ficlVm *vm) 358*a1bf3f78SToomas Soome { 359*a1bf3f78SToomas Soome int bufferLength = ficlStackPopInteger(vm->dataStack); 360*a1bf3f78SToomas Soome char *buffer = (char *)ficlStackPopPointer(vm->dataStack); 361*a1bf3f78SToomas Soome char *bufferStart = buffer; 362*a1bf3f78SToomas Soome 363*a1bf3f78SToomas Soome int formatLength = ficlStackPopInteger(vm->dataStack); 364*a1bf3f78SToomas Soome char *format = (char *)ficlStackPopPointer(vm->dataStack); 365*a1bf3f78SToomas Soome char *formatStop = format + formatLength; 366*a1bf3f78SToomas Soome 367*a1bf3f78SToomas Soome int base = 10; 368*a1bf3f78SToomas Soome int unsignedInteger = 0; /* false */ 369*a1bf3f78SToomas Soome 370*a1bf3f78SToomas Soome int append = 1; /* true */ 371*a1bf3f78SToomas Soome 372*a1bf3f78SToomas Soome while (format < formatStop) { 373*a1bf3f78SToomas Soome char scratch[64]; 374*a1bf3f78SToomas Soome char *source; 375*a1bf3f78SToomas Soome int actualLength; 376*a1bf3f78SToomas Soome int desiredLength; 377*a1bf3f78SToomas Soome int leadingZeroes; 378*a1bf3f78SToomas Soome 379*a1bf3f78SToomas Soome if (*format != '%') { 380*a1bf3f78SToomas Soome source = format; 381*a1bf3f78SToomas Soome actualLength = desiredLength = 1; 382*a1bf3f78SToomas Soome leadingZeroes = 0; 383*a1bf3f78SToomas Soome } else { 384*a1bf3f78SToomas Soome format++; 385*a1bf3f78SToomas Soome if (format == formatStop) 386*a1bf3f78SToomas Soome break; 387*a1bf3f78SToomas Soome 388*a1bf3f78SToomas Soome leadingZeroes = (*format == '0'); 389*a1bf3f78SToomas Soome if (leadingZeroes) { 390*a1bf3f78SToomas Soome format++; 391*a1bf3f78SToomas Soome if (format == formatStop) 392*a1bf3f78SToomas Soome break; 393*a1bf3f78SToomas Soome } 394*a1bf3f78SToomas Soome 395*a1bf3f78SToomas Soome desiredLength = isdigit((unsigned char)*format); 396*a1bf3f78SToomas Soome if (desiredLength) { 397*a1bf3f78SToomas Soome desiredLength = strtoul(format, &format, 10); 398*a1bf3f78SToomas Soome if (format == formatStop) 399*a1bf3f78SToomas Soome break; 400*a1bf3f78SToomas Soome } else if (*format == '*') { 401*a1bf3f78SToomas Soome desiredLength = 402*a1bf3f78SToomas Soome ficlStackPopInteger(vm->dataStack); 403*a1bf3f78SToomas Soome 404*a1bf3f78SToomas Soome format++; 405*a1bf3f78SToomas Soome if (format == formatStop) 406*a1bf3f78SToomas Soome break; 407*a1bf3f78SToomas Soome } 408*a1bf3f78SToomas Soome 409*a1bf3f78SToomas Soome switch (*format) { 410*a1bf3f78SToomas Soome case 's': 411*a1bf3f78SToomas Soome case 'S': 412*a1bf3f78SToomas Soome actualLength = 413*a1bf3f78SToomas Soome ficlStackPopInteger(vm->dataStack); 414*a1bf3f78SToomas Soome source = (char *) 415*a1bf3f78SToomas Soome ficlStackPopPointer(vm->dataStack); 416*a1bf3f78SToomas Soome break; 417*a1bf3f78SToomas Soome case 'x': 418*a1bf3f78SToomas Soome case 'X': 419*a1bf3f78SToomas Soome base = 16; 420*a1bf3f78SToomas Soome case 'u': 421*a1bf3f78SToomas Soome case 'U': 422*a1bf3f78SToomas Soome unsignedInteger = 1; /* true */ 423*a1bf3f78SToomas Soome case 'd': 424*a1bf3f78SToomas Soome case 'D': { 425*a1bf3f78SToomas Soome int integer; 426*a1bf3f78SToomas Soome integer = ficlStackPopInteger(vm->dataStack); 427*a1bf3f78SToomas Soome if (unsignedInteger) 428*a1bf3f78SToomas Soome ficlUltoa(integer, scratch, base); 429*a1bf3f78SToomas Soome else 430*a1bf3f78SToomas Soome ficlLtoa(integer, scratch, base); 431*a1bf3f78SToomas Soome base = 10; 432*a1bf3f78SToomas Soome unsignedInteger = 0; /* false */ 433*a1bf3f78SToomas Soome source = scratch; 434*a1bf3f78SToomas Soome actualLength = strlen(scratch); 435*a1bf3f78SToomas Soome break; 436*a1bf3f78SToomas Soome } 437*a1bf3f78SToomas Soome case '%': 438*a1bf3f78SToomas Soome source = format; 439*a1bf3f78SToomas Soome actualLength = 1; 440*a1bf3f78SToomas Soome default: 441*a1bf3f78SToomas Soome continue; 442*a1bf3f78SToomas Soome } 443*a1bf3f78SToomas Soome } 444*a1bf3f78SToomas Soome 445*a1bf3f78SToomas Soome if (append) { 446*a1bf3f78SToomas Soome if (!desiredLength) 447*a1bf3f78SToomas Soome desiredLength = actualLength; 448*a1bf3f78SToomas Soome if (desiredLength > bufferLength) { 449*a1bf3f78SToomas Soome append = 0; /* false */ 450*a1bf3f78SToomas Soome desiredLength = bufferLength; 451*a1bf3f78SToomas Soome } 452*a1bf3f78SToomas Soome while (desiredLength > actualLength) { 453*a1bf3f78SToomas Soome *buffer++ = (char)((leadingZeroes) ? '0' : ' '); 454*a1bf3f78SToomas Soome bufferLength--; 455*a1bf3f78SToomas Soome desiredLength--; 456*a1bf3f78SToomas Soome } 457*a1bf3f78SToomas Soome memcpy(buffer, source, actualLength); 458*a1bf3f78SToomas Soome buffer += actualLength; 459*a1bf3f78SToomas Soome bufferLength -= actualLength; 460*a1bf3f78SToomas Soome } 461*a1bf3f78SToomas Soome 462*a1bf3f78SToomas Soome format++; 463*a1bf3f78SToomas Soome } 464*a1bf3f78SToomas Soome 465*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, bufferStart); 466*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, buffer - bufferStart); 467*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, FICL_BOOL(!append)); 468*a1bf3f78SToomas Soome } 469*a1bf3f78SToomas Soome 470*a1bf3f78SToomas Soome /* 471*a1bf3f78SToomas Soome * d u p & f r i e n d s 472*a1bf3f78SToomas Soome */ 473*a1bf3f78SToomas Soome static void 474*a1bf3f78SToomas Soome ficlPrimitiveDepth(ficlVm *vm) 475*a1bf3f78SToomas Soome { 476*a1bf3f78SToomas Soome int i; 477*a1bf3f78SToomas Soome 478*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 0, 1); 479*a1bf3f78SToomas Soome 480*a1bf3f78SToomas Soome i = ficlStackDepth(vm->dataStack); 481*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, i); 482*a1bf3f78SToomas Soome } 483*a1bf3f78SToomas Soome 484*a1bf3f78SToomas Soome /* 485*a1bf3f78SToomas Soome * e m i t & f r i e n d s 486*a1bf3f78SToomas Soome */ 487*a1bf3f78SToomas Soome static void 488*a1bf3f78SToomas Soome ficlPrimitiveEmit(ficlVm *vm) 489*a1bf3f78SToomas Soome { 490*a1bf3f78SToomas Soome char buffer[2]; 491*a1bf3f78SToomas Soome int i; 492*a1bf3f78SToomas Soome 493*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 494*a1bf3f78SToomas Soome 495*a1bf3f78SToomas Soome i = ficlStackPopInteger(vm->dataStack); 496*a1bf3f78SToomas Soome buffer[0] = (char)i; 497*a1bf3f78SToomas Soome buffer[1] = '\0'; 498*a1bf3f78SToomas Soome ficlVmTextOut(vm, buffer); 499*a1bf3f78SToomas Soome } 500*a1bf3f78SToomas Soome 501*a1bf3f78SToomas Soome static void 502*a1bf3f78SToomas Soome ficlPrimitiveCR(ficlVm *vm) 503*a1bf3f78SToomas Soome { 504*a1bf3f78SToomas Soome ficlVmTextOut(vm, "\n"); 505*a1bf3f78SToomas Soome } 506*a1bf3f78SToomas Soome 507*a1bf3f78SToomas Soome static void 508*a1bf3f78SToomas Soome ficlPrimitiveBackslash(ficlVm *vm) 509*a1bf3f78SToomas Soome { 510*a1bf3f78SToomas Soome char *trace = ficlVmGetInBuf(vm); 511*a1bf3f78SToomas Soome char *stop = ficlVmGetInBufEnd(vm); 512*a1bf3f78SToomas Soome char c = *trace; 513*a1bf3f78SToomas Soome 514*a1bf3f78SToomas Soome while ((trace != stop) && (c != '\r') && (c != '\n')) { 515*a1bf3f78SToomas Soome c = *++trace; 516*a1bf3f78SToomas Soome } 517*a1bf3f78SToomas Soome 518*a1bf3f78SToomas Soome /* 519*a1bf3f78SToomas Soome * Cope with DOS or UNIX-style EOLs - 520*a1bf3f78SToomas Soome * Check for /r, /n, /r/n, or /n/r end-of-line sequences, 521*a1bf3f78SToomas Soome * and point trace to next char. If EOL is \0, we're done. 522*a1bf3f78SToomas Soome */ 523*a1bf3f78SToomas Soome if (trace != stop) { 524*a1bf3f78SToomas Soome trace++; 525*a1bf3f78SToomas Soome 526*a1bf3f78SToomas Soome if ((trace != stop) && (c != *trace) && 527*a1bf3f78SToomas Soome ((*trace == '\r') || (*trace == '\n'))) 528*a1bf3f78SToomas Soome trace++; 529*a1bf3f78SToomas Soome } 530*a1bf3f78SToomas Soome 531*a1bf3f78SToomas Soome ficlVmUpdateTib(vm, trace); 532*a1bf3f78SToomas Soome } 533*a1bf3f78SToomas Soome 534*a1bf3f78SToomas Soome /* 535*a1bf3f78SToomas Soome * paren CORE 536*a1bf3f78SToomas Soome * Compilation: Perform the execution semantics given below. 537*a1bf3f78SToomas Soome * Execution: ( "ccc<paren>" -- ) 538*a1bf3f78SToomas Soome * Parse ccc delimited by ) (right parenthesis). ( is an immediate word. 539*a1bf3f78SToomas Soome * The number of characters in ccc may be zero to the number of characters 540*a1bf3f78SToomas Soome * in the parse area. 541*a1bf3f78SToomas Soome */ 542*a1bf3f78SToomas Soome static void 543*a1bf3f78SToomas Soome ficlPrimitiveParenthesis(ficlVm *vm) 544*a1bf3f78SToomas Soome { 545*a1bf3f78SToomas Soome ficlVmParseStringEx(vm, ')', 0); 546*a1bf3f78SToomas Soome } 547*a1bf3f78SToomas Soome 548*a1bf3f78SToomas Soome /* 549*a1bf3f78SToomas Soome * F E T C H & S T O R E 550*a1bf3f78SToomas Soome */ 551*a1bf3f78SToomas Soome 552*a1bf3f78SToomas Soome /* 553*a1bf3f78SToomas Soome * i f C o I m 554*a1bf3f78SToomas Soome * IMMEDIATE 555*a1bf3f78SToomas Soome * Compiles code for a conditional branch into the dictionary 556*a1bf3f78SToomas Soome * and pushes the branch patch address on the stack for later 557*a1bf3f78SToomas Soome * patching by ELSE or THEN/ENDIF. 558*a1bf3f78SToomas Soome */ 559*a1bf3f78SToomas Soome static void 560*a1bf3f78SToomas Soome ficlPrimitiveIfCoIm(ficlVm *vm) 561*a1bf3f78SToomas Soome { 562*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 563*a1bf3f78SToomas Soome 564*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 565*a1bf3f78SToomas Soome ficlInstructionBranch0ParenWithCheck); 566*a1bf3f78SToomas Soome markBranch(dictionary, vm, origTag); 567*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 1); 568*a1bf3f78SToomas Soome } 569*a1bf3f78SToomas Soome 570*a1bf3f78SToomas Soome /* 571*a1bf3f78SToomas Soome * e l s e C o I m 572*a1bf3f78SToomas Soome * 573*a1bf3f78SToomas Soome * IMMEDIATE -- compiles an "else"... 574*a1bf3f78SToomas Soome * 1) FICL_VM_STATE_COMPILE a branch and a patch address; 575*a1bf3f78SToomas Soome * the address gets patched 576*a1bf3f78SToomas Soome * by "endif" to point past the "else" code. 577*a1bf3f78SToomas Soome * 2) Pop the the "if" patch address 578*a1bf3f78SToomas Soome * 3) Patch the "if" branch to point to the current FICL_VM_STATE_COMPILE 579*a1bf3f78SToomas Soome * address. 580*a1bf3f78SToomas Soome * 4) Push the "else" patch address. ("endif" patches this to jump past 581*a1bf3f78SToomas Soome * the "else" code. 582*a1bf3f78SToomas Soome */ 583*a1bf3f78SToomas Soome static void 584*a1bf3f78SToomas Soome ficlPrimitiveElseCoIm(ficlVm *vm) 585*a1bf3f78SToomas Soome { 586*a1bf3f78SToomas Soome ficlCell *patchAddr; 587*a1bf3f78SToomas Soome ficlInteger offset; 588*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 589*a1bf3f78SToomas Soome 590*a1bf3f78SToomas Soome /* (1) FICL_VM_STATE_COMPILE branch runtime */ 591*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 592*a1bf3f78SToomas Soome ficlInstructionBranchParenWithCheck); 593*a1bf3f78SToomas Soome 594*a1bf3f78SToomas Soome matchControlTag(vm, origTag); 595*a1bf3f78SToomas Soome /* (2) pop "if" patch addr */ 596*a1bf3f78SToomas Soome patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack); 597*a1bf3f78SToomas Soome markBranch(dictionary, vm, origTag); /* (4) push "else" patch addr */ 598*a1bf3f78SToomas Soome 599*a1bf3f78SToomas Soome /* (1) FICL_VM_STATE_COMPILE patch placeholder */ 600*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 1); 601*a1bf3f78SToomas Soome offset = dictionary->here - patchAddr; 602*a1bf3f78SToomas Soome (*patchAddr).i = offset; /* (3) Patch "if" */ 603*a1bf3f78SToomas Soome } 604*a1bf3f78SToomas Soome 605*a1bf3f78SToomas Soome /* 606*a1bf3f78SToomas Soome * e n d i f C o I m 607*a1bf3f78SToomas Soome */ 608*a1bf3f78SToomas Soome static void 609*a1bf3f78SToomas Soome ficlPrimitiveEndifCoIm(ficlVm *vm) 610*a1bf3f78SToomas Soome { 611*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 612*a1bf3f78SToomas Soome resolveForwardBranch(dictionary, vm, origTag); 613*a1bf3f78SToomas Soome } 614*a1bf3f78SToomas Soome 615*a1bf3f78SToomas Soome /* 616*a1bf3f78SToomas Soome * c a s e C o I m 617*a1bf3f78SToomas Soome * IMMEDIATE FICL_VM_STATE_COMPILE-ONLY 618*a1bf3f78SToomas Soome * 619*a1bf3f78SToomas Soome * 620*a1bf3f78SToomas Soome * At FICL_VM_STATE_COMPILE-time, a CASE-SYS (see DPANS94 6.2.0873) looks 621*a1bf3f78SToomas Soome * like this: 622*a1bf3f78SToomas Soome * i*addr i caseTag 623*a1bf3f78SToomas Soome * and an OF-SYS (see DPANS94 6.2.1950) looks like this: 624*a1bf3f78SToomas Soome * i*addr i caseTag addr ofTag 625*a1bf3f78SToomas Soome * The integer under caseTag is the count of fixup addresses that branch 626*a1bf3f78SToomas Soome * to ENDCASE. 627*a1bf3f78SToomas Soome */ 628*a1bf3f78SToomas Soome static void 629*a1bf3f78SToomas Soome ficlPrimitiveCaseCoIm(ficlVm *vm) 630*a1bf3f78SToomas Soome { 631*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 0, 2); 632*a1bf3f78SToomas Soome 633*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, 0); 634*a1bf3f78SToomas Soome markControlTag(vm, caseTag); 635*a1bf3f78SToomas Soome } 636*a1bf3f78SToomas Soome 637*a1bf3f78SToomas Soome /* 638*a1bf3f78SToomas Soome * e n d c a s eC o I m 639*a1bf3f78SToomas Soome * IMMEDIATE FICL_VM_STATE_COMPILE-ONLY 640*a1bf3f78SToomas Soome */ 641*a1bf3f78SToomas Soome static void 642*a1bf3f78SToomas Soome ficlPrimitiveEndcaseCoIm(ficlVm *vm) 643*a1bf3f78SToomas Soome { 644*a1bf3f78SToomas Soome ficlUnsigned fixupCount; 645*a1bf3f78SToomas Soome ficlDictionary *dictionary; 646*a1bf3f78SToomas Soome ficlCell *patchAddr; 647*a1bf3f78SToomas Soome ficlInteger offset; 648*a1bf3f78SToomas Soome 649*a1bf3f78SToomas Soome /* 650*a1bf3f78SToomas Soome * if the last OF ended with FALLTHROUGH, 651*a1bf3f78SToomas Soome * just add the FALLTHROUGH fixup to the 652*a1bf3f78SToomas Soome * ENDOF fixups 653*a1bf3f78SToomas Soome */ 654*a1bf3f78SToomas Soome if (ficlStackGetTop(vm->dataStack).p == fallthroughTag) { 655*a1bf3f78SToomas Soome matchControlTag(vm, fallthroughTag); 656*a1bf3f78SToomas Soome patchAddr = ficlStackPopPointer(vm->dataStack); 657*a1bf3f78SToomas Soome matchControlTag(vm, caseTag); 658*a1bf3f78SToomas Soome fixupCount = ficlStackPopUnsigned(vm->dataStack); 659*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, patchAddr); 660*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, fixupCount + 1); 661*a1bf3f78SToomas Soome markControlTag(vm, caseTag); 662*a1bf3f78SToomas Soome } 663*a1bf3f78SToomas Soome 664*a1bf3f78SToomas Soome matchControlTag(vm, caseTag); 665*a1bf3f78SToomas Soome 666*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 667*a1bf3f78SToomas Soome 668*a1bf3f78SToomas Soome fixupCount = ficlStackPopUnsigned(vm->dataStack); 669*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, fixupCount, 0); 670*a1bf3f78SToomas Soome 671*a1bf3f78SToomas Soome dictionary = ficlVmGetDictionary(vm); 672*a1bf3f78SToomas Soome 673*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, ficlInstructionDrop); 674*a1bf3f78SToomas Soome 675*a1bf3f78SToomas Soome while (fixupCount--) { 676*a1bf3f78SToomas Soome patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack); 677*a1bf3f78SToomas Soome offset = dictionary->here - patchAddr; 678*a1bf3f78SToomas Soome (*patchAddr).i = offset; 679*a1bf3f78SToomas Soome } 680*a1bf3f78SToomas Soome } 681*a1bf3f78SToomas Soome 682*a1bf3f78SToomas Soome /* 683*a1bf3f78SToomas Soome * o f C o I m 684*a1bf3f78SToomas Soome * IMMEDIATE FICL_VM_STATE_COMPILE-ONLY 685*a1bf3f78SToomas Soome */ 686*a1bf3f78SToomas Soome static void 687*a1bf3f78SToomas Soome ficlPrimitiveOfCoIm(ficlVm *vm) 688*a1bf3f78SToomas Soome { 689*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 690*a1bf3f78SToomas Soome ficlCell *fallthroughFixup = NULL; 691*a1bf3f78SToomas Soome 692*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 3); 693*a1bf3f78SToomas Soome 694*a1bf3f78SToomas Soome if (ficlStackGetTop(vm->dataStack).p == fallthroughTag) { 695*a1bf3f78SToomas Soome matchControlTag(vm, fallthroughTag); 696*a1bf3f78SToomas Soome fallthroughFixup = ficlStackPopPointer(vm->dataStack); 697*a1bf3f78SToomas Soome } 698*a1bf3f78SToomas Soome 699*a1bf3f78SToomas Soome matchControlTag(vm, caseTag); 700*a1bf3f78SToomas Soome 701*a1bf3f78SToomas Soome markControlTag(vm, caseTag); 702*a1bf3f78SToomas Soome 703*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, ficlInstructionOfParen); 704*a1bf3f78SToomas Soome markBranch(dictionary, vm, ofTag); 705*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 2); 706*a1bf3f78SToomas Soome 707*a1bf3f78SToomas Soome if (fallthroughFixup != NULL) { 708*a1bf3f78SToomas Soome ficlInteger offset = dictionary->here - fallthroughFixup; 709*a1bf3f78SToomas Soome (*fallthroughFixup).i = offset; 710*a1bf3f78SToomas Soome } 711*a1bf3f78SToomas Soome } 712*a1bf3f78SToomas Soome 713*a1bf3f78SToomas Soome /* 714*a1bf3f78SToomas Soome * e n d o f C o I m 715*a1bf3f78SToomas Soome * IMMEDIATE FICL_VM_STATE_COMPILE-ONLY 716*a1bf3f78SToomas Soome */ 717*a1bf3f78SToomas Soome static void 718*a1bf3f78SToomas Soome ficlPrimitiveEndofCoIm(ficlVm *vm) 719*a1bf3f78SToomas Soome { 720*a1bf3f78SToomas Soome ficlCell *patchAddr; 721*a1bf3f78SToomas Soome ficlUnsigned fixupCount; 722*a1bf3f78SToomas Soome ficlInteger offset; 723*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 724*a1bf3f78SToomas Soome 725*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 4, 3); 726*a1bf3f78SToomas Soome 727*a1bf3f78SToomas Soome /* ensure we're in an OF, */ 728*a1bf3f78SToomas Soome matchControlTag(vm, ofTag); 729*a1bf3f78SToomas Soome 730*a1bf3f78SToomas Soome /* grab the address of the branch location after the OF */ 731*a1bf3f78SToomas Soome patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack); 732*a1bf3f78SToomas Soome /* ensure we're also in a "case" */ 733*a1bf3f78SToomas Soome matchControlTag(vm, caseTag); 734*a1bf3f78SToomas Soome /* grab the current number of ENDOF fixups */ 735*a1bf3f78SToomas Soome fixupCount = ficlStackPopUnsigned(vm->dataStack); 736*a1bf3f78SToomas Soome 737*a1bf3f78SToomas Soome /* FICL_VM_STATE_COMPILE branch runtime */ 738*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 739*a1bf3f78SToomas Soome ficlInstructionBranchParenWithCheck); 740*a1bf3f78SToomas Soome 741*a1bf3f78SToomas Soome /* 742*a1bf3f78SToomas Soome * push a new ENDOF fixup, the updated count of ENDOF fixups, 743*a1bf3f78SToomas Soome * and the caseTag 744*a1bf3f78SToomas Soome */ 745*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, dictionary->here); 746*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, fixupCount + 1); 747*a1bf3f78SToomas Soome markControlTag(vm, caseTag); 748*a1bf3f78SToomas Soome 749*a1bf3f78SToomas Soome /* reserve space for the ENDOF fixup */ 750*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 2); 751*a1bf3f78SToomas Soome 752*a1bf3f78SToomas Soome /* and patch the original OF */ 753*a1bf3f78SToomas Soome offset = dictionary->here - patchAddr; 754*a1bf3f78SToomas Soome (*patchAddr).i = offset; 755*a1bf3f78SToomas Soome } 756*a1bf3f78SToomas Soome 757*a1bf3f78SToomas Soome /* 758*a1bf3f78SToomas Soome * f a l l t h r o u g h C o I m 759*a1bf3f78SToomas Soome * IMMEDIATE FICL_VM_STATE_COMPILE-ONLY 760*a1bf3f78SToomas Soome */ 761*a1bf3f78SToomas Soome static void 762*a1bf3f78SToomas Soome ficlPrimitiveFallthroughCoIm(ficlVm *vm) 763*a1bf3f78SToomas Soome { 764*a1bf3f78SToomas Soome ficlCell *patchAddr; 765*a1bf3f78SToomas Soome ficlInteger offset; 766*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 767*a1bf3f78SToomas Soome 768*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 4, 3); 769*a1bf3f78SToomas Soome 770*a1bf3f78SToomas Soome /* ensure we're in an OF, */ 771*a1bf3f78SToomas Soome matchControlTag(vm, ofTag); 772*a1bf3f78SToomas Soome /* grab the address of the branch location after the OF */ 773*a1bf3f78SToomas Soome patchAddr = (ficlCell *)ficlStackPopPointer(vm->dataStack); 774*a1bf3f78SToomas Soome /* ensure we're also in a "case" */ 775*a1bf3f78SToomas Soome matchControlTag(vm, caseTag); 776*a1bf3f78SToomas Soome 777*a1bf3f78SToomas Soome /* okay, here we go. put the case tag back. */ 778*a1bf3f78SToomas Soome markControlTag(vm, caseTag); 779*a1bf3f78SToomas Soome 780*a1bf3f78SToomas Soome /* FICL_VM_STATE_COMPILE branch runtime */ 781*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 782*a1bf3f78SToomas Soome ficlInstructionBranchParenWithCheck); 783*a1bf3f78SToomas Soome 784*a1bf3f78SToomas Soome /* push a new FALLTHROUGH fixup and the fallthroughTag */ 785*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, dictionary->here); 786*a1bf3f78SToomas Soome markControlTag(vm, fallthroughTag); 787*a1bf3f78SToomas Soome 788*a1bf3f78SToomas Soome /* reserve space for the FALLTHROUGH fixup */ 789*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 2); 790*a1bf3f78SToomas Soome 791*a1bf3f78SToomas Soome /* and patch the original OF */ 792*a1bf3f78SToomas Soome offset = dictionary->here - patchAddr; 793*a1bf3f78SToomas Soome (*patchAddr).i = offset; 794*a1bf3f78SToomas Soome } 795*a1bf3f78SToomas Soome 796*a1bf3f78SToomas Soome /* 797*a1bf3f78SToomas Soome * h a s h 798*a1bf3f78SToomas Soome * hash ( c-addr u -- code) 799*a1bf3f78SToomas Soome * calculates hashcode of specified string and leaves it on the stack 800*a1bf3f78SToomas Soome */ 801*a1bf3f78SToomas Soome static void 802*a1bf3f78SToomas Soome ficlPrimitiveHash(ficlVm *vm) 803*a1bf3f78SToomas Soome { 804*a1bf3f78SToomas Soome ficlString s; 805*a1bf3f78SToomas Soome 806*a1bf3f78SToomas Soome FICL_STRING_SET_LENGTH(s, ficlStackPopUnsigned(vm->dataStack)); 807*a1bf3f78SToomas Soome FICL_STRING_SET_POINTER(s, ficlStackPopPointer(vm->dataStack)); 808*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, ficlHashCode(s)); 809*a1bf3f78SToomas Soome } 810*a1bf3f78SToomas Soome 811*a1bf3f78SToomas Soome /* 812*a1bf3f78SToomas Soome * i n t e r p r e t 813*a1bf3f78SToomas Soome * This is the "user interface" of a Forth. It does the following: 814*a1bf3f78SToomas Soome * while there are words in the VM's Text Input Buffer 815*a1bf3f78SToomas Soome * Copy next word into the pad (ficlVmGetWord) 816*a1bf3f78SToomas Soome * Attempt to find the word in the dictionary (ficlDictionaryLookup) 817*a1bf3f78SToomas Soome * If successful, execute the word. 818*a1bf3f78SToomas Soome * Otherwise, attempt to convert the word to a number (isNumber) 819*a1bf3f78SToomas Soome * If successful, push the number onto the parameter stack. 820*a1bf3f78SToomas Soome * Otherwise, print an error message and exit loop... 821*a1bf3f78SToomas Soome * End Loop 822*a1bf3f78SToomas Soome * 823*a1bf3f78SToomas Soome * From the standard, section 3.4 824*a1bf3f78SToomas Soome * Text interpretation (see 6.1.1360 EVALUATE and 6.1.2050 QUIT) shall 825*a1bf3f78SToomas Soome * repeat the following steps until either the parse area is empty or an 826*a1bf3f78SToomas Soome * ambiguous condition exists: 827*a1bf3f78SToomas Soome * a) Skip leading spaces and parse a name (see 3.4.1); 828*a1bf3f78SToomas Soome */ 829*a1bf3f78SToomas Soome static void 830*a1bf3f78SToomas Soome ficlPrimitiveInterpret(ficlVm *vm) 831*a1bf3f78SToomas Soome { 832*a1bf3f78SToomas Soome ficlString s; 833*a1bf3f78SToomas Soome int i; 834*a1bf3f78SToomas Soome ficlSystem *system; 835*a1bf3f78SToomas Soome 836*a1bf3f78SToomas Soome FICL_VM_ASSERT(vm, vm); 837*a1bf3f78SToomas Soome 838*a1bf3f78SToomas Soome system = vm->callback.system; 839*a1bf3f78SToomas Soome s = ficlVmGetWord0(vm); 840*a1bf3f78SToomas Soome 841*a1bf3f78SToomas Soome /* 842*a1bf3f78SToomas Soome * Get next word...if out of text, we're done. 843*a1bf3f78SToomas Soome */ 844*a1bf3f78SToomas Soome if (s.length == 0) { 845*a1bf3f78SToomas Soome ficlVmThrow(vm, FICL_VM_STATUS_OUT_OF_TEXT); 846*a1bf3f78SToomas Soome } 847*a1bf3f78SToomas Soome 848*a1bf3f78SToomas Soome /* 849*a1bf3f78SToomas Soome * Run the parse chain against the incoming token until somebody 850*a1bf3f78SToomas Soome * eats it. Otherwise emit an error message and give up. 851*a1bf3f78SToomas Soome */ 852*a1bf3f78SToomas Soome for (i = 0; i < FICL_MAX_PARSE_STEPS; i++) { 853*a1bf3f78SToomas Soome ficlWord *word = system->parseList[i]; 854*a1bf3f78SToomas Soome 855*a1bf3f78SToomas Soome if (word == NULL) 856*a1bf3f78SToomas Soome break; 857*a1bf3f78SToomas Soome 858*a1bf3f78SToomas Soome if (word->code == ficlPrimitiveParseStepParen) { 859*a1bf3f78SToomas Soome ficlParseStep pStep; 860*a1bf3f78SToomas Soome pStep = (ficlParseStep)(word->param->fn); 861*a1bf3f78SToomas Soome if ((*pStep)(vm, s)) 862*a1bf3f78SToomas Soome return; 863*a1bf3f78SToomas Soome } else { 864*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, 865*a1bf3f78SToomas Soome FICL_STRING_GET_POINTER(s)); 866*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, 867*a1bf3f78SToomas Soome FICL_STRING_GET_LENGTH(s)); 868*a1bf3f78SToomas Soome ficlVmExecuteXT(vm, word); 869*a1bf3f78SToomas Soome if (ficlStackPopInteger(vm->dataStack)) 870*a1bf3f78SToomas Soome return; 871*a1bf3f78SToomas Soome } 872*a1bf3f78SToomas Soome } 873*a1bf3f78SToomas Soome 874*a1bf3f78SToomas Soome ficlVmThrowError(vm, "%.*s not found", FICL_STRING_GET_LENGTH(s), 875*a1bf3f78SToomas Soome FICL_STRING_GET_POINTER(s)); 876*a1bf3f78SToomas Soome /* back to inner interpreter */ 877*a1bf3f78SToomas Soome } 878*a1bf3f78SToomas Soome 879*a1bf3f78SToomas Soome /* 880*a1bf3f78SToomas Soome * Surrogate precompiled parse step for ficlParseWord 881*a1bf3f78SToomas Soome * (this step is hard coded in FICL_VM_STATE_INTERPRET) 882*a1bf3f78SToomas Soome */ 883*a1bf3f78SToomas Soome static void 884*a1bf3f78SToomas Soome ficlPrimitiveLookup(ficlVm *vm) 885*a1bf3f78SToomas Soome { 886*a1bf3f78SToomas Soome ficlString name; 887*a1bf3f78SToomas Soome FICL_STRING_SET_LENGTH(name, ficlStackPopUnsigned(vm->dataStack)); 888*a1bf3f78SToomas Soome FICL_STRING_SET_POINTER(name, ficlStackPopPointer(vm->dataStack)); 889*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, ficlVmParseWord(vm, name)); 890*a1bf3f78SToomas Soome } 891*a1bf3f78SToomas Soome 892*a1bf3f78SToomas Soome /* 893*a1bf3f78SToomas Soome * p a r e n P a r s e S t e p 894*a1bf3f78SToomas Soome * (parse-step) ( c-addr u -- flag ) 895*a1bf3f78SToomas Soome * runtime for a precompiled parse step - pop a counted string off the 896*a1bf3f78SToomas Soome * stack, run the parse step against it, and push the result flag (FICL_TRUE 897*a1bf3f78SToomas Soome * if success, FICL_FALSE otherwise). 898*a1bf3f78SToomas Soome */ 899*a1bf3f78SToomas Soome void 900*a1bf3f78SToomas Soome ficlPrimitiveParseStepParen(ficlVm *vm) 901*a1bf3f78SToomas Soome { 902*a1bf3f78SToomas Soome ficlString s; 903*a1bf3f78SToomas Soome ficlWord *word = vm->runningWord; 904*a1bf3f78SToomas Soome ficlParseStep pStep = (ficlParseStep)(word->param->fn); 905*a1bf3f78SToomas Soome 906*a1bf3f78SToomas Soome FICL_STRING_SET_LENGTH(s, ficlStackPopInteger(vm->dataStack)); 907*a1bf3f78SToomas Soome FICL_STRING_SET_POINTER(s, ficlStackPopPointer(vm->dataStack)); 908*a1bf3f78SToomas Soome 909*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, (*pStep)(vm, s)); 910*a1bf3f78SToomas Soome } 911*a1bf3f78SToomas Soome 912*a1bf3f78SToomas Soome static void 913*a1bf3f78SToomas Soome ficlPrimitiveAddParseStep(ficlVm *vm) 914*a1bf3f78SToomas Soome { 915*a1bf3f78SToomas Soome ficlWord *pStep; 916*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 917*a1bf3f78SToomas Soome 918*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 919*a1bf3f78SToomas Soome 920*a1bf3f78SToomas Soome pStep = (ficlWord *)(ficlStackPop(vm->dataStack).p); 921*a1bf3f78SToomas Soome if ((pStep != NULL) && ficlDictionaryIsAWord(dictionary, pStep)) 922*a1bf3f78SToomas Soome ficlSystemAddParseStep(vm->callback.system, pStep); 923*a1bf3f78SToomas Soome } 924*a1bf3f78SToomas Soome 925*a1bf3f78SToomas Soome /* 926*a1bf3f78SToomas Soome * l i t e r a l I m 927*a1bf3f78SToomas Soome * 928*a1bf3f78SToomas Soome * IMMEDIATE code for "literal". This function gets a value from the stack 929*a1bf3f78SToomas Soome * and compiles it into the dictionary preceded by the code for "(literal)". 930*a1bf3f78SToomas Soome * IMMEDIATE 931*a1bf3f78SToomas Soome */ 932*a1bf3f78SToomas Soome void 933*a1bf3f78SToomas Soome ficlPrimitiveLiteralIm(ficlVm *vm) 934*a1bf3f78SToomas Soome { 935*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 936*a1bf3f78SToomas Soome ficlInteger value; 937*a1bf3f78SToomas Soome 938*a1bf3f78SToomas Soome value = ficlStackPopInteger(vm->dataStack); 939*a1bf3f78SToomas Soome 940*a1bf3f78SToomas Soome switch (value) { 941*a1bf3f78SToomas Soome case 1: 942*a1bf3f78SToomas Soome case 2: 943*a1bf3f78SToomas Soome case 3: 944*a1bf3f78SToomas Soome case 4: 945*a1bf3f78SToomas Soome case 5: 946*a1bf3f78SToomas Soome case 6: 947*a1bf3f78SToomas Soome case 7: 948*a1bf3f78SToomas Soome case 8: 949*a1bf3f78SToomas Soome case 9: 950*a1bf3f78SToomas Soome case 10: 951*a1bf3f78SToomas Soome case 11: 952*a1bf3f78SToomas Soome case 12: 953*a1bf3f78SToomas Soome case 13: 954*a1bf3f78SToomas Soome case 14: 955*a1bf3f78SToomas Soome case 15: 956*a1bf3f78SToomas Soome case 16: 957*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, value); 958*a1bf3f78SToomas Soome break; 959*a1bf3f78SToomas Soome 960*a1bf3f78SToomas Soome case 0: 961*a1bf3f78SToomas Soome case -1: 962*a1bf3f78SToomas Soome case -2: 963*a1bf3f78SToomas Soome case -3: 964*a1bf3f78SToomas Soome case -4: 965*a1bf3f78SToomas Soome case -5: 966*a1bf3f78SToomas Soome case -6: 967*a1bf3f78SToomas Soome case -7: 968*a1bf3f78SToomas Soome case -8: 969*a1bf3f78SToomas Soome case -9: 970*a1bf3f78SToomas Soome case -10: 971*a1bf3f78SToomas Soome case -11: 972*a1bf3f78SToomas Soome case -12: 973*a1bf3f78SToomas Soome case -13: 974*a1bf3f78SToomas Soome case -14: 975*a1bf3f78SToomas Soome case -15: 976*a1bf3f78SToomas Soome case -16: 977*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 978*a1bf3f78SToomas Soome ficlInstruction0 - value); 979*a1bf3f78SToomas Soome break; 980*a1bf3f78SToomas Soome 981*a1bf3f78SToomas Soome default: 982*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 983*a1bf3f78SToomas Soome ficlInstructionLiteralParen); 984*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, value); 985*a1bf3f78SToomas Soome break; 986*a1bf3f78SToomas Soome } 987*a1bf3f78SToomas Soome } 988*a1bf3f78SToomas Soome 989*a1bf3f78SToomas Soome static void 990*a1bf3f78SToomas Soome ficlPrimitive2LiteralIm(ficlVm *vm) 991*a1bf3f78SToomas Soome { 992*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 993*a1bf3f78SToomas Soome 994*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, ficlInstruction2LiteralParen); 995*a1bf3f78SToomas Soome ficlDictionaryAppendCell(dictionary, ficlStackPop(vm->dataStack)); 996*a1bf3f78SToomas Soome ficlDictionaryAppendCell(dictionary, ficlStackPop(vm->dataStack)); 997*a1bf3f78SToomas Soome } 998*a1bf3f78SToomas Soome 999*a1bf3f78SToomas Soome /* 1000*a1bf3f78SToomas Soome * D o / L o o p 1001*a1bf3f78SToomas Soome * do -- IMMEDIATE FICL_VM_STATE_COMPILE ONLY 1002*a1bf3f78SToomas Soome * Compiles code to initialize a loop: FICL_VM_STATE_COMPILE (do), 1003*a1bf3f78SToomas Soome * allot space to hold the "leave" address, push a branch 1004*a1bf3f78SToomas Soome * target address for the loop. 1005*a1bf3f78SToomas Soome * (do) -- runtime for "do" 1006*a1bf3f78SToomas Soome * pops index and limit from the p stack and moves them 1007*a1bf3f78SToomas Soome * to the r stack, then skips to the loop body. 1008*a1bf3f78SToomas Soome * loop -- IMMEDIATE FICL_VM_STATE_COMPILE ONLY 1009*a1bf3f78SToomas Soome * +loop 1010*a1bf3f78SToomas Soome * Compiles code for the test part of a loop: 1011*a1bf3f78SToomas Soome * FICL_VM_STATE_COMPILE (loop), resolve forward branch from "do", and 1012*a1bf3f78SToomas Soome * copy "here" address to the "leave" address allotted by "do" 1013*a1bf3f78SToomas Soome * i,j,k -- FICL_VM_STATE_COMPILE ONLY 1014*a1bf3f78SToomas Soome * Runtime: Push loop indices on param stack (i is innermost loop...) 1015*a1bf3f78SToomas Soome * Note: each loop has three values on the return stack: 1016*a1bf3f78SToomas Soome * ( R: leave limit index ) 1017*a1bf3f78SToomas Soome * "leave" is the absolute address of the next ficlCell after the loop 1018*a1bf3f78SToomas Soome * limit and index are the loop control variables. 1019*a1bf3f78SToomas Soome * leave -- FICL_VM_STATE_COMPILE ONLY 1020*a1bf3f78SToomas Soome * Runtime: pop the loop control variables, then pop the 1021*a1bf3f78SToomas Soome * "leave" address and jump (absolute) there. 1022*a1bf3f78SToomas Soome */ 1023*a1bf3f78SToomas Soome static void 1024*a1bf3f78SToomas Soome ficlPrimitiveDoCoIm(ficlVm *vm) 1025*a1bf3f78SToomas Soome { 1026*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1027*a1bf3f78SToomas Soome 1028*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, ficlInstructionDoParen); 1029*a1bf3f78SToomas Soome /* 1030*a1bf3f78SToomas Soome * Allot space for a pointer to the end 1031*a1bf3f78SToomas Soome * of the loop - "leave" uses this... 1032*a1bf3f78SToomas Soome */ 1033*a1bf3f78SToomas Soome markBranch(dictionary, vm, leaveTag); 1034*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 0); 1035*a1bf3f78SToomas Soome /* 1036*a1bf3f78SToomas Soome * Mark location of head of loop... 1037*a1bf3f78SToomas Soome */ 1038*a1bf3f78SToomas Soome markBranch(dictionary, vm, doTag); 1039*a1bf3f78SToomas Soome } 1040*a1bf3f78SToomas Soome 1041*a1bf3f78SToomas Soome static void 1042*a1bf3f78SToomas Soome ficlPrimitiveQDoCoIm(ficlVm *vm) 1043*a1bf3f78SToomas Soome { 1044*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1045*a1bf3f78SToomas Soome 1046*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, ficlInstructionQDoParen); 1047*a1bf3f78SToomas Soome /* 1048*a1bf3f78SToomas Soome * Allot space for a pointer to the end 1049*a1bf3f78SToomas Soome * of the loop - "leave" uses this... 1050*a1bf3f78SToomas Soome */ 1051*a1bf3f78SToomas Soome markBranch(dictionary, vm, leaveTag); 1052*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 0); 1053*a1bf3f78SToomas Soome /* 1054*a1bf3f78SToomas Soome * Mark location of head of loop... 1055*a1bf3f78SToomas Soome */ 1056*a1bf3f78SToomas Soome markBranch(dictionary, vm, doTag); 1057*a1bf3f78SToomas Soome } 1058*a1bf3f78SToomas Soome 1059*a1bf3f78SToomas Soome 1060*a1bf3f78SToomas Soome static void 1061*a1bf3f78SToomas Soome ficlPrimitiveLoopCoIm(ficlVm *vm) 1062*a1bf3f78SToomas Soome { 1063*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1064*a1bf3f78SToomas Soome 1065*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, ficlInstructionLoopParen); 1066*a1bf3f78SToomas Soome resolveBackBranch(dictionary, vm, doTag); 1067*a1bf3f78SToomas Soome resolveAbsBranch(dictionary, vm, leaveTag); 1068*a1bf3f78SToomas Soome } 1069*a1bf3f78SToomas Soome 1070*a1bf3f78SToomas Soome static void 1071*a1bf3f78SToomas Soome ficlPrimitivePlusLoopCoIm(ficlVm *vm) 1072*a1bf3f78SToomas Soome { 1073*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1074*a1bf3f78SToomas Soome 1075*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, ficlInstructionPlusLoopParen); 1076*a1bf3f78SToomas Soome resolveBackBranch(dictionary, vm, doTag); 1077*a1bf3f78SToomas Soome resolveAbsBranch(dictionary, vm, leaveTag); 1078*a1bf3f78SToomas Soome } 1079*a1bf3f78SToomas Soome 1080*a1bf3f78SToomas Soome /* 1081*a1bf3f78SToomas Soome * v a r i a b l e 1082*a1bf3f78SToomas Soome */ 1083*a1bf3f78SToomas Soome static void 1084*a1bf3f78SToomas Soome ficlPrimitiveVariable(ficlVm *vm) 1085*a1bf3f78SToomas Soome { 1086*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1087*a1bf3f78SToomas Soome ficlString name = ficlVmGetWord(vm); 1088*a1bf3f78SToomas Soome 1089*a1bf3f78SToomas Soome ficlDictionaryAppendWord(dictionary, name, 1090*a1bf3f78SToomas Soome (ficlPrimitive)ficlInstructionVariableParen, FICL_WORD_DEFAULT); 1091*a1bf3f78SToomas Soome ficlVmDictionaryAllotCells(vm, dictionary, 1); 1092*a1bf3f78SToomas Soome } 1093*a1bf3f78SToomas Soome 1094*a1bf3f78SToomas Soome static void 1095*a1bf3f78SToomas Soome ficlPrimitive2Variable(ficlVm *vm) 1096*a1bf3f78SToomas Soome { 1097*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1098*a1bf3f78SToomas Soome ficlString name = ficlVmGetWord(vm); 1099*a1bf3f78SToomas Soome 1100*a1bf3f78SToomas Soome ficlDictionaryAppendWord(dictionary, name, 1101*a1bf3f78SToomas Soome (ficlPrimitive)ficlInstructionVariableParen, FICL_WORD_DEFAULT); 1102*a1bf3f78SToomas Soome ficlVmDictionaryAllotCells(vm, dictionary, 2); 1103*a1bf3f78SToomas Soome } 1104*a1bf3f78SToomas Soome 1105*a1bf3f78SToomas Soome /* 1106*a1bf3f78SToomas Soome * b a s e & f r i e n d s 1107*a1bf3f78SToomas Soome */ 1108*a1bf3f78SToomas Soome static void 1109*a1bf3f78SToomas Soome ficlPrimitiveBase(ficlVm *vm) 1110*a1bf3f78SToomas Soome { 1111*a1bf3f78SToomas Soome ficlCell *pBase, c; 1112*a1bf3f78SToomas Soome 1113*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 0, 1); 1114*a1bf3f78SToomas Soome 1115*a1bf3f78SToomas Soome pBase = (ficlCell *)(&vm->base); 1116*a1bf3f78SToomas Soome c.p = pBase; 1117*a1bf3f78SToomas Soome ficlStackPush(vm->dataStack, c); 1118*a1bf3f78SToomas Soome } 1119*a1bf3f78SToomas Soome 1120*a1bf3f78SToomas Soome static void 1121*a1bf3f78SToomas Soome ficlPrimitiveDecimal(ficlVm *vm) 1122*a1bf3f78SToomas Soome { 1123*a1bf3f78SToomas Soome vm->base = 10; 1124*a1bf3f78SToomas Soome } 1125*a1bf3f78SToomas Soome 1126*a1bf3f78SToomas Soome 1127*a1bf3f78SToomas Soome static void 1128*a1bf3f78SToomas Soome ficlPrimitiveHex(ficlVm *vm) 1129*a1bf3f78SToomas Soome { 1130*a1bf3f78SToomas Soome vm->base = 16; 1131*a1bf3f78SToomas Soome } 1132*a1bf3f78SToomas Soome 1133*a1bf3f78SToomas Soome /* 1134*a1bf3f78SToomas Soome * a l l o t & f r i e n d s 1135*a1bf3f78SToomas Soome */ 1136*a1bf3f78SToomas Soome static void 1137*a1bf3f78SToomas Soome ficlPrimitiveAllot(ficlVm *vm) 1138*a1bf3f78SToomas Soome { 1139*a1bf3f78SToomas Soome ficlDictionary *dictionary; 1140*a1bf3f78SToomas Soome ficlInteger i; 1141*a1bf3f78SToomas Soome 1142*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 1143*a1bf3f78SToomas Soome 1144*a1bf3f78SToomas Soome dictionary = ficlVmGetDictionary(vm); 1145*a1bf3f78SToomas Soome i = ficlStackPopInteger(vm->dataStack); 1146*a1bf3f78SToomas Soome 1147*a1bf3f78SToomas Soome FICL_VM_DICTIONARY_CHECK(vm, dictionary, i); 1148*a1bf3f78SToomas Soome 1149*a1bf3f78SToomas Soome ficlVmDictionaryAllot(vm, dictionary, i); 1150*a1bf3f78SToomas Soome } 1151*a1bf3f78SToomas Soome 1152*a1bf3f78SToomas Soome static void 1153*a1bf3f78SToomas Soome ficlPrimitiveHere(ficlVm *vm) 1154*a1bf3f78SToomas Soome { 1155*a1bf3f78SToomas Soome ficlDictionary *dictionary; 1156*a1bf3f78SToomas Soome 1157*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 0, 1); 1158*a1bf3f78SToomas Soome 1159*a1bf3f78SToomas Soome dictionary = ficlVmGetDictionary(vm); 1160*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, dictionary->here); 1161*a1bf3f78SToomas Soome } 1162*a1bf3f78SToomas Soome 1163*a1bf3f78SToomas Soome /* 1164*a1bf3f78SToomas Soome * t i c k 1165*a1bf3f78SToomas Soome * tick CORE ( "<spaces>name" -- xt ) 1166*a1bf3f78SToomas Soome * Skip leading space delimiters. Parse name delimited by a space. Find 1167*a1bf3f78SToomas Soome * name and return xt, the execution token for name. An ambiguous condition 1168*a1bf3f78SToomas Soome * exists if name is not found. 1169*a1bf3f78SToomas Soome */ 1170*a1bf3f78SToomas Soome void 1171*a1bf3f78SToomas Soome ficlPrimitiveTick(ficlVm *vm) 1172*a1bf3f78SToomas Soome { 1173*a1bf3f78SToomas Soome ficlWord *word = NULL; 1174*a1bf3f78SToomas Soome ficlString name = ficlVmGetWord(vm); 1175*a1bf3f78SToomas Soome 1176*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 0, 1); 1177*a1bf3f78SToomas Soome 1178*a1bf3f78SToomas Soome word = ficlDictionaryLookup(ficlVmGetDictionary(vm), name); 1179*a1bf3f78SToomas Soome if (!word) 1180*a1bf3f78SToomas Soome ficlVmThrowError(vm, "%.*s not found", 1181*a1bf3f78SToomas Soome FICL_STRING_GET_LENGTH(name), 1182*a1bf3f78SToomas Soome FICL_STRING_GET_POINTER(name)); 1183*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, word); 1184*a1bf3f78SToomas Soome } 1185*a1bf3f78SToomas Soome 1186*a1bf3f78SToomas Soome static void 1187*a1bf3f78SToomas Soome ficlPrimitiveBracketTickCoIm(ficlVm *vm) 1188*a1bf3f78SToomas Soome { 1189*a1bf3f78SToomas Soome ficlPrimitiveTick(vm); 1190*a1bf3f78SToomas Soome ficlPrimitiveLiteralIm(vm); 1191*a1bf3f78SToomas Soome } 1192*a1bf3f78SToomas Soome 1193*a1bf3f78SToomas Soome /* 1194*a1bf3f78SToomas Soome * p o s t p o n e 1195*a1bf3f78SToomas Soome * Lookup the next word in the input stream and FICL_VM_STATE_COMPILE code to 1196*a1bf3f78SToomas Soome * insert it into definitions created by the resulting word 1197*a1bf3f78SToomas Soome * (defers compilation, even of immediate words) 1198*a1bf3f78SToomas Soome */ 1199*a1bf3f78SToomas Soome static void 1200*a1bf3f78SToomas Soome ficlPrimitivePostponeCoIm(ficlVm *vm) 1201*a1bf3f78SToomas Soome { 1202*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1203*a1bf3f78SToomas Soome ficlWord *word; 1204*a1bf3f78SToomas Soome ficlWord *pComma = ficlSystemLookup(vm->callback.system, ","); 1205*a1bf3f78SToomas Soome ficlCell c; 1206*a1bf3f78SToomas Soome 1207*a1bf3f78SToomas Soome FICL_VM_ASSERT(vm, pComma); 1208*a1bf3f78SToomas Soome 1209*a1bf3f78SToomas Soome ficlPrimitiveTick(vm); 1210*a1bf3f78SToomas Soome word = ficlStackGetTop(vm->dataStack).p; 1211*a1bf3f78SToomas Soome if (ficlWordIsImmediate(word)) { 1212*a1bf3f78SToomas Soome ficlDictionaryAppendCell(dictionary, 1213*a1bf3f78SToomas Soome ficlStackPop(vm->dataStack)); 1214*a1bf3f78SToomas Soome } else { 1215*a1bf3f78SToomas Soome ficlPrimitiveLiteralIm(vm); 1216*a1bf3f78SToomas Soome c.p = pComma; 1217*a1bf3f78SToomas Soome ficlDictionaryAppendCell(dictionary, c); 1218*a1bf3f78SToomas Soome } 1219*a1bf3f78SToomas Soome } 1220*a1bf3f78SToomas Soome 1221*a1bf3f78SToomas Soome /* 1222*a1bf3f78SToomas Soome * e x e c u t e 1223*a1bf3f78SToomas Soome * Pop an execution token (pointer to a word) off the stack and 1224*a1bf3f78SToomas Soome * run it 1225*a1bf3f78SToomas Soome */ 1226*a1bf3f78SToomas Soome static void 1227*a1bf3f78SToomas Soome ficlPrimitiveExecute(ficlVm *vm) 1228*a1bf3f78SToomas Soome { 1229*a1bf3f78SToomas Soome ficlWord *word; 1230*a1bf3f78SToomas Soome 1231*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 1232*a1bf3f78SToomas Soome 1233*a1bf3f78SToomas Soome word = ficlStackPopPointer(vm->dataStack); 1234*a1bf3f78SToomas Soome ficlVmExecuteWord(vm, word); 1235*a1bf3f78SToomas Soome } 1236*a1bf3f78SToomas Soome 1237*a1bf3f78SToomas Soome /* 1238*a1bf3f78SToomas Soome * i m m e d i a t e 1239*a1bf3f78SToomas Soome * Make the most recently compiled word IMMEDIATE -- it executes even 1240*a1bf3f78SToomas Soome * in FICL_VM_STATE_COMPILE state (most often used for control compiling words 1241*a1bf3f78SToomas Soome * such as IF, THEN, etc) 1242*a1bf3f78SToomas Soome */ 1243*a1bf3f78SToomas Soome static void 1244*a1bf3f78SToomas Soome ficlPrimitiveImmediate(ficlVm *vm) 1245*a1bf3f78SToomas Soome { 1246*a1bf3f78SToomas Soome FICL_IGNORE(vm); 1247*a1bf3f78SToomas Soome ficlDictionarySetImmediate(ficlVmGetDictionary(vm)); 1248*a1bf3f78SToomas Soome } 1249*a1bf3f78SToomas Soome 1250*a1bf3f78SToomas Soome static void 1251*a1bf3f78SToomas Soome ficlPrimitiveCompileOnly(ficlVm *vm) 1252*a1bf3f78SToomas Soome { 1253*a1bf3f78SToomas Soome FICL_IGNORE(vm); 1254*a1bf3f78SToomas Soome ficlDictionarySetFlags(ficlVmGetDictionary(vm), FICL_WORD_COMPILE_ONLY); 1255*a1bf3f78SToomas Soome } 1256*a1bf3f78SToomas Soome 1257*a1bf3f78SToomas Soome static void 1258*a1bf3f78SToomas Soome ficlPrimitiveSetObjectFlag(ficlVm *vm) 1259*a1bf3f78SToomas Soome { 1260*a1bf3f78SToomas Soome FICL_IGNORE(vm); 1261*a1bf3f78SToomas Soome ficlDictionarySetFlags(ficlVmGetDictionary(vm), FICL_WORD_OBJECT); 1262*a1bf3f78SToomas Soome } 1263*a1bf3f78SToomas Soome 1264*a1bf3f78SToomas Soome static void 1265*a1bf3f78SToomas Soome ficlPrimitiveIsObject(ficlVm *vm) 1266*a1bf3f78SToomas Soome { 1267*a1bf3f78SToomas Soome ficlInteger flag; 1268*a1bf3f78SToomas Soome ficlWord *word = (ficlWord *)ficlStackPopPointer(vm->dataStack); 1269*a1bf3f78SToomas Soome 1270*a1bf3f78SToomas Soome flag = ((word != NULL) && (word->flags & FICL_WORD_OBJECT))? 1271*a1bf3f78SToomas Soome FICL_TRUE : FICL_FALSE; 1272*a1bf3f78SToomas Soome 1273*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, flag); 1274*a1bf3f78SToomas Soome } 1275*a1bf3f78SToomas Soome 1276*a1bf3f78SToomas Soome static void 1277*a1bf3f78SToomas Soome ficlPrimitiveCountedStringQuoteIm(ficlVm *vm) 1278*a1bf3f78SToomas Soome { 1279*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1280*a1bf3f78SToomas Soome 1281*a1bf3f78SToomas Soome if (vm->state == FICL_VM_STATE_INTERPRET) { 1282*a1bf3f78SToomas Soome ficlCountedString *counted = (ficlCountedString *) 1283*a1bf3f78SToomas Soome dictionary->here; 1284*a1bf3f78SToomas Soome 1285*a1bf3f78SToomas Soome ficlVmGetString(vm, counted, '\"'); 1286*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, counted); 1287*a1bf3f78SToomas Soome 1288*a1bf3f78SToomas Soome /* 1289*a1bf3f78SToomas Soome * move HERE past string so it doesn't get overwritten. --lch 1290*a1bf3f78SToomas Soome */ 1291*a1bf3f78SToomas Soome ficlVmDictionaryAllot(vm, dictionary, 1292*a1bf3f78SToomas Soome counted->length + sizeof (ficlUnsigned8)); 1293*a1bf3f78SToomas Soome } else { /* FICL_VM_STATE_COMPILE state */ 1294*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 1295*a1bf3f78SToomas Soome ficlInstructionCStringLiteralParen); 1296*a1bf3f78SToomas Soome dictionary->here = 1297*a1bf3f78SToomas Soome FICL_POINTER_TO_CELL(ficlVmGetString(vm, 1298*a1bf3f78SToomas Soome (ficlCountedString *)dictionary->here, '\"')); 1299*a1bf3f78SToomas Soome ficlDictionaryAlign(dictionary); 1300*a1bf3f78SToomas Soome } 1301*a1bf3f78SToomas Soome } 1302*a1bf3f78SToomas Soome 1303*a1bf3f78SToomas Soome /* 1304*a1bf3f78SToomas Soome * d o t Q u o t e 1305*a1bf3f78SToomas Soome * IMMEDIATE word that compiles a string literal for later display 1306*a1bf3f78SToomas Soome * FICL_VM_STATE_COMPILE fiStringLiteralParen, then copy the bytes of the 1307*a1bf3f78SToomas Soome * string from the 1308*a1bf3f78SToomas Soome * TIB to the dictionary. Backpatch the count byte and align the dictionary. 1309*a1bf3f78SToomas Soome */ 1310*a1bf3f78SToomas Soome static void 1311*a1bf3f78SToomas Soome ficlPrimitiveDotQuoteCoIm(ficlVm *vm) 1312*a1bf3f78SToomas Soome { 1313*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1314*a1bf3f78SToomas Soome ficlWord *pType = ficlSystemLookup(vm->callback.system, "type"); 1315*a1bf3f78SToomas Soome ficlCell c; 1316*a1bf3f78SToomas Soome 1317*a1bf3f78SToomas Soome FICL_VM_ASSERT(vm, pType); 1318*a1bf3f78SToomas Soome 1319*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 1320*a1bf3f78SToomas Soome ficlInstructionStringLiteralParen); 1321*a1bf3f78SToomas Soome dictionary->here = 1322*a1bf3f78SToomas Soome FICL_POINTER_TO_CELL(ficlVmGetString(vm, 1323*a1bf3f78SToomas Soome (ficlCountedString *)dictionary->here, '\"')); 1324*a1bf3f78SToomas Soome ficlDictionaryAlign(dictionary); 1325*a1bf3f78SToomas Soome c.p = pType; 1326*a1bf3f78SToomas Soome ficlDictionaryAppendCell(dictionary, c); 1327*a1bf3f78SToomas Soome } 1328*a1bf3f78SToomas Soome 1329*a1bf3f78SToomas Soome static void 1330*a1bf3f78SToomas Soome ficlPrimitiveDotParen(ficlVm *vm) 1331*a1bf3f78SToomas Soome { 1332*a1bf3f78SToomas Soome char *from = ficlVmGetInBuf(vm); 1333*a1bf3f78SToomas Soome char *stop = ficlVmGetInBufEnd(vm); 1334*a1bf3f78SToomas Soome char *to = vm->pad; 1335*a1bf3f78SToomas Soome char c; 1336*a1bf3f78SToomas Soome 1337*a1bf3f78SToomas Soome /* 1338*a1bf3f78SToomas Soome * Note: the standard does not want leading spaces skipped. 1339*a1bf3f78SToomas Soome */ 1340*a1bf3f78SToomas Soome for (c = *from; (from != stop) && (c != ')'); c = *++from) 1341*a1bf3f78SToomas Soome *to++ = c; 1342*a1bf3f78SToomas Soome 1343*a1bf3f78SToomas Soome *to = '\0'; 1344*a1bf3f78SToomas Soome if ((from != stop) && (c == ')')) 1345*a1bf3f78SToomas Soome from++; 1346*a1bf3f78SToomas Soome 1347*a1bf3f78SToomas Soome ficlVmTextOut(vm, vm->pad); 1348*a1bf3f78SToomas Soome ficlVmUpdateTib(vm, from); 1349*a1bf3f78SToomas Soome } 1350*a1bf3f78SToomas Soome 1351*a1bf3f78SToomas Soome /* 1352*a1bf3f78SToomas Soome * s l i t e r a l 1353*a1bf3f78SToomas Soome * STRING 1354*a1bf3f78SToomas Soome * Interpretation: Interpretation semantics for this word are undefined. 1355*a1bf3f78SToomas Soome * Compilation: ( c-addr1 u -- ) 1356*a1bf3f78SToomas Soome * Append the run-time semantics given below to the current definition. 1357*a1bf3f78SToomas Soome * Run-time: ( -- c-addr2 u ) 1358*a1bf3f78SToomas Soome * Return c-addr2 u describing a string consisting of the characters 1359*a1bf3f78SToomas Soome * specified by c-addr1 u during compilation. A program shall not alter 1360*a1bf3f78SToomas Soome * the returned string. 1361*a1bf3f78SToomas Soome */ 1362*a1bf3f78SToomas Soome static void ficlPrimitiveSLiteralCoIm(ficlVm *vm) 1363*a1bf3f78SToomas Soome { 1364*a1bf3f78SToomas Soome ficlDictionary *dictionary; 1365*a1bf3f78SToomas Soome char *from; 1366*a1bf3f78SToomas Soome char *to; 1367*a1bf3f78SToomas Soome ficlUnsigned length; 1368*a1bf3f78SToomas Soome 1369*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 0); 1370*a1bf3f78SToomas Soome 1371*a1bf3f78SToomas Soome dictionary = ficlVmGetDictionary(vm); 1372*a1bf3f78SToomas Soome length = ficlStackPopUnsigned(vm->dataStack); 1373*a1bf3f78SToomas Soome from = ficlStackPopPointer(vm->dataStack); 1374*a1bf3f78SToomas Soome 1375*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 1376*a1bf3f78SToomas Soome ficlInstructionStringLiteralParen); 1377*a1bf3f78SToomas Soome to = (char *)dictionary->here; 1378*a1bf3f78SToomas Soome *to++ = (char)length; 1379*a1bf3f78SToomas Soome 1380*a1bf3f78SToomas Soome for (; length > 0; --length) { 1381*a1bf3f78SToomas Soome *to++ = *from++; 1382*a1bf3f78SToomas Soome } 1383*a1bf3f78SToomas Soome 1384*a1bf3f78SToomas Soome *to++ = 0; 1385*a1bf3f78SToomas Soome dictionary->here = FICL_POINTER_TO_CELL(ficlAlignPointer(to)); 1386*a1bf3f78SToomas Soome } 1387*a1bf3f78SToomas Soome 1388*a1bf3f78SToomas Soome /* 1389*a1bf3f78SToomas Soome * s t a t e 1390*a1bf3f78SToomas Soome * Return the address of the VM's state member (must be sized the 1391*a1bf3f78SToomas Soome * same as a ficlCell for this reason) 1392*a1bf3f78SToomas Soome */ 1393*a1bf3f78SToomas Soome static void ficlPrimitiveState(ficlVm *vm) 1394*a1bf3f78SToomas Soome { 1395*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 0, 1); 1396*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, &vm->state); 1397*a1bf3f78SToomas Soome } 1398*a1bf3f78SToomas Soome 1399*a1bf3f78SToomas Soome /* 1400*a1bf3f78SToomas Soome * c r e a t e . . . d o e s > 1401*a1bf3f78SToomas Soome * Make a new word in the dictionary with the run-time effect of 1402*a1bf3f78SToomas Soome * a variable (push my address), but with extra space allotted 1403*a1bf3f78SToomas Soome * for use by does> . 1404*a1bf3f78SToomas Soome */ 1405*a1bf3f78SToomas Soome static void 1406*a1bf3f78SToomas Soome ficlPrimitiveCreate(ficlVm *vm) 1407*a1bf3f78SToomas Soome { 1408*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1409*a1bf3f78SToomas Soome ficlString name = ficlVmGetWord(vm); 1410*a1bf3f78SToomas Soome 1411*a1bf3f78SToomas Soome ficlDictionaryAppendWord(dictionary, name, 1412*a1bf3f78SToomas Soome (ficlPrimitive)ficlInstructionCreateParen, FICL_WORD_DEFAULT); 1413*a1bf3f78SToomas Soome ficlVmDictionaryAllotCells(vm, dictionary, 1); 1414*a1bf3f78SToomas Soome } 1415*a1bf3f78SToomas Soome 1416*a1bf3f78SToomas Soome static void 1417*a1bf3f78SToomas Soome ficlPrimitiveDoesCoIm(ficlVm *vm) 1418*a1bf3f78SToomas Soome { 1419*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1420*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 1421*a1bf3f78SToomas Soome if (vm->callback.system->localsCount > 0) { 1422*a1bf3f78SToomas Soome ficlDictionary *locals = 1423*a1bf3f78SToomas Soome ficlSystemGetLocals(vm->callback.system); 1424*a1bf3f78SToomas Soome ficlDictionaryEmpty(locals, locals->forthWordlist->size); 1425*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 1426*a1bf3f78SToomas Soome ficlInstructionUnlinkParen); 1427*a1bf3f78SToomas Soome } 1428*a1bf3f78SToomas Soome 1429*a1bf3f78SToomas Soome vm->callback.system->localsCount = 0; 1430*a1bf3f78SToomas Soome #endif 1431*a1bf3f78SToomas Soome FICL_IGNORE(vm); 1432*a1bf3f78SToomas Soome 1433*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, ficlInstructionDoesParen); 1434*a1bf3f78SToomas Soome } 1435*a1bf3f78SToomas Soome 1436*a1bf3f78SToomas Soome /* 1437*a1bf3f78SToomas Soome * t o b o d y 1438*a1bf3f78SToomas Soome * to-body CORE ( xt -- a-addr ) 1439*a1bf3f78SToomas Soome * a-addr is the data-field address corresponding to xt. An ambiguous 1440*a1bf3f78SToomas Soome * condition exists if xt is not for a word defined via CREATE. 1441*a1bf3f78SToomas Soome */ 1442*a1bf3f78SToomas Soome static void 1443*a1bf3f78SToomas Soome ficlPrimitiveToBody(ficlVm *vm) 1444*a1bf3f78SToomas Soome { 1445*a1bf3f78SToomas Soome ficlWord *word; 1446*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 1); 1447*a1bf3f78SToomas Soome 1448*a1bf3f78SToomas Soome word = ficlStackPopPointer(vm->dataStack); 1449*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, word->param + 1); 1450*a1bf3f78SToomas Soome } 1451*a1bf3f78SToomas Soome 1452*a1bf3f78SToomas Soome /* 1453*a1bf3f78SToomas Soome * from-body Ficl ( a-addr -- xt ) 1454*a1bf3f78SToomas Soome * Reverse effect of >body 1455*a1bf3f78SToomas Soome */ 1456*a1bf3f78SToomas Soome static void 1457*a1bf3f78SToomas Soome ficlPrimitiveFromBody(ficlVm *vm) 1458*a1bf3f78SToomas Soome { 1459*a1bf3f78SToomas Soome char *ptr; 1460*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 1); 1461*a1bf3f78SToomas Soome 1462*a1bf3f78SToomas Soome ptr = (char *)ficlStackPopPointer(vm->dataStack) - sizeof (ficlWord); 1463*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, ptr); 1464*a1bf3f78SToomas Soome } 1465*a1bf3f78SToomas Soome 1466*a1bf3f78SToomas Soome /* 1467*a1bf3f78SToomas Soome * >name Ficl ( xt -- c-addr u ) 1468*a1bf3f78SToomas Soome * Push the address and length of a word's name given its address 1469*a1bf3f78SToomas Soome * xt. 1470*a1bf3f78SToomas Soome */ 1471*a1bf3f78SToomas Soome static void 1472*a1bf3f78SToomas Soome ficlPrimitiveToName(ficlVm *vm) 1473*a1bf3f78SToomas Soome { 1474*a1bf3f78SToomas Soome ficlWord *word; 1475*a1bf3f78SToomas Soome 1476*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 2); 1477*a1bf3f78SToomas Soome 1478*a1bf3f78SToomas Soome word = ficlStackPopPointer(vm->dataStack); 1479*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, word->name); 1480*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, word->length); 1481*a1bf3f78SToomas Soome } 1482*a1bf3f78SToomas Soome 1483*a1bf3f78SToomas Soome static void 1484*a1bf3f78SToomas Soome ficlPrimitiveLastWord(ficlVm *vm) 1485*a1bf3f78SToomas Soome { 1486*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1487*a1bf3f78SToomas Soome ficlWord *wp = dictionary->smudge; 1488*a1bf3f78SToomas Soome ficlCell c; 1489*a1bf3f78SToomas Soome 1490*a1bf3f78SToomas Soome FICL_VM_ASSERT(vm, wp); 1491*a1bf3f78SToomas Soome 1492*a1bf3f78SToomas Soome c.p = wp; 1493*a1bf3f78SToomas Soome ficlVmPush(vm, c); 1494*a1bf3f78SToomas Soome } 1495*a1bf3f78SToomas Soome 1496*a1bf3f78SToomas Soome /* 1497*a1bf3f78SToomas Soome * l b r a c k e t e t c 1498*a1bf3f78SToomas Soome */ 1499*a1bf3f78SToomas Soome static void 1500*a1bf3f78SToomas Soome ficlPrimitiveLeftBracketCoIm(ficlVm *vm) 1501*a1bf3f78SToomas Soome { 1502*a1bf3f78SToomas Soome vm->state = FICL_VM_STATE_INTERPRET; 1503*a1bf3f78SToomas Soome } 1504*a1bf3f78SToomas Soome 1505*a1bf3f78SToomas Soome static void 1506*a1bf3f78SToomas Soome ficlPrimitiveRightBracket(ficlVm *vm) 1507*a1bf3f78SToomas Soome { 1508*a1bf3f78SToomas Soome vm->state = FICL_VM_STATE_COMPILE; 1509*a1bf3f78SToomas Soome } 1510*a1bf3f78SToomas Soome 1511*a1bf3f78SToomas Soome /* 1512*a1bf3f78SToomas Soome * p i c t u r e d n u m e r i c w o r d s 1513*a1bf3f78SToomas Soome * 1514*a1bf3f78SToomas Soome * less-number-sign CORE ( -- ) 1515*a1bf3f78SToomas Soome * Initialize the pictured numeric output conversion process. 1516*a1bf3f78SToomas Soome * (clear the pad) 1517*a1bf3f78SToomas Soome */ 1518*a1bf3f78SToomas Soome static void 1519*a1bf3f78SToomas Soome ficlPrimitiveLessNumberSign(ficlVm *vm) 1520*a1bf3f78SToomas Soome { 1521*a1bf3f78SToomas Soome ficlCountedString *counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad); 1522*a1bf3f78SToomas Soome counted->length = 0; 1523*a1bf3f78SToomas Soome } 1524*a1bf3f78SToomas Soome 1525*a1bf3f78SToomas Soome /* 1526*a1bf3f78SToomas Soome * number-sign CORE ( ud1 -- ud2 ) 1527*a1bf3f78SToomas Soome * Divide ud1 by the number in BASE giving the quotient ud2 and the remainder 1528*a1bf3f78SToomas Soome * n. (n is the least-significant digit of ud1.) Convert n to external form 1529*a1bf3f78SToomas Soome * and add the resulting character to the beginning of the pictured numeric 1530*a1bf3f78SToomas Soome * output string. An ambiguous condition exists if # executes outside of a 1531*a1bf3f78SToomas Soome * <# #> delimited number conversion. 1532*a1bf3f78SToomas Soome */ 1533*a1bf3f78SToomas Soome static void 1534*a1bf3f78SToomas Soome ficlPrimitiveNumberSign(ficlVm *vm) 1535*a1bf3f78SToomas Soome { 1536*a1bf3f78SToomas Soome ficlCountedString *counted; 1537*a1bf3f78SToomas Soome ficl2Unsigned u; 1538*a1bf3f78SToomas Soome ficl2UnsignedQR uqr; 1539*a1bf3f78SToomas Soome 1540*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 2); 1541*a1bf3f78SToomas Soome 1542*a1bf3f78SToomas Soome counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad); 1543*a1bf3f78SToomas Soome u = ficlStackPop2Unsigned(vm->dataStack); 1544*a1bf3f78SToomas Soome uqr = ficl2UnsignedDivide(u, (ficlUnsigned16)(vm->base)); 1545*a1bf3f78SToomas Soome counted->text[counted->length++] = ficlDigitToCharacter(uqr.remainder); 1546*a1bf3f78SToomas Soome ficlStackPush2Unsigned(vm->dataStack, uqr.quotient); 1547*a1bf3f78SToomas Soome } 1548*a1bf3f78SToomas Soome 1549*a1bf3f78SToomas Soome /* 1550*a1bf3f78SToomas Soome * number-sign-greater CORE ( xd -- c-addr u ) 1551*a1bf3f78SToomas Soome * Drop xd. Make the pictured numeric output string available as a character 1552*a1bf3f78SToomas Soome * string. c-addr and u specify the resulting character string. A program 1553*a1bf3f78SToomas Soome * may replace characters within the string. 1554*a1bf3f78SToomas Soome */ 1555*a1bf3f78SToomas Soome static void 1556*a1bf3f78SToomas Soome ficlPrimitiveNumberSignGreater(ficlVm *vm) 1557*a1bf3f78SToomas Soome { 1558*a1bf3f78SToomas Soome ficlCountedString *counted; 1559*a1bf3f78SToomas Soome 1560*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 2); 1561*a1bf3f78SToomas Soome 1562*a1bf3f78SToomas Soome counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad); 1563*a1bf3f78SToomas Soome counted->text[counted->length] = 0; 1564*a1bf3f78SToomas Soome ficlStringReverse(counted->text); 1565*a1bf3f78SToomas Soome ficlStackDrop(vm->dataStack, 2); 1566*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, counted->text); 1567*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, counted->length); 1568*a1bf3f78SToomas Soome } 1569*a1bf3f78SToomas Soome 1570*a1bf3f78SToomas Soome /* 1571*a1bf3f78SToomas Soome * number-sign-s CORE ( ud1 -- ud2 ) 1572*a1bf3f78SToomas Soome * Convert one digit of ud1 according to the rule for #. Continue conversion 1573*a1bf3f78SToomas Soome * until the quotient is zero. ud2 is zero. An ambiguous condition exists if 1574*a1bf3f78SToomas Soome * #S executes outside of a <# #> delimited number conversion. 1575*a1bf3f78SToomas Soome * TO DO: presently does not use ud1 hi ficlCell - use it! 1576*a1bf3f78SToomas Soome */ 1577*a1bf3f78SToomas Soome static void 1578*a1bf3f78SToomas Soome ficlPrimitiveNumberSignS(ficlVm *vm) 1579*a1bf3f78SToomas Soome { 1580*a1bf3f78SToomas Soome ficlCountedString *counted; 1581*a1bf3f78SToomas Soome ficl2Unsigned u; 1582*a1bf3f78SToomas Soome ficl2UnsignedQR uqr; 1583*a1bf3f78SToomas Soome 1584*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 2); 1585*a1bf3f78SToomas Soome 1586*a1bf3f78SToomas Soome counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad); 1587*a1bf3f78SToomas Soome u = ficlStackPop2Unsigned(vm->dataStack); 1588*a1bf3f78SToomas Soome 1589*a1bf3f78SToomas Soome do { 1590*a1bf3f78SToomas Soome uqr = ficl2UnsignedDivide(u, (ficlUnsigned16)(vm->base)); 1591*a1bf3f78SToomas Soome counted->text[counted->length++] = 1592*a1bf3f78SToomas Soome ficlDigitToCharacter(uqr.remainder); 1593*a1bf3f78SToomas Soome u = uqr.quotient; 1594*a1bf3f78SToomas Soome } while (FICL_2UNSIGNED_NOT_ZERO(u)); 1595*a1bf3f78SToomas Soome 1596*a1bf3f78SToomas Soome ficlStackPush2Unsigned(vm->dataStack, u); 1597*a1bf3f78SToomas Soome } 1598*a1bf3f78SToomas Soome 1599*a1bf3f78SToomas Soome /* 1600*a1bf3f78SToomas Soome * HOLD CORE ( char -- ) 1601*a1bf3f78SToomas Soome * Add char to the beginning of the pictured numeric output string. 1602*a1bf3f78SToomas Soome * An ambiguous condition exists if HOLD executes outside of a <# #> 1603*a1bf3f78SToomas Soome * delimited number conversion. 1604*a1bf3f78SToomas Soome */ 1605*a1bf3f78SToomas Soome static void 1606*a1bf3f78SToomas Soome ficlPrimitiveHold(ficlVm *vm) 1607*a1bf3f78SToomas Soome { 1608*a1bf3f78SToomas Soome ficlCountedString *counted; 1609*a1bf3f78SToomas Soome int i; 1610*a1bf3f78SToomas Soome 1611*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 1612*a1bf3f78SToomas Soome 1613*a1bf3f78SToomas Soome counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad); 1614*a1bf3f78SToomas Soome i = ficlStackPopInteger(vm->dataStack); 1615*a1bf3f78SToomas Soome counted->text[counted->length++] = (char)i; 1616*a1bf3f78SToomas Soome } 1617*a1bf3f78SToomas Soome 1618*a1bf3f78SToomas Soome /* 1619*a1bf3f78SToomas Soome * SIGN CORE ( n -- ) 1620*a1bf3f78SToomas Soome * If n is negative, add a minus sign to the beginning of the pictured 1621*a1bf3f78SToomas Soome * numeric output string. An ambiguous condition exists if SIGN 1622*a1bf3f78SToomas Soome * executes outside of a <# #> delimited number conversion. 1623*a1bf3f78SToomas Soome */ 1624*a1bf3f78SToomas Soome static void 1625*a1bf3f78SToomas Soome ficlPrimitiveSign(ficlVm *vm) 1626*a1bf3f78SToomas Soome { 1627*a1bf3f78SToomas Soome ficlCountedString *counted; 1628*a1bf3f78SToomas Soome int i; 1629*a1bf3f78SToomas Soome 1630*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 1631*a1bf3f78SToomas Soome 1632*a1bf3f78SToomas Soome counted = FICL_POINTER_TO_COUNTED_STRING(vm->pad); 1633*a1bf3f78SToomas Soome i = ficlStackPopInteger(vm->dataStack); 1634*a1bf3f78SToomas Soome if (i < 0) 1635*a1bf3f78SToomas Soome counted->text[counted->length++] = '-'; 1636*a1bf3f78SToomas Soome } 1637*a1bf3f78SToomas Soome 1638*a1bf3f78SToomas Soome /* 1639*a1bf3f78SToomas Soome * t o N u m b e r 1640*a1bf3f78SToomas Soome * to-number CORE ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 ) 1641*a1bf3f78SToomas Soome * ud2 is the unsigned result of converting the characters within the 1642*a1bf3f78SToomas Soome * string specified by c-addr1 u1 into digits, using the number in BASE, 1643*a1bf3f78SToomas Soome * and adding each into ud1 after multiplying ud1 by the number in BASE. 1644*a1bf3f78SToomas Soome * Conversion continues left-to-right until a character that is not 1645*a1bf3f78SToomas Soome * convertible, including any + or -, is encountered or the string is 1646*a1bf3f78SToomas Soome * entirely converted. c-addr2 is the location of the first unconverted 1647*a1bf3f78SToomas Soome * character or the first character past the end of the string if the string 1648*a1bf3f78SToomas Soome * was entirely converted. u2 is the number of unconverted characters in the 1649*a1bf3f78SToomas Soome * string. An ambiguous condition exists if ud2 overflows during the 1650*a1bf3f78SToomas Soome * conversion. 1651*a1bf3f78SToomas Soome */ 1652*a1bf3f78SToomas Soome static void 1653*a1bf3f78SToomas Soome ficlPrimitiveToNumber(ficlVm *vm) 1654*a1bf3f78SToomas Soome { 1655*a1bf3f78SToomas Soome ficlUnsigned length; 1656*a1bf3f78SToomas Soome char *trace; 1657*a1bf3f78SToomas Soome ficl2Unsigned accumulator; 1658*a1bf3f78SToomas Soome ficlUnsigned base = vm->base; 1659*a1bf3f78SToomas Soome ficlUnsigned c; 1660*a1bf3f78SToomas Soome ficlUnsigned digit; 1661*a1bf3f78SToomas Soome 1662*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 4, 4); 1663*a1bf3f78SToomas Soome 1664*a1bf3f78SToomas Soome length = ficlStackPopUnsigned(vm->dataStack); 1665*a1bf3f78SToomas Soome trace = (char *)ficlStackPopPointer(vm->dataStack); 1666*a1bf3f78SToomas Soome accumulator = ficlStackPop2Unsigned(vm->dataStack); 1667*a1bf3f78SToomas Soome 1668*a1bf3f78SToomas Soome for (c = *trace; length > 0; c = *++trace, length--) { 1669*a1bf3f78SToomas Soome if (c < '0') 1670*a1bf3f78SToomas Soome break; 1671*a1bf3f78SToomas Soome 1672*a1bf3f78SToomas Soome digit = c - '0'; 1673*a1bf3f78SToomas Soome 1674*a1bf3f78SToomas Soome if (digit > 9) 1675*a1bf3f78SToomas Soome digit = tolower(c) - 'a' + 10; 1676*a1bf3f78SToomas Soome /* 1677*a1bf3f78SToomas Soome * Note: following test also catches chars between 9 and a 1678*a1bf3f78SToomas Soome * because 'digit' is unsigned! 1679*a1bf3f78SToomas Soome */ 1680*a1bf3f78SToomas Soome if (digit >= base) 1681*a1bf3f78SToomas Soome break; 1682*a1bf3f78SToomas Soome 1683*a1bf3f78SToomas Soome accumulator = ficl2UnsignedMultiplyAccumulate(accumulator, 1684*a1bf3f78SToomas Soome base, digit); 1685*a1bf3f78SToomas Soome } 1686*a1bf3f78SToomas Soome 1687*a1bf3f78SToomas Soome ficlStackPush2Unsigned(vm->dataStack, accumulator); 1688*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, trace); 1689*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, length); 1690*a1bf3f78SToomas Soome } 1691*a1bf3f78SToomas Soome 1692*a1bf3f78SToomas Soome /* 1693*a1bf3f78SToomas Soome * q u i t & a b o r t 1694*a1bf3f78SToomas Soome * quit CORE ( -- ) ( R: i*x -- ) 1695*a1bf3f78SToomas Soome * Empty the return stack, store zero in SOURCE-ID if it is present, make 1696*a1bf3f78SToomas Soome * the user input device the input source, and enter interpretation state. 1697*a1bf3f78SToomas Soome * Do not display a message. Repeat the following: 1698*a1bf3f78SToomas Soome * 1699*a1bf3f78SToomas Soome * Accept a line from the input source into the input buffer, set >IN to 1700*a1bf3f78SToomas Soome * zero, and FICL_VM_STATE_INTERPRET. 1701*a1bf3f78SToomas Soome * Display the implementation-defined system prompt if in 1702*a1bf3f78SToomas Soome * interpretation state, all processing has been completed, and no 1703*a1bf3f78SToomas Soome * ambiguous condition exists. 1704*a1bf3f78SToomas Soome */ 1705*a1bf3f78SToomas Soome static void 1706*a1bf3f78SToomas Soome ficlPrimitiveQuit(ficlVm *vm) 1707*a1bf3f78SToomas Soome { 1708*a1bf3f78SToomas Soome ficlVmThrow(vm, FICL_VM_STATUS_QUIT); 1709*a1bf3f78SToomas Soome } 1710*a1bf3f78SToomas Soome 1711*a1bf3f78SToomas Soome static void 1712*a1bf3f78SToomas Soome ficlPrimitiveAbort(ficlVm *vm) 1713*a1bf3f78SToomas Soome { 1714*a1bf3f78SToomas Soome ficlVmThrow(vm, FICL_VM_STATUS_ABORT); 1715*a1bf3f78SToomas Soome } 1716*a1bf3f78SToomas Soome 1717*a1bf3f78SToomas Soome /* 1718*a1bf3f78SToomas Soome * a c c e p t 1719*a1bf3f78SToomas Soome * accept CORE ( c-addr +n1 -- +n2 ) 1720*a1bf3f78SToomas Soome * Receive a string of at most +n1 characters. An ambiguous condition 1721*a1bf3f78SToomas Soome * exists if +n1 is zero or greater than 32,767. Display graphic characters 1722*a1bf3f78SToomas Soome * as they are received. A program that depends on the presence or absence 1723*a1bf3f78SToomas Soome * of non-graphic characters in the string has an environmental dependency. 1724*a1bf3f78SToomas Soome * The editing functions, if any, that the system performs in order to 1725*a1bf3f78SToomas Soome * construct the string are implementation-defined. 1726*a1bf3f78SToomas Soome * 1727*a1bf3f78SToomas Soome * (Although the standard text doesn't say so, I assume that the intent 1728*a1bf3f78SToomas Soome * of 'accept' is to store the string at the address specified on 1729*a1bf3f78SToomas Soome * the stack.) 1730*a1bf3f78SToomas Soome * 1731*a1bf3f78SToomas Soome * NOTE: getchar() is used there as its present both in loader and 1732*a1bf3f78SToomas Soome * userland; however, the more correct solution would be to set 1733*a1bf3f78SToomas Soome * terminal to raw mode for userland. 1734*a1bf3f78SToomas Soome */ 1735*a1bf3f78SToomas Soome static void 1736*a1bf3f78SToomas Soome ficlPrimitiveAccept(ficlVm *vm) 1737*a1bf3f78SToomas Soome { 1738*a1bf3f78SToomas Soome ficlUnsigned size; 1739*a1bf3f78SToomas Soome char *address; 1740*a1bf3f78SToomas Soome int c; 1741*a1bf3f78SToomas Soome ficlUnsigned length = 0; 1742*a1bf3f78SToomas Soome 1743*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 1); 1744*a1bf3f78SToomas Soome 1745*a1bf3f78SToomas Soome size = ficlStackPopInteger(vm->dataStack); 1746*a1bf3f78SToomas Soome address = ficlStackPopPointer(vm->dataStack); 1747*a1bf3f78SToomas Soome 1748*a1bf3f78SToomas Soome while (size != length) { 1749*a1bf3f78SToomas Soome c = getchar(); 1750*a1bf3f78SToomas Soome if (c == '\n' || c == '\r') 1751*a1bf3f78SToomas Soome break; 1752*a1bf3f78SToomas Soome address[length++] = c; 1753*a1bf3f78SToomas Soome } 1754*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, length); 1755*a1bf3f78SToomas Soome } 1756*a1bf3f78SToomas Soome 1757*a1bf3f78SToomas Soome /* 1758*a1bf3f78SToomas Soome * a l i g n 1759*a1bf3f78SToomas Soome * 6.1.0705 ALIGN CORE ( -- ) 1760*a1bf3f78SToomas Soome * If the data-space pointer is not aligned, reserve enough space to 1761*a1bf3f78SToomas Soome * align it. 1762*a1bf3f78SToomas Soome */ 1763*a1bf3f78SToomas Soome static void 1764*a1bf3f78SToomas Soome ficlPrimitiveAlign(ficlVm *vm) 1765*a1bf3f78SToomas Soome { 1766*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1767*a1bf3f78SToomas Soome FICL_IGNORE(vm); 1768*a1bf3f78SToomas Soome ficlDictionaryAlign(dictionary); 1769*a1bf3f78SToomas Soome } 1770*a1bf3f78SToomas Soome 1771*a1bf3f78SToomas Soome /* 1772*a1bf3f78SToomas Soome * a l i g n e d 1773*a1bf3f78SToomas Soome */ 1774*a1bf3f78SToomas Soome static void 1775*a1bf3f78SToomas Soome ficlPrimitiveAligned(ficlVm *vm) 1776*a1bf3f78SToomas Soome { 1777*a1bf3f78SToomas Soome void *addr; 1778*a1bf3f78SToomas Soome 1779*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 1); 1780*a1bf3f78SToomas Soome 1781*a1bf3f78SToomas Soome addr = ficlStackPopPointer(vm->dataStack); 1782*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, ficlAlignPointer(addr)); 1783*a1bf3f78SToomas Soome } 1784*a1bf3f78SToomas Soome 1785*a1bf3f78SToomas Soome /* 1786*a1bf3f78SToomas Soome * b e g i n & f r i e n d s 1787*a1bf3f78SToomas Soome * Indefinite loop control structures 1788*a1bf3f78SToomas Soome * A.6.1.0760 BEGIN 1789*a1bf3f78SToomas Soome * Typical use: 1790*a1bf3f78SToomas Soome * : X ... BEGIN ... test UNTIL ; 1791*a1bf3f78SToomas Soome * or 1792*a1bf3f78SToomas Soome * : X ... BEGIN ... test WHILE ... REPEAT ; 1793*a1bf3f78SToomas Soome */ 1794*a1bf3f78SToomas Soome static void 1795*a1bf3f78SToomas Soome ficlPrimitiveBeginCoIm(ficlVm *vm) 1796*a1bf3f78SToomas Soome { 1797*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1798*a1bf3f78SToomas Soome markBranch(dictionary, vm, destTag); 1799*a1bf3f78SToomas Soome } 1800*a1bf3f78SToomas Soome 1801*a1bf3f78SToomas Soome static void 1802*a1bf3f78SToomas Soome ficlPrimitiveUntilCoIm(ficlVm *vm) 1803*a1bf3f78SToomas Soome { 1804*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1805*a1bf3f78SToomas Soome 1806*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 1807*a1bf3f78SToomas Soome ficlInstructionBranch0ParenWithCheck); 1808*a1bf3f78SToomas Soome resolveBackBranch(dictionary, vm, destTag); 1809*a1bf3f78SToomas Soome } 1810*a1bf3f78SToomas Soome 1811*a1bf3f78SToomas Soome static void 1812*a1bf3f78SToomas Soome ficlPrimitiveWhileCoIm(ficlVm *vm) 1813*a1bf3f78SToomas Soome { 1814*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1815*a1bf3f78SToomas Soome 1816*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 5); 1817*a1bf3f78SToomas Soome 1818*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 1819*a1bf3f78SToomas Soome ficlInstructionBranch0ParenWithCheck); 1820*a1bf3f78SToomas Soome markBranch(dictionary, vm, origTag); 1821*a1bf3f78SToomas Soome 1822*a1bf3f78SToomas Soome /* equivalent to 2swap */ 1823*a1bf3f78SToomas Soome ficlStackRoll(vm->dataStack, 3); 1824*a1bf3f78SToomas Soome ficlStackRoll(vm->dataStack, 3); 1825*a1bf3f78SToomas Soome 1826*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 1); 1827*a1bf3f78SToomas Soome } 1828*a1bf3f78SToomas Soome 1829*a1bf3f78SToomas Soome static void 1830*a1bf3f78SToomas Soome ficlPrimitiveRepeatCoIm(ficlVm *vm) 1831*a1bf3f78SToomas Soome { 1832*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1833*a1bf3f78SToomas Soome 1834*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 1835*a1bf3f78SToomas Soome ficlInstructionBranchParenWithCheck); 1836*a1bf3f78SToomas Soome /* expect "begin" branch marker */ 1837*a1bf3f78SToomas Soome resolveBackBranch(dictionary, vm, destTag); 1838*a1bf3f78SToomas Soome /* expect "while" branch marker */ 1839*a1bf3f78SToomas Soome resolveForwardBranch(dictionary, vm, origTag); 1840*a1bf3f78SToomas Soome } 1841*a1bf3f78SToomas Soome 1842*a1bf3f78SToomas Soome static void 1843*a1bf3f78SToomas Soome ficlPrimitiveAgainCoIm(ficlVm *vm) 1844*a1bf3f78SToomas Soome { 1845*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 1846*a1bf3f78SToomas Soome 1847*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 1848*a1bf3f78SToomas Soome ficlInstructionBranchParenWithCheck); 1849*a1bf3f78SToomas Soome /* expect "begin" branch marker */ 1850*a1bf3f78SToomas Soome resolveBackBranch(dictionary, vm, destTag); 1851*a1bf3f78SToomas Soome } 1852*a1bf3f78SToomas Soome 1853*a1bf3f78SToomas Soome /* 1854*a1bf3f78SToomas Soome * c h a r & f r i e n d s 1855*a1bf3f78SToomas Soome * 6.1.0895 CHAR CORE ( "<spaces>name" -- char ) 1856*a1bf3f78SToomas Soome * Skip leading space delimiters. Parse name delimited by a space. 1857*a1bf3f78SToomas Soome * Put the value of its first character onto the stack. 1858*a1bf3f78SToomas Soome * 1859*a1bf3f78SToomas Soome * bracket-char CORE 1860*a1bf3f78SToomas Soome * Interpretation: Interpretation semantics for this word are undefined. 1861*a1bf3f78SToomas Soome * Compilation: ( "<spaces>name" -- ) 1862*a1bf3f78SToomas Soome * Skip leading space delimiters. Parse name delimited by a space. 1863*a1bf3f78SToomas Soome * Append the run-time semantics given below to the current definition. 1864*a1bf3f78SToomas Soome * Run-time: ( -- char ) 1865*a1bf3f78SToomas Soome * Place char, the value of the first character of name, on the stack. 1866*a1bf3f78SToomas Soome */ 1867*a1bf3f78SToomas Soome static void 1868*a1bf3f78SToomas Soome ficlPrimitiveChar(ficlVm *vm) 1869*a1bf3f78SToomas Soome { 1870*a1bf3f78SToomas Soome ficlString s; 1871*a1bf3f78SToomas Soome 1872*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 0, 1); 1873*a1bf3f78SToomas Soome 1874*a1bf3f78SToomas Soome s = ficlVmGetWord(vm); 1875*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, (ficlUnsigned)(s.text[0])); 1876*a1bf3f78SToomas Soome } 1877*a1bf3f78SToomas Soome 1878*a1bf3f78SToomas Soome static void 1879*a1bf3f78SToomas Soome ficlPrimitiveCharCoIm(ficlVm *vm) 1880*a1bf3f78SToomas Soome { 1881*a1bf3f78SToomas Soome ficlPrimitiveChar(vm); 1882*a1bf3f78SToomas Soome ficlPrimitiveLiteralIm(vm); 1883*a1bf3f78SToomas Soome } 1884*a1bf3f78SToomas Soome 1885*a1bf3f78SToomas Soome /* 1886*a1bf3f78SToomas Soome * c h a r P l u s 1887*a1bf3f78SToomas Soome * char-plus CORE ( c-addr1 -- c-addr2 ) 1888*a1bf3f78SToomas Soome * Add the size in address units of a character to c-addr1, giving c-addr2. 1889*a1bf3f78SToomas Soome */ 1890*a1bf3f78SToomas Soome static void 1891*a1bf3f78SToomas Soome ficlPrimitiveCharPlus(ficlVm *vm) 1892*a1bf3f78SToomas Soome { 1893*a1bf3f78SToomas Soome char *p; 1894*a1bf3f78SToomas Soome 1895*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 1); 1896*a1bf3f78SToomas Soome 1897*a1bf3f78SToomas Soome p = ficlStackPopPointer(vm->dataStack); 1898*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, p + 1); 1899*a1bf3f78SToomas Soome } 1900*a1bf3f78SToomas Soome 1901*a1bf3f78SToomas Soome /* 1902*a1bf3f78SToomas Soome * c h a r s 1903*a1bf3f78SToomas Soome * chars CORE ( n1 -- n2 ) 1904*a1bf3f78SToomas Soome * n2 is the size in address units of n1 characters. 1905*a1bf3f78SToomas Soome * For most processors, this function can be a no-op. To guarantee 1906*a1bf3f78SToomas Soome * portability, we'll multiply by sizeof (char). 1907*a1bf3f78SToomas Soome */ 1908*a1bf3f78SToomas Soome #if defined(_M_IX86) 1909*a1bf3f78SToomas Soome #pragma warning(disable: 4127) 1910*a1bf3f78SToomas Soome #endif 1911*a1bf3f78SToomas Soome static void 1912*a1bf3f78SToomas Soome ficlPrimitiveChars(ficlVm *vm) 1913*a1bf3f78SToomas Soome { 1914*a1bf3f78SToomas Soome if (sizeof (char) > 1) { 1915*a1bf3f78SToomas Soome ficlInteger i; 1916*a1bf3f78SToomas Soome 1917*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 1); 1918*a1bf3f78SToomas Soome 1919*a1bf3f78SToomas Soome i = ficlStackPopInteger(vm->dataStack); 1920*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, i * sizeof (char)); 1921*a1bf3f78SToomas Soome } 1922*a1bf3f78SToomas Soome /* otherwise no-op! */ 1923*a1bf3f78SToomas Soome } 1924*a1bf3f78SToomas Soome #if defined(_M_IX86) 1925*a1bf3f78SToomas Soome #pragma warning(default: 4127) 1926*a1bf3f78SToomas Soome #endif 1927*a1bf3f78SToomas Soome 1928*a1bf3f78SToomas Soome /* 1929*a1bf3f78SToomas Soome * c o u n t 1930*a1bf3f78SToomas Soome * COUNT CORE ( c-addr1 -- c-addr2 u ) 1931*a1bf3f78SToomas Soome * Return the character string specification for the counted string stored 1932*a1bf3f78SToomas Soome * at c-addr1. c-addr2 is the address of the first character after c-addr1. 1933*a1bf3f78SToomas Soome * u is the contents of the character at c-addr1, which is the length in 1934*a1bf3f78SToomas Soome * characters of the string at c-addr2. 1935*a1bf3f78SToomas Soome */ 1936*a1bf3f78SToomas Soome static void 1937*a1bf3f78SToomas Soome ficlPrimitiveCount(ficlVm *vm) 1938*a1bf3f78SToomas Soome { 1939*a1bf3f78SToomas Soome ficlCountedString *counted; 1940*a1bf3f78SToomas Soome 1941*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 2); 1942*a1bf3f78SToomas Soome 1943*a1bf3f78SToomas Soome counted = ficlStackPopPointer(vm->dataStack); 1944*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, counted->text); 1945*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, counted->length); 1946*a1bf3f78SToomas Soome } 1947*a1bf3f78SToomas Soome 1948*a1bf3f78SToomas Soome /* 1949*a1bf3f78SToomas Soome * e n v i r o n m e n t ? 1950*a1bf3f78SToomas Soome * environment-query CORE ( c-addr u -- FICL_FALSE | i*x FICL_TRUE ) 1951*a1bf3f78SToomas Soome * c-addr is the address of a character string and u is the string's 1952*a1bf3f78SToomas Soome * character count. u may have a value in the range from zero to an 1953*a1bf3f78SToomas Soome * implementation-defined maximum which shall not be less than 31. The 1954*a1bf3f78SToomas Soome * character string should contain a keyword from 3.2.6 Environmental 1955*a1bf3f78SToomas Soome * queries or the optional word sets to be checked for correspondence 1956*a1bf3f78SToomas Soome * with an attribute of the present environment. If the system treats the 1957*a1bf3f78SToomas Soome * attribute as unknown, the returned flag is FICL_FALSE; otherwise, the flag 1958*a1bf3f78SToomas Soome * is FICL_TRUE and the i*x returned is of the type specified in the table for 1959*a1bf3f78SToomas Soome * the attribute queried. 1960*a1bf3f78SToomas Soome */ 1961*a1bf3f78SToomas Soome static void 1962*a1bf3f78SToomas Soome ficlPrimitiveEnvironmentQ(ficlVm *vm) 1963*a1bf3f78SToomas Soome { 1964*a1bf3f78SToomas Soome ficlDictionary *environment; 1965*a1bf3f78SToomas Soome ficlWord *word; 1966*a1bf3f78SToomas Soome ficlString name; 1967*a1bf3f78SToomas Soome 1968*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 1); 1969*a1bf3f78SToomas Soome 1970*a1bf3f78SToomas Soome environment = vm->callback.system->environment; 1971*a1bf3f78SToomas Soome name.length = ficlStackPopUnsigned(vm->dataStack); 1972*a1bf3f78SToomas Soome name.text = ficlStackPopPointer(vm->dataStack); 1973*a1bf3f78SToomas Soome 1974*a1bf3f78SToomas Soome word = ficlDictionaryLookup(environment, name); 1975*a1bf3f78SToomas Soome 1976*a1bf3f78SToomas Soome if (word != NULL) { 1977*a1bf3f78SToomas Soome ficlVmExecuteWord(vm, word); 1978*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, FICL_TRUE); 1979*a1bf3f78SToomas Soome } else { 1980*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, FICL_FALSE); 1981*a1bf3f78SToomas Soome } 1982*a1bf3f78SToomas Soome } 1983*a1bf3f78SToomas Soome 1984*a1bf3f78SToomas Soome /* 1985*a1bf3f78SToomas Soome * e v a l u a t e 1986*a1bf3f78SToomas Soome * EVALUATE CORE ( i*x c-addr u -- j*x ) 1987*a1bf3f78SToomas Soome * Save the current input source specification. Store minus-one (-1) in 1988*a1bf3f78SToomas Soome * SOURCE-ID if it is present. Make the string described by c-addr and u 1989*a1bf3f78SToomas Soome * both the input source and input buffer, set >IN to zero, and 1990*a1bf3f78SToomas Soome * FICL_VM_STATE_INTERPRET. 1991*a1bf3f78SToomas Soome * When the parse area is empty, restore the prior input source 1992*a1bf3f78SToomas Soome * specification. Other stack effects are due to the words EVALUATEd. 1993*a1bf3f78SToomas Soome */ 1994*a1bf3f78SToomas Soome static void 1995*a1bf3f78SToomas Soome ficlPrimitiveEvaluate(ficlVm *vm) 1996*a1bf3f78SToomas Soome { 1997*a1bf3f78SToomas Soome ficlCell id; 1998*a1bf3f78SToomas Soome int result; 1999*a1bf3f78SToomas Soome ficlString string; 2000*a1bf3f78SToomas Soome 2001*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 0); 2002*a1bf3f78SToomas Soome 2003*a1bf3f78SToomas Soome FICL_STRING_SET_LENGTH(string, ficlStackPopUnsigned(vm->dataStack)); 2004*a1bf3f78SToomas Soome FICL_STRING_SET_POINTER(string, ficlStackPopPointer(vm->dataStack)); 2005*a1bf3f78SToomas Soome 2006*a1bf3f78SToomas Soome id = vm->sourceId; 2007*a1bf3f78SToomas Soome vm->sourceId.i = -1; 2008*a1bf3f78SToomas Soome result = ficlVmExecuteString(vm, string); 2009*a1bf3f78SToomas Soome vm->sourceId = id; 2010*a1bf3f78SToomas Soome if (result != FICL_VM_STATUS_OUT_OF_TEXT) 2011*a1bf3f78SToomas Soome ficlVmThrow(vm, result); 2012*a1bf3f78SToomas Soome } 2013*a1bf3f78SToomas Soome 2014*a1bf3f78SToomas Soome /* 2015*a1bf3f78SToomas Soome * s t r i n g q u o t e 2016*a1bf3f78SToomas Soome * Interpreting: get string delimited by a quote from the input stream, 2017*a1bf3f78SToomas Soome * copy to a scratch area, and put its count and address on the stack. 2018*a1bf3f78SToomas Soome * Compiling: FICL_VM_STATE_COMPILE code to push the address and count 2019*a1bf3f78SToomas Soome * of a string literal, FICL_VM_STATE_COMPILE the string from the input 2020*a1bf3f78SToomas Soome * stream, and align the dictionary pointer. 2021*a1bf3f78SToomas Soome */ 2022*a1bf3f78SToomas Soome static void 2023*a1bf3f78SToomas Soome ficlPrimitiveStringQuoteIm(ficlVm *vm) 2024*a1bf3f78SToomas Soome { 2025*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 2026*a1bf3f78SToomas Soome 2027*a1bf3f78SToomas Soome if (vm->state == FICL_VM_STATE_INTERPRET) { 2028*a1bf3f78SToomas Soome ficlCountedString *counted; 2029*a1bf3f78SToomas Soome counted = (ficlCountedString *)dictionary->here; 2030*a1bf3f78SToomas Soome ficlVmGetString(vm, counted, '\"'); 2031*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, counted->text); 2032*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, counted->length); 2033*a1bf3f78SToomas Soome } else { /* FICL_VM_STATE_COMPILE state */ 2034*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 2035*a1bf3f78SToomas Soome ficlInstructionStringLiteralParen); 2036*a1bf3f78SToomas Soome dictionary->here = FICL_POINTER_TO_CELL( 2037*a1bf3f78SToomas Soome ficlVmGetString(vm, (ficlCountedString *)dictionary->here, 2038*a1bf3f78SToomas Soome '\"')); 2039*a1bf3f78SToomas Soome ficlDictionaryAlign(dictionary); 2040*a1bf3f78SToomas Soome } 2041*a1bf3f78SToomas Soome } 2042*a1bf3f78SToomas Soome 2043*a1bf3f78SToomas Soome /* 2044*a1bf3f78SToomas Soome * t y p e 2045*a1bf3f78SToomas Soome * Pop count and char address from stack and print the designated string. 2046*a1bf3f78SToomas Soome */ 2047*a1bf3f78SToomas Soome static void 2048*a1bf3f78SToomas Soome ficlPrimitiveType(ficlVm *vm) 2049*a1bf3f78SToomas Soome { 2050*a1bf3f78SToomas Soome ficlUnsigned length; 2051*a1bf3f78SToomas Soome char *s; 2052*a1bf3f78SToomas Soome 2053*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 0); 2054*a1bf3f78SToomas Soome 2055*a1bf3f78SToomas Soome length = ficlStackPopUnsigned(vm->dataStack); 2056*a1bf3f78SToomas Soome s = ficlStackPopPointer(vm->dataStack); 2057*a1bf3f78SToomas Soome 2058*a1bf3f78SToomas Soome if ((s == NULL) || (length == 0)) 2059*a1bf3f78SToomas Soome return; 2060*a1bf3f78SToomas Soome 2061*a1bf3f78SToomas Soome /* 2062*a1bf3f78SToomas Soome * Since we don't have an output primitive for a counted string 2063*a1bf3f78SToomas Soome * (oops), make sure the string is null terminated. If not, copy 2064*a1bf3f78SToomas Soome * and terminate it. 2065*a1bf3f78SToomas Soome */ 2066*a1bf3f78SToomas Soome if (s[length] != 0) { 2067*a1bf3f78SToomas Soome char *here = (char *)ficlVmGetDictionary(vm)->here; 2068*a1bf3f78SToomas Soome if (s != here) 2069*a1bf3f78SToomas Soome strncpy(here, s, length); 2070*a1bf3f78SToomas Soome 2071*a1bf3f78SToomas Soome here[length] = '\0'; 2072*a1bf3f78SToomas Soome s = here; 2073*a1bf3f78SToomas Soome } 2074*a1bf3f78SToomas Soome 2075*a1bf3f78SToomas Soome ficlVmTextOut(vm, s); 2076*a1bf3f78SToomas Soome } 2077*a1bf3f78SToomas Soome 2078*a1bf3f78SToomas Soome /* 2079*a1bf3f78SToomas Soome * w o r d 2080*a1bf3f78SToomas Soome * word CORE ( char "<chars>ccc<char>" -- c-addr ) 2081*a1bf3f78SToomas Soome * Skip leading delimiters. Parse characters ccc delimited by char. An 2082*a1bf3f78SToomas Soome * ambiguous condition exists if the length of the parsed string is greater 2083*a1bf3f78SToomas Soome * than the implementation-defined length of a counted string. 2084*a1bf3f78SToomas Soome * 2085*a1bf3f78SToomas Soome * c-addr is the address of a transient region containing the parsed word 2086*a1bf3f78SToomas Soome * as a counted string. If the parse area was empty or contained no 2087*a1bf3f78SToomas Soome * characters other than the delimiter, the resulting string has a zero 2088*a1bf3f78SToomas Soome * length. A space, not included in the length, follows the string. A 2089*a1bf3f78SToomas Soome * program may replace characters within the string. 2090*a1bf3f78SToomas Soome * NOTE! Ficl also NULL-terminates the dest string. 2091*a1bf3f78SToomas Soome */ 2092*a1bf3f78SToomas Soome static void 2093*a1bf3f78SToomas Soome ficlPrimitiveWord(ficlVm *vm) 2094*a1bf3f78SToomas Soome { 2095*a1bf3f78SToomas Soome ficlCountedString *counted; 2096*a1bf3f78SToomas Soome char delim; 2097*a1bf3f78SToomas Soome ficlString name; 2098*a1bf3f78SToomas Soome 2099*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 1); 2100*a1bf3f78SToomas Soome 2101*a1bf3f78SToomas Soome counted = (ficlCountedString *)vm->pad; 2102*a1bf3f78SToomas Soome delim = (char)ficlStackPopInteger(vm->dataStack); 2103*a1bf3f78SToomas Soome name = ficlVmParseStringEx(vm, delim, 1); 2104*a1bf3f78SToomas Soome 2105*a1bf3f78SToomas Soome if (FICL_STRING_GET_LENGTH(name) > FICL_PAD_SIZE - 1) 2106*a1bf3f78SToomas Soome FICL_STRING_SET_LENGTH(name, FICL_PAD_SIZE - 1); 2107*a1bf3f78SToomas Soome 2108*a1bf3f78SToomas Soome counted->length = (ficlUnsigned8)FICL_STRING_GET_LENGTH(name); 2109*a1bf3f78SToomas Soome strncpy(counted->text, FICL_STRING_GET_POINTER(name), 2110*a1bf3f78SToomas Soome FICL_STRING_GET_LENGTH(name)); 2111*a1bf3f78SToomas Soome 2112*a1bf3f78SToomas Soome /* 2113*a1bf3f78SToomas Soome * store an extra space at the end of the primitive... 2114*a1bf3f78SToomas Soome * why? dunno yet. Guy Carver did it. 2115*a1bf3f78SToomas Soome */ 2116*a1bf3f78SToomas Soome counted->text[counted->length] = ' '; 2117*a1bf3f78SToomas Soome counted->text[counted->length + 1] = 0; 2118*a1bf3f78SToomas Soome 2119*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, counted); 2120*a1bf3f78SToomas Soome } 2121*a1bf3f78SToomas Soome 2122*a1bf3f78SToomas Soome /* 2123*a1bf3f78SToomas Soome * p a r s e - w o r d 2124*a1bf3f78SToomas Soome * Ficl PARSE-WORD ( <spaces>name -- c-addr u ) 2125*a1bf3f78SToomas Soome * Skip leading spaces and parse name delimited by a space. c-addr is the 2126*a1bf3f78SToomas Soome * address within the input buffer and u is the length of the selected 2127*a1bf3f78SToomas Soome * string. If the parse area is empty, the resulting string has a zero length. 2128*a1bf3f78SToomas Soome */ 2129*a1bf3f78SToomas Soome static void ficlPrimitiveParseNoCopy(ficlVm *vm) 2130*a1bf3f78SToomas Soome { 2131*a1bf3f78SToomas Soome ficlString s; 2132*a1bf3f78SToomas Soome 2133*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 0, 2); 2134*a1bf3f78SToomas Soome 2135*a1bf3f78SToomas Soome s = ficlVmGetWord0(vm); 2136*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, FICL_STRING_GET_POINTER(s)); 2137*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, FICL_STRING_GET_LENGTH(s)); 2138*a1bf3f78SToomas Soome } 2139*a1bf3f78SToomas Soome 2140*a1bf3f78SToomas Soome /* 2141*a1bf3f78SToomas Soome * p a r s e 2142*a1bf3f78SToomas Soome * CORE EXT ( char "ccc<char>" -- c-addr u ) 2143*a1bf3f78SToomas Soome * Parse ccc delimited by the delimiter char. 2144*a1bf3f78SToomas Soome * c-addr is the address (within the input buffer) and u is the length of 2145*a1bf3f78SToomas Soome * the parsed string. If the parse area was empty, the resulting string has 2146*a1bf3f78SToomas Soome * a zero length. 2147*a1bf3f78SToomas Soome * NOTE! PARSE differs from WORD: it does not skip leading delimiters. 2148*a1bf3f78SToomas Soome */ 2149*a1bf3f78SToomas Soome static void 2150*a1bf3f78SToomas Soome ficlPrimitiveParse(ficlVm *vm) 2151*a1bf3f78SToomas Soome { 2152*a1bf3f78SToomas Soome ficlString s; 2153*a1bf3f78SToomas Soome char delim; 2154*a1bf3f78SToomas Soome 2155*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 2); 2156*a1bf3f78SToomas Soome 2157*a1bf3f78SToomas Soome delim = (char)ficlStackPopInteger(vm->dataStack); 2158*a1bf3f78SToomas Soome 2159*a1bf3f78SToomas Soome s = ficlVmParseStringEx(vm, delim, 0); 2160*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, FICL_STRING_GET_POINTER(s)); 2161*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, FICL_STRING_GET_LENGTH(s)); 2162*a1bf3f78SToomas Soome } 2163*a1bf3f78SToomas Soome 2164*a1bf3f78SToomas Soome /* 2165*a1bf3f78SToomas Soome * f i n d 2166*a1bf3f78SToomas Soome * FIND CORE ( c-addr -- c-addr 0 | xt 1 | xt -1 ) 2167*a1bf3f78SToomas Soome * Find the definition named in the counted string at c-addr. If the 2168*a1bf3f78SToomas Soome * definition is not found, return c-addr and zero. If the definition is 2169*a1bf3f78SToomas Soome * found, return its execution token xt. If the definition is immediate, 2170*a1bf3f78SToomas Soome * also return one (1), otherwise also return minus-one (-1). For a given 2171*a1bf3f78SToomas Soome * string, the values returned by FIND while compiling may differ from 2172*a1bf3f78SToomas Soome * those returned while not compiling. 2173*a1bf3f78SToomas Soome */ 2174*a1bf3f78SToomas Soome static void 2175*a1bf3f78SToomas Soome do_find(ficlVm *vm, ficlString name, void *returnForFailure) 2176*a1bf3f78SToomas Soome { 2177*a1bf3f78SToomas Soome ficlWord *word; 2178*a1bf3f78SToomas Soome 2179*a1bf3f78SToomas Soome word = ficlDictionaryLookup(ficlVmGetDictionary(vm), name); 2180*a1bf3f78SToomas Soome if (word) { 2181*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, word); 2182*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, 2183*a1bf3f78SToomas Soome (ficlWordIsImmediate(word) ? 1 : -1)); 2184*a1bf3f78SToomas Soome } else { 2185*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, returnForFailure); 2186*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, 0); 2187*a1bf3f78SToomas Soome } 2188*a1bf3f78SToomas Soome } 2189*a1bf3f78SToomas Soome 2190*a1bf3f78SToomas Soome /* 2191*a1bf3f78SToomas Soome * f i n d 2192*a1bf3f78SToomas Soome * FIND CORE ( c-addr -- c-addr 0 | xt 1 | xt -1 ) 2193*a1bf3f78SToomas Soome * Find the definition named in the counted string at c-addr. If the 2194*a1bf3f78SToomas Soome * definition is not found, return c-addr and zero. If the definition is 2195*a1bf3f78SToomas Soome * found, return its execution token xt. If the definition is immediate, 2196*a1bf3f78SToomas Soome * also return one (1), otherwise also return minus-one (-1). For a given 2197*a1bf3f78SToomas Soome * string, the values returned by FIND while compiling may differ from 2198*a1bf3f78SToomas Soome * those returned while not compiling. 2199*a1bf3f78SToomas Soome */ 2200*a1bf3f78SToomas Soome static void 2201*a1bf3f78SToomas Soome ficlPrimitiveCFind(ficlVm *vm) 2202*a1bf3f78SToomas Soome { 2203*a1bf3f78SToomas Soome ficlCountedString *counted; 2204*a1bf3f78SToomas Soome ficlString name; 2205*a1bf3f78SToomas Soome 2206*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 2); 2207*a1bf3f78SToomas Soome 2208*a1bf3f78SToomas Soome counted = ficlStackPopPointer(vm->dataStack); 2209*a1bf3f78SToomas Soome FICL_STRING_SET_FROM_COUNTED_STRING(name, *counted); 2210*a1bf3f78SToomas Soome do_find(vm, name, counted); 2211*a1bf3f78SToomas Soome } 2212*a1bf3f78SToomas Soome 2213*a1bf3f78SToomas Soome /* 2214*a1bf3f78SToomas Soome * s f i n d 2215*a1bf3f78SToomas Soome * Ficl ( c-addr u -- 0 0 | xt 1 | xt -1 ) 2216*a1bf3f78SToomas Soome * Like FIND, but takes "c-addr u" for the string. 2217*a1bf3f78SToomas Soome */ 2218*a1bf3f78SToomas Soome static void 2219*a1bf3f78SToomas Soome ficlPrimitiveSFind(ficlVm *vm) 2220*a1bf3f78SToomas Soome { 2221*a1bf3f78SToomas Soome ficlString name; 2222*a1bf3f78SToomas Soome 2223*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 2); 2224*a1bf3f78SToomas Soome 2225*a1bf3f78SToomas Soome name.length = ficlStackPopInteger(vm->dataStack); 2226*a1bf3f78SToomas Soome name.text = ficlStackPopPointer(vm->dataStack); 2227*a1bf3f78SToomas Soome 2228*a1bf3f78SToomas Soome do_find(vm, name, NULL); 2229*a1bf3f78SToomas Soome } 2230*a1bf3f78SToomas Soome 2231*a1bf3f78SToomas Soome /* 2232*a1bf3f78SToomas Soome * r e c u r s e 2233*a1bf3f78SToomas Soome */ 2234*a1bf3f78SToomas Soome static void 2235*a1bf3f78SToomas Soome ficlPrimitiveRecurseCoIm(ficlVm *vm) 2236*a1bf3f78SToomas Soome { 2237*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 2238*a1bf3f78SToomas Soome ficlCell c; 2239*a1bf3f78SToomas Soome 2240*a1bf3f78SToomas Soome FICL_IGNORE(vm); 2241*a1bf3f78SToomas Soome c.p = dictionary->smudge; 2242*a1bf3f78SToomas Soome ficlDictionaryAppendCell(dictionary, c); 2243*a1bf3f78SToomas Soome } 2244*a1bf3f78SToomas Soome 2245*a1bf3f78SToomas Soome /* 2246*a1bf3f78SToomas Soome * s o u r c e 2247*a1bf3f78SToomas Soome * CORE ( -- c-addr u ) 2248*a1bf3f78SToomas Soome * c-addr is the address of, and u is the number of characters in, the 2249*a1bf3f78SToomas Soome * input buffer. 2250*a1bf3f78SToomas Soome */ 2251*a1bf3f78SToomas Soome static void 2252*a1bf3f78SToomas Soome ficlPrimitiveSource(ficlVm *vm) 2253*a1bf3f78SToomas Soome { 2254*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 0, 2); 2255*a1bf3f78SToomas Soome 2256*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, vm->tib.text); 2257*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, ficlVmGetInBufLen(vm)); 2258*a1bf3f78SToomas Soome } 2259*a1bf3f78SToomas Soome 2260*a1bf3f78SToomas Soome /* 2261*a1bf3f78SToomas Soome * v e r s i o n 2262*a1bf3f78SToomas Soome * non-standard... 2263*a1bf3f78SToomas Soome */ 2264*a1bf3f78SToomas Soome static void 2265*a1bf3f78SToomas Soome ficlPrimitiveVersion(ficlVm *vm) 2266*a1bf3f78SToomas Soome { 2267*a1bf3f78SToomas Soome ficlVmTextOut(vm, "Ficl version " FICL_VERSION "\n"); 2268*a1bf3f78SToomas Soome } 2269*a1bf3f78SToomas Soome 2270*a1bf3f78SToomas Soome /* 2271*a1bf3f78SToomas Soome * t o I n 2272*a1bf3f78SToomas Soome * to-in CORE 2273*a1bf3f78SToomas Soome */ 2274*a1bf3f78SToomas Soome static void 2275*a1bf3f78SToomas Soome ficlPrimitiveToIn(ficlVm *vm) 2276*a1bf3f78SToomas Soome { 2277*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 0, 1); 2278*a1bf3f78SToomas Soome 2279*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, &vm->tib.index); 2280*a1bf3f78SToomas Soome } 2281*a1bf3f78SToomas Soome 2282*a1bf3f78SToomas Soome /* 2283*a1bf3f78SToomas Soome * c o l o n N o N a m e 2284*a1bf3f78SToomas Soome * CORE EXT ( C: -- colon-sys ) ( S: -- xt ) 2285*a1bf3f78SToomas Soome * Create an unnamed colon definition and push its address. 2286*a1bf3f78SToomas Soome * Change state to FICL_VM_STATE_COMPILE. 2287*a1bf3f78SToomas Soome */ 2288*a1bf3f78SToomas Soome static void 2289*a1bf3f78SToomas Soome ficlPrimitiveColonNoName(ficlVm *vm) 2290*a1bf3f78SToomas Soome { 2291*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 2292*a1bf3f78SToomas Soome ficlWord *word; 2293*a1bf3f78SToomas Soome ficlString name; 2294*a1bf3f78SToomas Soome 2295*a1bf3f78SToomas Soome FICL_STRING_SET_LENGTH(name, 0); 2296*a1bf3f78SToomas Soome FICL_STRING_SET_POINTER(name, NULL); 2297*a1bf3f78SToomas Soome 2298*a1bf3f78SToomas Soome vm->state = FICL_VM_STATE_COMPILE; 2299*a1bf3f78SToomas Soome word = ficlDictionaryAppendWord(dictionary, name, 2300*a1bf3f78SToomas Soome (ficlPrimitive)ficlInstructionColonParen, 2301*a1bf3f78SToomas Soome FICL_WORD_DEFAULT | FICL_WORD_SMUDGED); 2302*a1bf3f78SToomas Soome 2303*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, word); 2304*a1bf3f78SToomas Soome markControlTag(vm, colonTag); 2305*a1bf3f78SToomas Soome } 2306*a1bf3f78SToomas Soome 2307*a1bf3f78SToomas Soome /* 2308*a1bf3f78SToomas Soome * u s e r V a r i a b l e 2309*a1bf3f78SToomas Soome * user ( u -- ) "<spaces>name" 2310*a1bf3f78SToomas Soome * Get a name from the input stream and create a user variable 2311*a1bf3f78SToomas Soome * with the name and the index supplied. The run-time effect 2312*a1bf3f78SToomas Soome * of a user variable is to push the address of the indexed ficlCell 2313*a1bf3f78SToomas Soome * in the running vm's user array. 2314*a1bf3f78SToomas Soome * 2315*a1bf3f78SToomas Soome * User variables are vm local cells. Each vm has an array of 2316*a1bf3f78SToomas Soome * FICL_USER_CELLS of them when FICL_WANT_USER is nonzero. 2317*a1bf3f78SToomas Soome * Ficl's user facility is implemented with two primitives, 2318*a1bf3f78SToomas Soome * "user" and "(user)", a variable ("nUser") (in softcore.c) that 2319*a1bf3f78SToomas Soome * holds the index of the next free user ficlCell, and a redefinition 2320*a1bf3f78SToomas Soome * (also in softcore) of "user" that defines a user word and increments 2321*a1bf3f78SToomas Soome * nUser. 2322*a1bf3f78SToomas Soome */ 2323*a1bf3f78SToomas Soome #if FICL_WANT_USER 2324*a1bf3f78SToomas Soome static void 2325*a1bf3f78SToomas Soome ficlPrimitiveUser(ficlVm *vm) 2326*a1bf3f78SToomas Soome { 2327*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 2328*a1bf3f78SToomas Soome ficlString name = ficlVmGetWord(vm); 2329*a1bf3f78SToomas Soome ficlCell c; 2330*a1bf3f78SToomas Soome 2331*a1bf3f78SToomas Soome c = ficlStackPop(vm->dataStack); 2332*a1bf3f78SToomas Soome if (c.i >= FICL_USER_CELLS) { 2333*a1bf3f78SToomas Soome ficlVmThrowError(vm, "Error - out of user space"); 2334*a1bf3f78SToomas Soome } 2335*a1bf3f78SToomas Soome 2336*a1bf3f78SToomas Soome ficlDictionaryAppendWord(dictionary, name, 2337*a1bf3f78SToomas Soome (ficlPrimitive)ficlInstructionUserParen, FICL_WORD_DEFAULT); 2338*a1bf3f78SToomas Soome ficlDictionaryAppendCell(dictionary, c); 2339*a1bf3f78SToomas Soome } 2340*a1bf3f78SToomas Soome #endif 2341*a1bf3f78SToomas Soome 2342*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 2343*a1bf3f78SToomas Soome /* 2344*a1bf3f78SToomas Soome * Each local is recorded in a private locals dictionary as a 2345*a1bf3f78SToomas Soome * word that does doLocalIm at runtime. DoLocalIm compiles code 2346*a1bf3f78SToomas Soome * into the client definition to fetch the value of the 2347*a1bf3f78SToomas Soome * corresponding local variable from the return stack. 2348*a1bf3f78SToomas Soome * The private dictionary gets initialized at the end of each block 2349*a1bf3f78SToomas Soome * that uses locals (in ; and does> for example). 2350*a1bf3f78SToomas Soome */ 2351*a1bf3f78SToomas Soome void 2352*a1bf3f78SToomas Soome ficlLocalParenIm(ficlVm *vm, int isDouble, int isFloat) 2353*a1bf3f78SToomas Soome { 2354*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 2355*a1bf3f78SToomas Soome ficlInteger nLocal = vm->runningWord->param[0].i; 2356*a1bf3f78SToomas Soome 2357*a1bf3f78SToomas Soome #if !FICL_WANT_FLOAT 2358*a1bf3f78SToomas Soome FICL_VM_ASSERT(vm, !isFloat); 2359*a1bf3f78SToomas Soome /* get rid of unused parameter warning */ 2360*a1bf3f78SToomas Soome isFloat = 0; 2361*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */ 2362*a1bf3f78SToomas Soome 2363*a1bf3f78SToomas Soome if (vm->state == FICL_VM_STATE_INTERPRET) { 2364*a1bf3f78SToomas Soome ficlStack *stack; 2365*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT 2366*a1bf3f78SToomas Soome if (isFloat) 2367*a1bf3f78SToomas Soome stack = vm->floatStack; 2368*a1bf3f78SToomas Soome else 2369*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */ 2370*a1bf3f78SToomas Soome stack = vm->dataStack; 2371*a1bf3f78SToomas Soome 2372*a1bf3f78SToomas Soome ficlStackPush(stack, vm->returnStack->frame[nLocal]); 2373*a1bf3f78SToomas Soome if (isDouble) 2374*a1bf3f78SToomas Soome ficlStackPush(stack, vm->returnStack->frame[nLocal+1]); 2375*a1bf3f78SToomas Soome } else { 2376*a1bf3f78SToomas Soome ficlInstruction instruction; 2377*a1bf3f78SToomas Soome ficlInteger appendLocalOffset; 2378*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT 2379*a1bf3f78SToomas Soome if (isFloat) { 2380*a1bf3f78SToomas Soome instruction = 2381*a1bf3f78SToomas Soome (isDouble) ? ficlInstructionGetF2LocalParen : 2382*a1bf3f78SToomas Soome ficlInstructionGetFLocalParen; 2383*a1bf3f78SToomas Soome appendLocalOffset = FICL_TRUE; 2384*a1bf3f78SToomas Soome } else 2385*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */ 2386*a1bf3f78SToomas Soome if (nLocal == 0) { 2387*a1bf3f78SToomas Soome instruction = (isDouble) ? ficlInstructionGet2Local0 : 2388*a1bf3f78SToomas Soome ficlInstructionGetLocal0; 2389*a1bf3f78SToomas Soome appendLocalOffset = FICL_FALSE; 2390*a1bf3f78SToomas Soome } else if ((nLocal == 1) && !isDouble) { 2391*a1bf3f78SToomas Soome instruction = ficlInstructionGetLocal1; 2392*a1bf3f78SToomas Soome appendLocalOffset = FICL_FALSE; 2393*a1bf3f78SToomas Soome } else { 2394*a1bf3f78SToomas Soome instruction = 2395*a1bf3f78SToomas Soome (isDouble) ? ficlInstructionGet2LocalParen : 2396*a1bf3f78SToomas Soome ficlInstructionGetLocalParen; 2397*a1bf3f78SToomas Soome appendLocalOffset = FICL_TRUE; 2398*a1bf3f78SToomas Soome } 2399*a1bf3f78SToomas Soome 2400*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, instruction); 2401*a1bf3f78SToomas Soome if (appendLocalOffset) 2402*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, nLocal); 2403*a1bf3f78SToomas Soome } 2404*a1bf3f78SToomas Soome } 2405*a1bf3f78SToomas Soome 2406*a1bf3f78SToomas Soome static void 2407*a1bf3f78SToomas Soome ficlPrimitiveDoLocalIm(ficlVm *vm) 2408*a1bf3f78SToomas Soome { 2409*a1bf3f78SToomas Soome ficlLocalParenIm(vm, 0, 0); 2410*a1bf3f78SToomas Soome } 2411*a1bf3f78SToomas Soome 2412*a1bf3f78SToomas Soome static void 2413*a1bf3f78SToomas Soome ficlPrimitiveDo2LocalIm(ficlVm *vm) 2414*a1bf3f78SToomas Soome { 2415*a1bf3f78SToomas Soome ficlLocalParenIm(vm, 1, 0); 2416*a1bf3f78SToomas Soome } 2417*a1bf3f78SToomas Soome 2418*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT 2419*a1bf3f78SToomas Soome static void 2420*a1bf3f78SToomas Soome ficlPrimitiveDoFLocalIm(ficlVm *vm) 2421*a1bf3f78SToomas Soome { 2422*a1bf3f78SToomas Soome ficlLocalParenIm(vm, 0, 1); 2423*a1bf3f78SToomas Soome } 2424*a1bf3f78SToomas Soome 2425*a1bf3f78SToomas Soome static void 2426*a1bf3f78SToomas Soome ficlPrimitiveDoF2LocalIm(ficlVm *vm) 2427*a1bf3f78SToomas Soome { 2428*a1bf3f78SToomas Soome ficlLocalParenIm(vm, 1, 1); 2429*a1bf3f78SToomas Soome } 2430*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */ 2431*a1bf3f78SToomas Soome 2432*a1bf3f78SToomas Soome /* 2433*a1bf3f78SToomas Soome * l o c a l P a r e n 2434*a1bf3f78SToomas Soome * paren-local-paren LOCAL 2435*a1bf3f78SToomas Soome * Interpretation: Interpretation semantics for this word are undefined. 2436*a1bf3f78SToomas Soome * Execution: ( c-addr u -- ) 2437*a1bf3f78SToomas Soome * When executed during compilation, (LOCAL) passes a message to the 2438*a1bf3f78SToomas Soome * system that has one of two meanings. If u is non-zero, 2439*a1bf3f78SToomas Soome * the message identifies a new local whose definition name is given by 2440*a1bf3f78SToomas Soome * the string of characters identified by c-addr u. If u is zero, 2441*a1bf3f78SToomas Soome * the message is last local and c-addr has no significance. 2442*a1bf3f78SToomas Soome * 2443*a1bf3f78SToomas Soome * The result of executing (LOCAL) during compilation of a definition is 2444*a1bf3f78SToomas Soome * to create a set of named local identifiers, each of which is 2445*a1bf3f78SToomas Soome * a definition name, that only have execution semantics within the scope 2446*a1bf3f78SToomas Soome * of that definition's source. 2447*a1bf3f78SToomas Soome * 2448*a1bf3f78SToomas Soome * local Execution: ( -- x ) 2449*a1bf3f78SToomas Soome * 2450*a1bf3f78SToomas Soome * Push the local's value, x, onto the stack. The local's value is 2451*a1bf3f78SToomas Soome * initialized as described in 13.3.3 Processing locals and may be 2452*a1bf3f78SToomas Soome * changed by preceding the local's name with TO. An ambiguous condition 2453*a1bf3f78SToomas Soome * exists when local is executed while in interpretation state. 2454*a1bf3f78SToomas Soome */ 2455*a1bf3f78SToomas Soome void 2456*a1bf3f78SToomas Soome ficlLocalParen(ficlVm *vm, int isDouble, int isFloat) 2457*a1bf3f78SToomas Soome { 2458*a1bf3f78SToomas Soome ficlDictionary *dictionary; 2459*a1bf3f78SToomas Soome ficlString name; 2460*a1bf3f78SToomas Soome 2461*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 0); 2462*a1bf3f78SToomas Soome 2463*a1bf3f78SToomas Soome dictionary = ficlVmGetDictionary(vm); 2464*a1bf3f78SToomas Soome FICL_STRING_SET_LENGTH(name, ficlStackPopUnsigned(vm->dataStack)); 2465*a1bf3f78SToomas Soome FICL_STRING_SET_POINTER(name, 2466*a1bf3f78SToomas Soome (char *)ficlStackPopPointer(vm->dataStack)); 2467*a1bf3f78SToomas Soome 2468*a1bf3f78SToomas Soome if (FICL_STRING_GET_LENGTH(name) > 0) { 2469*a1bf3f78SToomas Soome /* 2470*a1bf3f78SToomas Soome * add a local to the **locals** dictionary and 2471*a1bf3f78SToomas Soome * update localsCount 2472*a1bf3f78SToomas Soome */ 2473*a1bf3f78SToomas Soome ficlPrimitive code; 2474*a1bf3f78SToomas Soome ficlInstruction instruction; 2475*a1bf3f78SToomas Soome ficlDictionary *locals; 2476*a1bf3f78SToomas Soome 2477*a1bf3f78SToomas Soome locals = ficlSystemGetLocals(vm->callback.system); 2478*a1bf3f78SToomas Soome if (vm->callback.system->localsCount >= FICL_MAX_LOCALS) { 2479*a1bf3f78SToomas Soome ficlVmThrowError(vm, "Error: out of local space"); 2480*a1bf3f78SToomas Soome } 2481*a1bf3f78SToomas Soome 2482*a1bf3f78SToomas Soome #if !FICL_WANT_FLOAT 2483*a1bf3f78SToomas Soome FICL_VM_ASSERT(vm, !isFloat); 2484*a1bf3f78SToomas Soome /* get rid of unused parameter warning */ 2485*a1bf3f78SToomas Soome isFloat = 0; 2486*a1bf3f78SToomas Soome #else /* FICL_WANT_FLOAT */ 2487*a1bf3f78SToomas Soome if (isFloat) { 2488*a1bf3f78SToomas Soome if (isDouble) { 2489*a1bf3f78SToomas Soome code = ficlPrimitiveDoF2LocalIm; 2490*a1bf3f78SToomas Soome instruction = ficlInstructionToF2LocalParen; 2491*a1bf3f78SToomas Soome } else { 2492*a1bf3f78SToomas Soome code = ficlPrimitiveDoFLocalIm; 2493*a1bf3f78SToomas Soome instruction = ficlInstructionToFLocalParen; 2494*a1bf3f78SToomas Soome } 2495*a1bf3f78SToomas Soome } else 2496*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */ 2497*a1bf3f78SToomas Soome if (isDouble) { 2498*a1bf3f78SToomas Soome code = ficlPrimitiveDo2LocalIm; 2499*a1bf3f78SToomas Soome instruction = ficlInstructionTo2LocalParen; 2500*a1bf3f78SToomas Soome } else { 2501*a1bf3f78SToomas Soome code = ficlPrimitiveDoLocalIm; 2502*a1bf3f78SToomas Soome instruction = ficlInstructionToLocalParen; 2503*a1bf3f78SToomas Soome } 2504*a1bf3f78SToomas Soome 2505*a1bf3f78SToomas Soome ficlDictionaryAppendWord(locals, name, code, 2506*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 2507*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(locals, 2508*a1bf3f78SToomas Soome vm->callback.system->localsCount); 2509*a1bf3f78SToomas Soome 2510*a1bf3f78SToomas Soome if (vm->callback.system->localsCount == 0) { 2511*a1bf3f78SToomas Soome /* 2512*a1bf3f78SToomas Soome * FICL_VM_STATE_COMPILE code to create a local 2513*a1bf3f78SToomas Soome * stack frame 2514*a1bf3f78SToomas Soome */ 2515*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 2516*a1bf3f78SToomas Soome ficlInstructionLinkParen); 2517*a1bf3f78SToomas Soome 2518*a1bf3f78SToomas Soome /* save location in dictionary for #locals */ 2519*a1bf3f78SToomas Soome vm->callback.system->localsFixup = dictionary->here; 2520*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 2521*a1bf3f78SToomas Soome vm->callback.system->localsCount); 2522*a1bf3f78SToomas Soome } 2523*a1bf3f78SToomas Soome 2524*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, instruction); 2525*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, 2526*a1bf3f78SToomas Soome vm->callback.system->localsCount); 2527*a1bf3f78SToomas Soome 2528*a1bf3f78SToomas Soome vm->callback.system->localsCount += (isDouble) ? 2 : 1; 2529*a1bf3f78SToomas Soome } else if (vm->callback.system->localsCount > 0) { 2530*a1bf3f78SToomas Soome /* write localsCount to (link) param area in dictionary */ 2531*a1bf3f78SToomas Soome *(ficlInteger *)(vm->callback.system->localsFixup) = 2532*a1bf3f78SToomas Soome vm->callback.system->localsCount; 2533*a1bf3f78SToomas Soome } 2534*a1bf3f78SToomas Soome } 2535*a1bf3f78SToomas Soome 2536*a1bf3f78SToomas Soome static void 2537*a1bf3f78SToomas Soome ficlPrimitiveLocalParen(ficlVm *vm) 2538*a1bf3f78SToomas Soome { 2539*a1bf3f78SToomas Soome ficlLocalParen(vm, 0, 0); 2540*a1bf3f78SToomas Soome } 2541*a1bf3f78SToomas Soome 2542*a1bf3f78SToomas Soome static void 2543*a1bf3f78SToomas Soome ficlPrimitive2LocalParen(ficlVm *vm) 2544*a1bf3f78SToomas Soome { 2545*a1bf3f78SToomas Soome ficlLocalParen(vm, 1, 0); 2546*a1bf3f78SToomas Soome } 2547*a1bf3f78SToomas Soome #endif /* FICL_WANT_LOCALS */ 2548*a1bf3f78SToomas Soome 2549*a1bf3f78SToomas Soome /* 2550*a1bf3f78SToomas Soome * t o V a l u e 2551*a1bf3f78SToomas Soome * CORE EXT 2552*a1bf3f78SToomas Soome * Interpretation: ( x "<spaces>name" -- ) 2553*a1bf3f78SToomas Soome * Skip leading spaces and parse name delimited by a space. Store x in 2554*a1bf3f78SToomas Soome * name. An ambiguous condition exists if name was not defined by VALUE. 2555*a1bf3f78SToomas Soome * NOTE: In Ficl, VALUE is an alias of CONSTANT 2556*a1bf3f78SToomas Soome */ 2557*a1bf3f78SToomas Soome static void 2558*a1bf3f78SToomas Soome ficlPrimitiveToValue(ficlVm *vm) 2559*a1bf3f78SToomas Soome { 2560*a1bf3f78SToomas Soome ficlString name = ficlVmGetWord(vm); 2561*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlVmGetDictionary(vm); 2562*a1bf3f78SToomas Soome ficlWord *word; 2563*a1bf3f78SToomas Soome ficlInstruction instruction = 0; 2564*a1bf3f78SToomas Soome ficlStack *stack; 2565*a1bf3f78SToomas Soome ficlInteger isDouble; 2566*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 2567*a1bf3f78SToomas Soome ficlInteger nLocal; 2568*a1bf3f78SToomas Soome ficlInteger appendLocalOffset; 2569*a1bf3f78SToomas Soome ficlInteger isFloat; 2570*a1bf3f78SToomas Soome #endif /* FICL_WANT_LOCALS */ 2571*a1bf3f78SToomas Soome 2572*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 2573*a1bf3f78SToomas Soome if ((vm->callback.system->localsCount > 0) && 2574*a1bf3f78SToomas Soome (vm->state == FICL_VM_STATE_COMPILE)) { 2575*a1bf3f78SToomas Soome ficlDictionary *locals; 2576*a1bf3f78SToomas Soome 2577*a1bf3f78SToomas Soome locals = ficlSystemGetLocals(vm->callback.system); 2578*a1bf3f78SToomas Soome word = ficlDictionaryLookup(locals, name); 2579*a1bf3f78SToomas Soome if (!word) 2580*a1bf3f78SToomas Soome goto TO_GLOBAL; 2581*a1bf3f78SToomas Soome 2582*a1bf3f78SToomas Soome if (word->code == ficlPrimitiveDoLocalIm) { 2583*a1bf3f78SToomas Soome instruction = ficlInstructionToLocalParen; 2584*a1bf3f78SToomas Soome isDouble = isFloat = FICL_FALSE; 2585*a1bf3f78SToomas Soome } else if (word->code == ficlPrimitiveDo2LocalIm) { 2586*a1bf3f78SToomas Soome instruction = ficlInstructionTo2LocalParen; 2587*a1bf3f78SToomas Soome isDouble = FICL_TRUE; 2588*a1bf3f78SToomas Soome isFloat = FICL_FALSE; 2589*a1bf3f78SToomas Soome } 2590*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT 2591*a1bf3f78SToomas Soome else if (word->code == ficlPrimitiveDoFLocalIm) { 2592*a1bf3f78SToomas Soome instruction = ficlInstructionToFLocalParen; 2593*a1bf3f78SToomas Soome isDouble = FICL_FALSE; 2594*a1bf3f78SToomas Soome isFloat = FICL_TRUE; 2595*a1bf3f78SToomas Soome } else if (word->code == ficlPrimitiveDoF2LocalIm) { 2596*a1bf3f78SToomas Soome instruction = ficlInstructionToF2LocalParen; 2597*a1bf3f78SToomas Soome isDouble = isFloat = FICL_TRUE; 2598*a1bf3f78SToomas Soome } 2599*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */ 2600*a1bf3f78SToomas Soome else { 2601*a1bf3f78SToomas Soome ficlVmThrowError(vm, 2602*a1bf3f78SToomas Soome "to %.*s : local is of unknown type", 2603*a1bf3f78SToomas Soome FICL_STRING_GET_LENGTH(name), 2604*a1bf3f78SToomas Soome FICL_STRING_GET_POINTER(name)); 2605*a1bf3f78SToomas Soome return; 2606*a1bf3f78SToomas Soome } 2607*a1bf3f78SToomas Soome 2608*a1bf3f78SToomas Soome nLocal = word->param[0].i; 2609*a1bf3f78SToomas Soome appendLocalOffset = FICL_TRUE; 2610*a1bf3f78SToomas Soome 2611*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT 2612*a1bf3f78SToomas Soome if (!isFloat) { 2613*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */ 2614*a1bf3f78SToomas Soome if (nLocal == 0) { 2615*a1bf3f78SToomas Soome instruction = 2616*a1bf3f78SToomas Soome (isDouble) ? ficlInstructionTo2Local0 : 2617*a1bf3f78SToomas Soome ficlInstructionToLocal0; 2618*a1bf3f78SToomas Soome appendLocalOffset = FICL_FALSE; 2619*a1bf3f78SToomas Soome } else if ((nLocal == 1) && !isDouble) { 2620*a1bf3f78SToomas Soome instruction = ficlInstructionToLocal1; 2621*a1bf3f78SToomas Soome appendLocalOffset = FICL_FALSE; 2622*a1bf3f78SToomas Soome } 2623*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT 2624*a1bf3f78SToomas Soome } 2625*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */ 2626*a1bf3f78SToomas Soome 2627*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, instruction); 2628*a1bf3f78SToomas Soome if (appendLocalOffset) 2629*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, nLocal); 2630*a1bf3f78SToomas Soome return; 2631*a1bf3f78SToomas Soome } 2632*a1bf3f78SToomas Soome #endif 2633*a1bf3f78SToomas Soome 2634*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 2635*a1bf3f78SToomas Soome TO_GLOBAL: 2636*a1bf3f78SToomas Soome #endif /* FICL_WANT_LOCALS */ 2637*a1bf3f78SToomas Soome word = ficlDictionaryLookup(dictionary, name); 2638*a1bf3f78SToomas Soome if (!word) 2639*a1bf3f78SToomas Soome ficlVmThrowError(vm, "%.*s not found", 2640*a1bf3f78SToomas Soome FICL_STRING_GET_LENGTH(name), 2641*a1bf3f78SToomas Soome FICL_STRING_GET_POINTER(name)); 2642*a1bf3f78SToomas Soome 2643*a1bf3f78SToomas Soome switch ((ficlInstruction)word->code) { 2644*a1bf3f78SToomas Soome case ficlInstructionConstantParen: 2645*a1bf3f78SToomas Soome instruction = ficlInstructionStore; 2646*a1bf3f78SToomas Soome stack = vm->dataStack; 2647*a1bf3f78SToomas Soome isDouble = FICL_FALSE; 2648*a1bf3f78SToomas Soome break; 2649*a1bf3f78SToomas Soome case ficlInstruction2ConstantParen: 2650*a1bf3f78SToomas Soome instruction = ficlInstruction2Store; 2651*a1bf3f78SToomas Soome stack = vm->dataStack; 2652*a1bf3f78SToomas Soome isDouble = FICL_TRUE; 2653*a1bf3f78SToomas Soome break; 2654*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT 2655*a1bf3f78SToomas Soome case ficlInstructionFConstantParen: 2656*a1bf3f78SToomas Soome instruction = ficlInstructionFStore; 2657*a1bf3f78SToomas Soome stack = vm->floatStack; 2658*a1bf3f78SToomas Soome isDouble = FICL_FALSE; 2659*a1bf3f78SToomas Soome break; 2660*a1bf3f78SToomas Soome case ficlInstructionF2ConstantParen: 2661*a1bf3f78SToomas Soome instruction = ficlInstructionF2Store; 2662*a1bf3f78SToomas Soome stack = vm->floatStack; 2663*a1bf3f78SToomas Soome isDouble = FICL_TRUE; 2664*a1bf3f78SToomas Soome break; 2665*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */ 2666*a1bf3f78SToomas Soome default: 2667*a1bf3f78SToomas Soome ficlVmThrowError(vm, 2668*a1bf3f78SToomas Soome "to %.*s : value/constant is of unknown type", 2669*a1bf3f78SToomas Soome FICL_STRING_GET_LENGTH(name), 2670*a1bf3f78SToomas Soome FICL_STRING_GET_POINTER(name)); 2671*a1bf3f78SToomas Soome return; 2672*a1bf3f78SToomas Soome } 2673*a1bf3f78SToomas Soome 2674*a1bf3f78SToomas Soome if (vm->state == FICL_VM_STATE_INTERPRET) { 2675*a1bf3f78SToomas Soome word->param[0] = ficlStackPop(stack); 2676*a1bf3f78SToomas Soome if (isDouble) 2677*a1bf3f78SToomas Soome word->param[1] = ficlStackPop(stack); 2678*a1bf3f78SToomas Soome } else { 2679*a1bf3f78SToomas Soome /* FICL_VM_STATE_COMPILE code to store to word's param */ 2680*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, &word->param[0]); 2681*a1bf3f78SToomas Soome ficlPrimitiveLiteralIm(vm); 2682*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(dictionary, instruction); 2683*a1bf3f78SToomas Soome } 2684*a1bf3f78SToomas Soome } 2685*a1bf3f78SToomas Soome 2686*a1bf3f78SToomas Soome /* 2687*a1bf3f78SToomas Soome * f m S l a s h M o d 2688*a1bf3f78SToomas Soome * f-m-slash-mod CORE ( d1 n1 -- n2 n3 ) 2689*a1bf3f78SToomas Soome * Divide d1 by n1, giving the floored quotient n3 and the remainder n2. 2690*a1bf3f78SToomas Soome * Input and output stack arguments are signed. An ambiguous condition 2691*a1bf3f78SToomas Soome * exists if n1 is zero or if the quotient lies outside the range of a 2692*a1bf3f78SToomas Soome * single-ficlCell signed integer. 2693*a1bf3f78SToomas Soome */ 2694*a1bf3f78SToomas Soome static void 2695*a1bf3f78SToomas Soome ficlPrimitiveFMSlashMod(ficlVm *vm) 2696*a1bf3f78SToomas Soome { 2697*a1bf3f78SToomas Soome ficl2Integer d1; 2698*a1bf3f78SToomas Soome ficlInteger n1; 2699*a1bf3f78SToomas Soome ficl2IntegerQR qr; 2700*a1bf3f78SToomas Soome 2701*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 3, 2); 2702*a1bf3f78SToomas Soome 2703*a1bf3f78SToomas Soome n1 = ficlStackPopInteger(vm->dataStack); 2704*a1bf3f78SToomas Soome d1 = ficlStackPop2Integer(vm->dataStack); 2705*a1bf3f78SToomas Soome qr = ficl2IntegerDivideFloored(d1, n1); 2706*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, qr.remainder); 2707*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, 2708*a1bf3f78SToomas Soome FICL_2UNSIGNED_GET_LOW(qr.quotient)); 2709*a1bf3f78SToomas Soome } 2710*a1bf3f78SToomas Soome 2711*a1bf3f78SToomas Soome /* 2712*a1bf3f78SToomas Soome * s m S l a s h R e m 2713*a1bf3f78SToomas Soome * s-m-slash-remainder CORE ( d1 n1 -- n2 n3 ) 2714*a1bf3f78SToomas Soome * Divide d1 by n1, giving the symmetric quotient n3 and the remainder n2. 2715*a1bf3f78SToomas Soome * Input and output stack arguments are signed. An ambiguous condition 2716*a1bf3f78SToomas Soome * exists if n1 is zero or if the quotient lies outside the range of a 2717*a1bf3f78SToomas Soome * single-ficlCell signed integer. 2718*a1bf3f78SToomas Soome */ 2719*a1bf3f78SToomas Soome static void 2720*a1bf3f78SToomas Soome ficlPrimitiveSMSlashRem(ficlVm *vm) 2721*a1bf3f78SToomas Soome { 2722*a1bf3f78SToomas Soome ficl2Integer d1; 2723*a1bf3f78SToomas Soome ficlInteger n1; 2724*a1bf3f78SToomas Soome ficl2IntegerQR qr; 2725*a1bf3f78SToomas Soome 2726*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 3, 2); 2727*a1bf3f78SToomas Soome 2728*a1bf3f78SToomas Soome n1 = ficlStackPopInteger(vm->dataStack); 2729*a1bf3f78SToomas Soome d1 = ficlStackPop2Integer(vm->dataStack); 2730*a1bf3f78SToomas Soome qr = ficl2IntegerDivideSymmetric(d1, n1); 2731*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, qr.remainder); 2732*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, 2733*a1bf3f78SToomas Soome FICL_2UNSIGNED_GET_LOW(qr.quotient)); 2734*a1bf3f78SToomas Soome } 2735*a1bf3f78SToomas Soome 2736*a1bf3f78SToomas Soome static void 2737*a1bf3f78SToomas Soome ficlPrimitiveMod(ficlVm *vm) 2738*a1bf3f78SToomas Soome { 2739*a1bf3f78SToomas Soome ficl2Integer d1; 2740*a1bf3f78SToomas Soome ficlInteger n1; 2741*a1bf3f78SToomas Soome ficlInteger i; 2742*a1bf3f78SToomas Soome ficl2IntegerQR qr; 2743*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 1); 2744*a1bf3f78SToomas Soome 2745*a1bf3f78SToomas Soome n1 = ficlStackPopInteger(vm->dataStack); 2746*a1bf3f78SToomas Soome i = ficlStackPopInteger(vm->dataStack); 2747*a1bf3f78SToomas Soome FICL_INTEGER_TO_2INTEGER(i, d1); 2748*a1bf3f78SToomas Soome qr = ficl2IntegerDivideSymmetric(d1, n1); 2749*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, qr.remainder); 2750*a1bf3f78SToomas Soome } 2751*a1bf3f78SToomas Soome 2752*a1bf3f78SToomas Soome /* 2753*a1bf3f78SToomas Soome * u m S l a s h M o d 2754*a1bf3f78SToomas Soome * u-m-slash-mod CORE ( ud u1 -- u2 u3 ) 2755*a1bf3f78SToomas Soome * Divide ud by u1, giving the quotient u3 and the remainder u2. 2756*a1bf3f78SToomas Soome * All values and arithmetic are unsigned. An ambiguous condition 2757*a1bf3f78SToomas Soome * exists if u1 is zero or if the quotient lies outside the range of a 2758*a1bf3f78SToomas Soome * single-ficlCell unsigned integer. 2759*a1bf3f78SToomas Soome */ 2760*a1bf3f78SToomas Soome static void 2761*a1bf3f78SToomas Soome ficlPrimitiveUMSlashMod(ficlVm *vm) 2762*a1bf3f78SToomas Soome { 2763*a1bf3f78SToomas Soome ficl2Unsigned ud; 2764*a1bf3f78SToomas Soome ficlUnsigned u1; 2765*a1bf3f78SToomas Soome ficl2UnsignedQR uqr; 2766*a1bf3f78SToomas Soome 2767*a1bf3f78SToomas Soome u1 = ficlStackPopUnsigned(vm->dataStack); 2768*a1bf3f78SToomas Soome ud = ficlStackPop2Unsigned(vm->dataStack); 2769*a1bf3f78SToomas Soome uqr = ficl2UnsignedDivide(ud, u1); 2770*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, uqr.remainder); 2771*a1bf3f78SToomas Soome ficlStackPushUnsigned(vm->dataStack, 2772*a1bf3f78SToomas Soome FICL_2UNSIGNED_GET_LOW(uqr.quotient)); 2773*a1bf3f78SToomas Soome } 2774*a1bf3f78SToomas Soome 2775*a1bf3f78SToomas Soome /* 2776*a1bf3f78SToomas Soome * m S t a r 2777*a1bf3f78SToomas Soome * m-star CORE ( n1 n2 -- d ) 2778*a1bf3f78SToomas Soome * d is the signed product of n1 times n2. 2779*a1bf3f78SToomas Soome */ 2780*a1bf3f78SToomas Soome static void 2781*a1bf3f78SToomas Soome ficlPrimitiveMStar(ficlVm *vm) 2782*a1bf3f78SToomas Soome { 2783*a1bf3f78SToomas Soome ficlInteger n2; 2784*a1bf3f78SToomas Soome ficlInteger n1; 2785*a1bf3f78SToomas Soome ficl2Integer d; 2786*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 2); 2787*a1bf3f78SToomas Soome 2788*a1bf3f78SToomas Soome n2 = ficlStackPopInteger(vm->dataStack); 2789*a1bf3f78SToomas Soome n1 = ficlStackPopInteger(vm->dataStack); 2790*a1bf3f78SToomas Soome 2791*a1bf3f78SToomas Soome d = ficl2IntegerMultiply(n1, n2); 2792*a1bf3f78SToomas Soome ficlStackPush2Integer(vm->dataStack, d); 2793*a1bf3f78SToomas Soome } 2794*a1bf3f78SToomas Soome 2795*a1bf3f78SToomas Soome static void 2796*a1bf3f78SToomas Soome ficlPrimitiveUMStar(ficlVm *vm) 2797*a1bf3f78SToomas Soome { 2798*a1bf3f78SToomas Soome ficlUnsigned u2; 2799*a1bf3f78SToomas Soome ficlUnsigned u1; 2800*a1bf3f78SToomas Soome ficl2Unsigned ud; 2801*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 2, 2); 2802*a1bf3f78SToomas Soome 2803*a1bf3f78SToomas Soome u2 = ficlStackPopUnsigned(vm->dataStack); 2804*a1bf3f78SToomas Soome u1 = ficlStackPopUnsigned(vm->dataStack); 2805*a1bf3f78SToomas Soome 2806*a1bf3f78SToomas Soome ud = ficl2UnsignedMultiply(u1, u2); 2807*a1bf3f78SToomas Soome ficlStackPush2Unsigned(vm->dataStack, ud); 2808*a1bf3f78SToomas Soome } 2809*a1bf3f78SToomas Soome 2810*a1bf3f78SToomas Soome /* 2811*a1bf3f78SToomas Soome * 2 r o t 2812*a1bf3f78SToomas Soome * DOUBLE ( d1 d2 d3 -- d2 d3 d1 ) 2813*a1bf3f78SToomas Soome */ 2814*a1bf3f78SToomas Soome static void 2815*a1bf3f78SToomas Soome ficlPrimitive2Rot(ficlVm *vm) 2816*a1bf3f78SToomas Soome { 2817*a1bf3f78SToomas Soome ficl2Integer d1, d2, d3; 2818*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 6, 6); 2819*a1bf3f78SToomas Soome 2820*a1bf3f78SToomas Soome d3 = ficlStackPop2Integer(vm->dataStack); 2821*a1bf3f78SToomas Soome d2 = ficlStackPop2Integer(vm->dataStack); 2822*a1bf3f78SToomas Soome d1 = ficlStackPop2Integer(vm->dataStack); 2823*a1bf3f78SToomas Soome ficlStackPush2Integer(vm->dataStack, d2); 2824*a1bf3f78SToomas Soome ficlStackPush2Integer(vm->dataStack, d3); 2825*a1bf3f78SToomas Soome ficlStackPush2Integer(vm->dataStack, d1); 2826*a1bf3f78SToomas Soome } 2827*a1bf3f78SToomas Soome 2828*a1bf3f78SToomas Soome /* 2829*a1bf3f78SToomas Soome * p a d 2830*a1bf3f78SToomas Soome * CORE EXT ( -- c-addr ) 2831*a1bf3f78SToomas Soome * c-addr is the address of a transient region that can be used to hold 2832*a1bf3f78SToomas Soome * data for intermediate processing. 2833*a1bf3f78SToomas Soome */ 2834*a1bf3f78SToomas Soome static void 2835*a1bf3f78SToomas Soome ficlPrimitivePad(ficlVm *vm) 2836*a1bf3f78SToomas Soome { 2837*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, vm->pad); 2838*a1bf3f78SToomas Soome } 2839*a1bf3f78SToomas Soome 2840*a1bf3f78SToomas Soome /* 2841*a1bf3f78SToomas Soome * s o u r c e - i d 2842*a1bf3f78SToomas Soome * CORE EXT, FILE ( -- 0 | -1 | fileid ) 2843*a1bf3f78SToomas Soome * Identifies the input source as follows: 2844*a1bf3f78SToomas Soome * 2845*a1bf3f78SToomas Soome * SOURCE-ID Input source 2846*a1bf3f78SToomas Soome * --------- ------------ 2847*a1bf3f78SToomas Soome * fileid Text file fileid 2848*a1bf3f78SToomas Soome * -1 String (via EVALUATE) 2849*a1bf3f78SToomas Soome * 0 User input device 2850*a1bf3f78SToomas Soome */ 2851*a1bf3f78SToomas Soome static void 2852*a1bf3f78SToomas Soome ficlPrimitiveSourceID(ficlVm *vm) 2853*a1bf3f78SToomas Soome { 2854*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, vm->sourceId.i); 2855*a1bf3f78SToomas Soome } 2856*a1bf3f78SToomas Soome 2857*a1bf3f78SToomas Soome /* 2858*a1bf3f78SToomas Soome * r e f i l l 2859*a1bf3f78SToomas Soome * CORE EXT ( -- flag ) 2860*a1bf3f78SToomas Soome * Attempt to fill the input buffer from the input source, returning 2861*a1bf3f78SToomas Soome * a FICL_TRUE flag if successful. 2862*a1bf3f78SToomas Soome * When the input source is the user input device, attempt to receive input 2863*a1bf3f78SToomas Soome * into the terminal input buffer. If successful, make the result the input 2864*a1bf3f78SToomas Soome * buffer, set >IN to zero, and return FICL_TRUE. Receipt of a line containing 2865*a1bf3f78SToomas Soome * no characters is considered successful. If there is no input available from 2866*a1bf3f78SToomas Soome * the current input source, return FICL_FALSE. 2867*a1bf3f78SToomas Soome * When the input source is a string from EVALUATE, return FICL_FALSE and 2868*a1bf3f78SToomas Soome * perform no other action. 2869*a1bf3f78SToomas Soome */ 2870*a1bf3f78SToomas Soome static void 2871*a1bf3f78SToomas Soome ficlPrimitiveRefill(ficlVm *vm) 2872*a1bf3f78SToomas Soome { 2873*a1bf3f78SToomas Soome ficlInteger ret = (vm->sourceId.i == -1) ? FICL_FALSE : FICL_TRUE; 2874*a1bf3f78SToomas Soome if (ret && (vm->restart == 0)) 2875*a1bf3f78SToomas Soome ficlVmThrow(vm, FICL_VM_STATUS_RESTART); 2876*a1bf3f78SToomas Soome 2877*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, ret); 2878*a1bf3f78SToomas Soome } 2879*a1bf3f78SToomas Soome 2880*a1bf3f78SToomas Soome /* 2881*a1bf3f78SToomas Soome * freebsd exception handling words 2882*a1bf3f78SToomas Soome * Catch, from ANS Forth standard. Installs a safety net, then EXECUTE 2883*a1bf3f78SToomas Soome * the word in ToS. If an exception happens, restore the state to what 2884*a1bf3f78SToomas Soome * it was before, and pushes the exception value on the stack. If not, 2885*a1bf3f78SToomas Soome * push zero. 2886*a1bf3f78SToomas Soome * 2887*a1bf3f78SToomas Soome * Notice that Catch implements an inner interpreter. This is ugly, 2888*a1bf3f78SToomas Soome * but given how Ficl works, it cannot be helped. The problem is that 2889*a1bf3f78SToomas Soome * colon definitions will be executed *after* the function returns, 2890*a1bf3f78SToomas Soome * while "code" definitions will be executed immediately. I considered 2891*a1bf3f78SToomas Soome * other solutions to this problem, but all of them shared the same 2892*a1bf3f78SToomas Soome * basic problem (with added disadvantages): if Ficl ever changes it's 2893*a1bf3f78SToomas Soome * inner thread modus operandi, one would have to fix this word. 2894*a1bf3f78SToomas Soome * 2895*a1bf3f78SToomas Soome * More comments can be found throughout catch's code. 2896*a1bf3f78SToomas Soome * 2897*a1bf3f78SToomas Soome * Daniel C. Sobral Jan 09/1999 2898*a1bf3f78SToomas Soome * sadler may 2000 -- revised to follow ficl.c:ficlExecXT. 2899*a1bf3f78SToomas Soome */ 2900*a1bf3f78SToomas Soome static void 2901*a1bf3f78SToomas Soome ficlPrimitiveCatch(ficlVm *vm) 2902*a1bf3f78SToomas Soome { 2903*a1bf3f78SToomas Soome int except; 2904*a1bf3f78SToomas Soome jmp_buf vmState; 2905*a1bf3f78SToomas Soome ficlVm vmCopy; 2906*a1bf3f78SToomas Soome ficlStack dataStackCopy; 2907*a1bf3f78SToomas Soome ficlStack returnStackCopy; 2908*a1bf3f78SToomas Soome ficlWord *word; 2909*a1bf3f78SToomas Soome 2910*a1bf3f78SToomas Soome FICL_VM_ASSERT(vm, vm); 2911*a1bf3f78SToomas Soome FICL_VM_ASSERT(vm, vm->callback.system->exitInnerWord); 2912*a1bf3f78SToomas Soome 2913*a1bf3f78SToomas Soome /* 2914*a1bf3f78SToomas Soome * Get xt. 2915*a1bf3f78SToomas Soome * We need this *before* we save the stack pointer, or 2916*a1bf3f78SToomas Soome * we'll have to pop one element out of the stack after 2917*a1bf3f78SToomas Soome * an exception. I prefer to get done with it up front. :-) 2918*a1bf3f78SToomas Soome */ 2919*a1bf3f78SToomas Soome 2920*a1bf3f78SToomas Soome FICL_STACK_CHECK(vm->dataStack, 1, 0); 2921*a1bf3f78SToomas Soome 2922*a1bf3f78SToomas Soome word = ficlStackPopPointer(vm->dataStack); 2923*a1bf3f78SToomas Soome 2924*a1bf3f78SToomas Soome /* 2925*a1bf3f78SToomas Soome * Save vm's state -- a catch will not back out environmental 2926*a1bf3f78SToomas Soome * changes. 2927*a1bf3f78SToomas Soome * 2928*a1bf3f78SToomas Soome * We are *not* saving dictionary state, since it is 2929*a1bf3f78SToomas Soome * global instead of per vm, and we are not saving 2930*a1bf3f78SToomas Soome * stack contents, since we are not required to (and, 2931*a1bf3f78SToomas Soome * thus, it would be useless). We save vm, and vm 2932*a1bf3f78SToomas Soome * "stacks" (a structure containing general information 2933*a1bf3f78SToomas Soome * about it, including the current stack pointer). 2934*a1bf3f78SToomas Soome */ 2935*a1bf3f78SToomas Soome memcpy((void*)&vmCopy, (void*)vm, sizeof (ficlVm)); 2936*a1bf3f78SToomas Soome memcpy((void*)&dataStackCopy, (void*)vm->dataStack, sizeof (ficlStack)); 2937*a1bf3f78SToomas Soome memcpy((void*)&returnStackCopy, (void*)vm->returnStack, 2938*a1bf3f78SToomas Soome sizeof (ficlStack)); 2939*a1bf3f78SToomas Soome 2940*a1bf3f78SToomas Soome /* 2941*a1bf3f78SToomas Soome * Give vm a jmp_buf 2942*a1bf3f78SToomas Soome */ 2943*a1bf3f78SToomas Soome vm->exceptionHandler = &vmState; 2944*a1bf3f78SToomas Soome 2945*a1bf3f78SToomas Soome /* 2946*a1bf3f78SToomas Soome * Safety net 2947*a1bf3f78SToomas Soome */ 2948*a1bf3f78SToomas Soome except = setjmp(vmState); 2949*a1bf3f78SToomas Soome 2950*a1bf3f78SToomas Soome switch (except) { 2951*a1bf3f78SToomas Soome /* 2952*a1bf3f78SToomas Soome * Setup condition - push poison pill so that the VM throws 2953*a1bf3f78SToomas Soome * VM_INNEREXIT if the XT terminates normally, then execute 2954*a1bf3f78SToomas Soome * the XT 2955*a1bf3f78SToomas Soome */ 2956*a1bf3f78SToomas Soome case 0: 2957*a1bf3f78SToomas Soome /* Open mouth, insert emetic */ 2958*a1bf3f78SToomas Soome ficlVmPushIP(vm, &(vm->callback.system->exitInnerWord)); 2959*a1bf3f78SToomas Soome ficlVmExecuteWord(vm, word); 2960*a1bf3f78SToomas Soome ficlVmInnerLoop(vm, 0); 2961*a1bf3f78SToomas Soome break; 2962*a1bf3f78SToomas Soome 2963*a1bf3f78SToomas Soome /* 2964*a1bf3f78SToomas Soome * Normal exit from XT - lose the poison pill, 2965*a1bf3f78SToomas Soome * restore old setjmp vector and push a zero. 2966*a1bf3f78SToomas Soome */ 2967*a1bf3f78SToomas Soome case FICL_VM_STATUS_INNER_EXIT: 2968*a1bf3f78SToomas Soome ficlVmPopIP(vm); /* Gack - hurl poison pill */ 2969*a1bf3f78SToomas Soome /* Restore just the setjmp vector */ 2970*a1bf3f78SToomas Soome vm->exceptionHandler = vmCopy.exceptionHandler; 2971*a1bf3f78SToomas Soome /* Push 0 -- everything is ok */ 2972*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, 0); 2973*a1bf3f78SToomas Soome break; 2974*a1bf3f78SToomas Soome 2975*a1bf3f78SToomas Soome /* 2976*a1bf3f78SToomas Soome * Some other exception got thrown - restore pre-existing VM state 2977*a1bf3f78SToomas Soome * and push the exception code 2978*a1bf3f78SToomas Soome */ 2979*a1bf3f78SToomas Soome default: 2980*a1bf3f78SToomas Soome /* Restore vm's state */ 2981*a1bf3f78SToomas Soome memcpy((void*)vm, (void*)&vmCopy, sizeof (ficlVm)); 2982*a1bf3f78SToomas Soome memcpy((void*)vm->dataStack, (void*)&dataStackCopy, 2983*a1bf3f78SToomas Soome sizeof (ficlStack)); 2984*a1bf3f78SToomas Soome memcpy((void*)vm->returnStack, (void*)&returnStackCopy, 2985*a1bf3f78SToomas Soome sizeof (ficlStack)); 2986*a1bf3f78SToomas Soome 2987*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, except); /* Push error */ 2988*a1bf3f78SToomas Soome break; 2989*a1bf3f78SToomas Soome } 2990*a1bf3f78SToomas Soome } 2991*a1bf3f78SToomas Soome 2992*a1bf3f78SToomas Soome /* 2993*a1bf3f78SToomas Soome * t h r o w 2994*a1bf3f78SToomas Soome * EXCEPTION 2995*a1bf3f78SToomas Soome * Throw -- From ANS Forth standard. 2996*a1bf3f78SToomas Soome * 2997*a1bf3f78SToomas Soome * Throw takes the ToS and, if that's different from zero, 2998*a1bf3f78SToomas Soome * returns to the last executed catch context. Further throws will 2999*a1bf3f78SToomas Soome * unstack previously executed "catches", in LIFO mode. 3000*a1bf3f78SToomas Soome * 3001*a1bf3f78SToomas Soome * Daniel C. Sobral Jan 09/1999 3002*a1bf3f78SToomas Soome */ 3003*a1bf3f78SToomas Soome static void 3004*a1bf3f78SToomas Soome ficlPrimitiveThrow(ficlVm *vm) 3005*a1bf3f78SToomas Soome { 3006*a1bf3f78SToomas Soome int except; 3007*a1bf3f78SToomas Soome 3008*a1bf3f78SToomas Soome except = ficlStackPopInteger(vm->dataStack); 3009*a1bf3f78SToomas Soome 3010*a1bf3f78SToomas Soome if (except) 3011*a1bf3f78SToomas Soome ficlVmThrow(vm, except); 3012*a1bf3f78SToomas Soome } 3013*a1bf3f78SToomas Soome 3014*a1bf3f78SToomas Soome /* 3015*a1bf3f78SToomas Soome * a l l o c a t e 3016*a1bf3f78SToomas Soome * MEMORY 3017*a1bf3f78SToomas Soome */ 3018*a1bf3f78SToomas Soome static void 3019*a1bf3f78SToomas Soome ficlPrimitiveAllocate(ficlVm *vm) 3020*a1bf3f78SToomas Soome { 3021*a1bf3f78SToomas Soome size_t size; 3022*a1bf3f78SToomas Soome void *p; 3023*a1bf3f78SToomas Soome 3024*a1bf3f78SToomas Soome size = ficlStackPopInteger(vm->dataStack); 3025*a1bf3f78SToomas Soome p = ficlMalloc(size); 3026*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, p); 3027*a1bf3f78SToomas Soome if (p != NULL) 3028*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, 0); 3029*a1bf3f78SToomas Soome else 3030*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, 1); 3031*a1bf3f78SToomas Soome } 3032*a1bf3f78SToomas Soome 3033*a1bf3f78SToomas Soome /* 3034*a1bf3f78SToomas Soome * f r e e 3035*a1bf3f78SToomas Soome * MEMORY 3036*a1bf3f78SToomas Soome */ 3037*a1bf3f78SToomas Soome static void 3038*a1bf3f78SToomas Soome ficlPrimitiveFree(ficlVm *vm) 3039*a1bf3f78SToomas Soome { 3040*a1bf3f78SToomas Soome void *p; 3041*a1bf3f78SToomas Soome 3042*a1bf3f78SToomas Soome p = ficlStackPopPointer(vm->dataStack); 3043*a1bf3f78SToomas Soome ficlFree(p); 3044*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, 0); 3045*a1bf3f78SToomas Soome } 3046*a1bf3f78SToomas Soome 3047*a1bf3f78SToomas Soome /* 3048*a1bf3f78SToomas Soome * r e s i z e 3049*a1bf3f78SToomas Soome * MEMORY 3050*a1bf3f78SToomas Soome */ 3051*a1bf3f78SToomas Soome static void 3052*a1bf3f78SToomas Soome ficlPrimitiveResize(ficlVm *vm) 3053*a1bf3f78SToomas Soome { 3054*a1bf3f78SToomas Soome size_t size; 3055*a1bf3f78SToomas Soome void *new, *old; 3056*a1bf3f78SToomas Soome 3057*a1bf3f78SToomas Soome size = ficlStackPopInteger(vm->dataStack); 3058*a1bf3f78SToomas Soome old = ficlStackPopPointer(vm->dataStack); 3059*a1bf3f78SToomas Soome new = ficlRealloc(old, size); 3060*a1bf3f78SToomas Soome 3061*a1bf3f78SToomas Soome if (new) { 3062*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, new); 3063*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, 0); 3064*a1bf3f78SToomas Soome } else { 3065*a1bf3f78SToomas Soome ficlStackPushPointer(vm->dataStack, old); 3066*a1bf3f78SToomas Soome ficlStackPushInteger(vm->dataStack, 1); 3067*a1bf3f78SToomas Soome } 3068*a1bf3f78SToomas Soome } 3069*a1bf3f78SToomas Soome 3070*a1bf3f78SToomas Soome /* 3071*a1bf3f78SToomas Soome * e x i t - i n n e r 3072*a1bf3f78SToomas Soome * Signals execXT that an inner loop has completed 3073*a1bf3f78SToomas Soome */ 3074*a1bf3f78SToomas Soome static void 3075*a1bf3f78SToomas Soome ficlPrimitiveExitInner(ficlVm *vm) 3076*a1bf3f78SToomas Soome { 3077*a1bf3f78SToomas Soome ficlVmThrow(vm, FICL_VM_STATUS_INNER_EXIT); 3078*a1bf3f78SToomas Soome } 3079*a1bf3f78SToomas Soome 3080*a1bf3f78SToomas Soome #if 0 3081*a1bf3f78SToomas Soome static void 3082*a1bf3f78SToomas Soome ficlPrimitiveName(ficlVm *vm) 3083*a1bf3f78SToomas Soome { 3084*a1bf3f78SToomas Soome FICL_IGNORE(vm); 3085*a1bf3f78SToomas Soome } 3086*a1bf3f78SToomas Soome #endif 3087*a1bf3f78SToomas Soome 3088*a1bf3f78SToomas Soome /* 3089*a1bf3f78SToomas Soome * f i c l C o m p i l e C o r e 3090*a1bf3f78SToomas Soome * Builds the primitive wordset and the environment-query namespace. 3091*a1bf3f78SToomas Soome */ 3092*a1bf3f78SToomas Soome void 3093*a1bf3f78SToomas Soome ficlSystemCompileCore(ficlSystem *system) 3094*a1bf3f78SToomas Soome { 3095*a1bf3f78SToomas Soome ficlWord *interpret; 3096*a1bf3f78SToomas Soome ficlDictionary *dictionary = ficlSystemGetDictionary(system); 3097*a1bf3f78SToomas Soome ficlDictionary *environment = ficlSystemGetEnvironment(system); 3098*a1bf3f78SToomas Soome 3099*a1bf3f78SToomas Soome FICL_SYSTEM_ASSERT(system, dictionary); 3100*a1bf3f78SToomas Soome FICL_SYSTEM_ASSERT(system, environment); 3101*a1bf3f78SToomas Soome 3102*a1bf3f78SToomas Soome #define FICL_TOKEN(token, description) 3103*a1bf3f78SToomas Soome #define FICL_INSTRUCTION_TOKEN(token, description, flags) \ 3104*a1bf3f78SToomas Soome ficlDictionarySetInstruction(dictionary, description, token, flags); 3105*a1bf3f78SToomas Soome #include "ficltokens.h" 3106*a1bf3f78SToomas Soome #undef FICL_TOKEN 3107*a1bf3f78SToomas Soome #undef FICL_INSTRUCTION_TOKEN 3108*a1bf3f78SToomas Soome 3109*a1bf3f78SToomas Soome /* 3110*a1bf3f78SToomas Soome * The Core word set 3111*a1bf3f78SToomas Soome * see softcore.c for definitions of: abs bl space spaces abort" 3112*a1bf3f78SToomas Soome */ 3113*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "#", ficlPrimitiveNumberSign, 3114*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3115*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "#>", 3116*a1bf3f78SToomas Soome ficlPrimitiveNumberSignGreater, FICL_WORD_DEFAULT); 3117*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "#s", ficlPrimitiveNumberSignS, 3118*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3119*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "\'", ficlPrimitiveTick, 3120*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3121*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "(", ficlPrimitiveParenthesis, 3122*a1bf3f78SToomas Soome FICL_WORD_IMMEDIATE); 3123*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "+loop", 3124*a1bf3f78SToomas Soome ficlPrimitivePlusLoopCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3125*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, ".", ficlPrimitiveDot, 3126*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3127*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, ".\"", 3128*a1bf3f78SToomas Soome ficlPrimitiveDotQuoteCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3129*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, ":", ficlPrimitiveColon, 3130*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3131*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, ";", ficlPrimitiveSemicolonCoIm, 3132*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3133*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "<#", 3134*a1bf3f78SToomas Soome ficlPrimitiveLessNumberSign, FICL_WORD_DEFAULT); 3135*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, ">body", ficlPrimitiveToBody, 3136*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3137*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, ">in", ficlPrimitiveToIn, 3138*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3139*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, ">number", ficlPrimitiveToNumber, 3140*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3141*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "abort", ficlPrimitiveAbort, 3142*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3143*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "accept", ficlPrimitiveAccept, 3144*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3145*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "align", ficlPrimitiveAlign, 3146*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3147*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "aligned", ficlPrimitiveAligned, 3148*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3149*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "allot", ficlPrimitiveAllot, 3150*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3151*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "base", ficlPrimitiveBase, 3152*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3153*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "begin", ficlPrimitiveBeginCoIm, 3154*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3155*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "case", ficlPrimitiveCaseCoIm, 3156*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3157*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "char", ficlPrimitiveChar, 3158*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3159*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "char+", ficlPrimitiveCharPlus, 3160*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3161*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "chars", ficlPrimitiveChars, 3162*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3163*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "constant", 3164*a1bf3f78SToomas Soome ficlPrimitiveConstant, FICL_WORD_DEFAULT); 3165*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "count", ficlPrimitiveCount, 3166*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3167*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "cr", ficlPrimitiveCR, 3168*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3169*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "create", ficlPrimitiveCreate, 3170*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3171*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "decimal", ficlPrimitiveDecimal, 3172*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3173*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "depth", ficlPrimitiveDepth, 3174*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3175*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "do", ficlPrimitiveDoCoIm, 3176*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3177*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "does>", ficlPrimitiveDoesCoIm, 3178*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3179*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "else", ficlPrimitiveElseCoIm, 3180*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3181*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "emit", ficlPrimitiveEmit, 3182*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3183*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "endcase", 3184*a1bf3f78SToomas Soome ficlPrimitiveEndcaseCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3185*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "endof", ficlPrimitiveEndofCoIm, 3186*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3187*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "environment?", 3188*a1bf3f78SToomas Soome ficlPrimitiveEnvironmentQ, FICL_WORD_DEFAULT); 3189*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "evaluate", 3190*a1bf3f78SToomas Soome ficlPrimitiveEvaluate, FICL_WORD_DEFAULT); 3191*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "execute", ficlPrimitiveExecute, 3192*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3193*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "exit", ficlPrimitiveExitCoIm, 3194*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3195*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "fallthrough", 3196*a1bf3f78SToomas Soome ficlPrimitiveFallthroughCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3197*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "find", ficlPrimitiveCFind, 3198*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3199*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "fm/mod", 3200*a1bf3f78SToomas Soome ficlPrimitiveFMSlashMod, FICL_WORD_DEFAULT); 3201*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "here", ficlPrimitiveHere, 3202*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3203*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "hold", ficlPrimitiveHold, 3204*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3205*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "if", ficlPrimitiveIfCoIm, 3206*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3207*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "immediate", 3208*a1bf3f78SToomas Soome ficlPrimitiveImmediate, FICL_WORD_DEFAULT); 3209*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "literal", 3210*a1bf3f78SToomas Soome ficlPrimitiveLiteralIm, FICL_WORD_IMMEDIATE); 3211*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "loop", ficlPrimitiveLoopCoIm, 3212*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3213*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "m*", ficlPrimitiveMStar, 3214*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3215*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "mod", ficlPrimitiveMod, 3216*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3217*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "of", ficlPrimitiveOfCoIm, 3218*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3219*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "postpone", 3220*a1bf3f78SToomas Soome ficlPrimitivePostponeCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3221*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "quit", ficlPrimitiveQuit, 3222*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3223*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "recurse", 3224*a1bf3f78SToomas Soome ficlPrimitiveRecurseCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3225*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "repeat", 3226*a1bf3f78SToomas Soome ficlPrimitiveRepeatCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3227*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "s\"", 3228*a1bf3f78SToomas Soome ficlPrimitiveStringQuoteIm, FICL_WORD_IMMEDIATE); 3229*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "sign", ficlPrimitiveSign, 3230*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3231*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "sm/rem", 3232*a1bf3f78SToomas Soome ficlPrimitiveSMSlashRem, FICL_WORD_DEFAULT); 3233*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "source", ficlPrimitiveSource, 3234*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3235*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "state", ficlPrimitiveState, 3236*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3237*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "then", ficlPrimitiveEndifCoIm, 3238*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3239*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "type", ficlPrimitiveType, 3240*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3241*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "u.", ficlPrimitiveUDot, 3242*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3243*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "um*", ficlPrimitiveUMStar, 3244*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3245*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "um/mod", 3246*a1bf3f78SToomas Soome ficlPrimitiveUMSlashMod, FICL_WORD_DEFAULT); 3247*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "until", 3248*a1bf3f78SToomas Soome ficlPrimitiveUntilCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3249*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "variable", 3250*a1bf3f78SToomas Soome ficlPrimitiveVariable, FICL_WORD_DEFAULT); 3251*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "while", 3252*a1bf3f78SToomas Soome ficlPrimitiveWhileCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3253*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "word", ficlPrimitiveWord, 3254*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3255*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "[", 3256*a1bf3f78SToomas Soome ficlPrimitiveLeftBracketCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3257*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "[\']", 3258*a1bf3f78SToomas Soome ficlPrimitiveBracketTickCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3259*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "[char]", ficlPrimitiveCharCoIm, 3260*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3261*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "]", ficlPrimitiveRightBracket, 3262*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3263*a1bf3f78SToomas Soome /* 3264*a1bf3f78SToomas Soome * The Core Extensions word set... 3265*a1bf3f78SToomas Soome * see softcore.fr for other definitions 3266*a1bf3f78SToomas Soome */ 3267*a1bf3f78SToomas Soome /* "#tib" */ 3268*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, ".(", ficlPrimitiveDotParen, 3269*a1bf3f78SToomas Soome FICL_WORD_IMMEDIATE); 3270*a1bf3f78SToomas Soome /* ".r" is in softcore */ 3271*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, ":noname", 3272*a1bf3f78SToomas Soome ficlPrimitiveColonNoName, FICL_WORD_DEFAULT); 3273*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "?do", ficlPrimitiveQDoCoIm, 3274*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3275*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "again", ficlPrimitiveAgainCoIm, 3276*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3277*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "c\"", 3278*a1bf3f78SToomas Soome ficlPrimitiveCountedStringQuoteIm, FICL_WORD_IMMEDIATE); 3279*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "hex", ficlPrimitiveHex, 3280*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3281*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "pad", ficlPrimitivePad, 3282*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3283*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "parse", ficlPrimitiveParse, 3284*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3285*a1bf3f78SToomas Soome 3286*a1bf3f78SToomas Soome /* 3287*a1bf3f78SToomas Soome * query restore-input save-input tib u.r u> unused 3288*a1bf3f78SToomas Soome * [FICL_VM_STATE_COMPILE] 3289*a1bf3f78SToomas Soome */ 3290*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "refill", ficlPrimitiveRefill, 3291*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3292*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "source-id", 3293*a1bf3f78SToomas Soome ficlPrimitiveSourceID, FICL_WORD_DEFAULT); 3294*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "to", ficlPrimitiveToValue, 3295*a1bf3f78SToomas Soome FICL_WORD_IMMEDIATE); 3296*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "value", ficlPrimitiveConstant, 3297*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3298*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "\\", ficlPrimitiveBackslash, 3299*a1bf3f78SToomas Soome FICL_WORD_IMMEDIATE); 3300*a1bf3f78SToomas Soome 3301*a1bf3f78SToomas Soome /* 3302*a1bf3f78SToomas Soome * Environment query values for the Core word set 3303*a1bf3f78SToomas Soome */ 3304*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "/counted-string", 3305*a1bf3f78SToomas Soome FICL_COUNTED_STRING_MAX); 3306*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "/hold", FICL_PAD_SIZE); 3307*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "/pad", FICL_PAD_SIZE); 3308*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "address-unit-bits", 8); 3309*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "core", FICL_TRUE); 3310*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "core-ext", FICL_FALSE); 3311*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "floored", FICL_FALSE); 3312*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "max-char", UCHAR_MAX); 3313*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "max-n", LONG_MAX); 3314*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "max-u", ULONG_MAX); 3315*a1bf3f78SToomas Soome 3316*a1bf3f78SToomas Soome { 3317*a1bf3f78SToomas Soome ficl2Integer id; 3318*a1bf3f78SToomas Soome ficlInteger low, high; 3319*a1bf3f78SToomas Soome 3320*a1bf3f78SToomas Soome low = ULONG_MAX; 3321*a1bf3f78SToomas Soome high = LONG_MAX; 3322*a1bf3f78SToomas Soome FICL_2INTEGER_SET(high, low, id); 3323*a1bf3f78SToomas Soome ficlDictionarySet2Constant(environment, "max-d", id); 3324*a1bf3f78SToomas Soome high = ULONG_MAX; 3325*a1bf3f78SToomas Soome FICL_2INTEGER_SET(high, low, id); 3326*a1bf3f78SToomas Soome ficlDictionarySet2Constant(environment, "max-ud", id); 3327*a1bf3f78SToomas Soome } 3328*a1bf3f78SToomas Soome 3329*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "return-stack-cells", 3330*a1bf3f78SToomas Soome FICL_DEFAULT_STACK_SIZE); 3331*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "stack-cells", 3332*a1bf3f78SToomas Soome FICL_DEFAULT_STACK_SIZE); 3333*a1bf3f78SToomas Soome 3334*a1bf3f78SToomas Soome /* 3335*a1bf3f78SToomas Soome * The optional Double-Number word set (partial) 3336*a1bf3f78SToomas Soome */ 3337*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "2constant", 3338*a1bf3f78SToomas Soome ficlPrimitive2Constant, FICL_WORD_IMMEDIATE); 3339*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "2literal", 3340*a1bf3f78SToomas Soome ficlPrimitive2LiteralIm, FICL_WORD_IMMEDIATE); 3341*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "2variable", 3342*a1bf3f78SToomas Soome ficlPrimitive2Variable, FICL_WORD_IMMEDIATE); 3343*a1bf3f78SToomas Soome /* 3344*a1bf3f78SToomas Soome * D+ D- D. D.R D0< D0= D2* D2/ in softcore 3345*a1bf3f78SToomas Soome * D< D= D>S DABS DMAX DMIN DNEGATE in softcore 3346*a1bf3f78SToomas Soome * m-star-slash is TODO 3347*a1bf3f78SToomas Soome * M+ in softcore 3348*a1bf3f78SToomas Soome */ 3349*a1bf3f78SToomas Soome 3350*a1bf3f78SToomas Soome /* 3351*a1bf3f78SToomas Soome * DOUBLE EXT 3352*a1bf3f78SToomas Soome */ 3353*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "2rot", 3354*a1bf3f78SToomas Soome ficlPrimitive2Rot, FICL_WORD_DEFAULT); 3355*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "2value", 3356*a1bf3f78SToomas Soome ficlPrimitive2Constant, FICL_WORD_IMMEDIATE); 3357*a1bf3f78SToomas Soome /* du< in softcore */ 3358*a1bf3f78SToomas Soome /* 3359*a1bf3f78SToomas Soome * The optional Exception and Exception Extensions word set 3360*a1bf3f78SToomas Soome */ 3361*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "catch", ficlPrimitiveCatch, 3362*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3363*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "throw", ficlPrimitiveThrow, 3364*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3365*a1bf3f78SToomas Soome 3366*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "exception", FICL_TRUE); 3367*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "exception-ext", FICL_TRUE); 3368*a1bf3f78SToomas Soome 3369*a1bf3f78SToomas Soome /* 3370*a1bf3f78SToomas Soome * The optional Locals and Locals Extensions word set 3371*a1bf3f78SToomas Soome * see softcore.c for implementation of locals| 3372*a1bf3f78SToomas Soome */ 3373*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 3374*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "doLocal", 3375*a1bf3f78SToomas Soome ficlPrimitiveDoLocalIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3376*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "(local)", 3377*a1bf3f78SToomas Soome ficlPrimitiveLocalParen, FICL_WORD_COMPILE_ONLY); 3378*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "(2local)", 3379*a1bf3f78SToomas Soome ficlPrimitive2LocalParen, FICL_WORD_COMPILE_ONLY); 3380*a1bf3f78SToomas Soome 3381*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "locals", FICL_TRUE); 3382*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "locals-ext", FICL_TRUE); 3383*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "#locals", FICL_MAX_LOCALS); 3384*a1bf3f78SToomas Soome #endif 3385*a1bf3f78SToomas Soome 3386*a1bf3f78SToomas Soome /* 3387*a1bf3f78SToomas Soome * The optional Memory-Allocation word set 3388*a1bf3f78SToomas Soome */ 3389*a1bf3f78SToomas Soome 3390*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "allocate", 3391*a1bf3f78SToomas Soome ficlPrimitiveAllocate, FICL_WORD_DEFAULT); 3392*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "free", ficlPrimitiveFree, 3393*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3394*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "resize", ficlPrimitiveResize, 3395*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3396*a1bf3f78SToomas Soome 3397*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "memory-alloc", FICL_TRUE); 3398*a1bf3f78SToomas Soome 3399*a1bf3f78SToomas Soome /* 3400*a1bf3f78SToomas Soome * The optional Search-Order word set 3401*a1bf3f78SToomas Soome */ 3402*a1bf3f78SToomas Soome ficlSystemCompileSearch(system); 3403*a1bf3f78SToomas Soome 3404*a1bf3f78SToomas Soome /* 3405*a1bf3f78SToomas Soome * The optional Programming-Tools and Programming-Tools 3406*a1bf3f78SToomas Soome * Extensions word set 3407*a1bf3f78SToomas Soome */ 3408*a1bf3f78SToomas Soome ficlSystemCompileTools(system); 3409*a1bf3f78SToomas Soome 3410*a1bf3f78SToomas Soome /* 3411*a1bf3f78SToomas Soome * The optional File-Access and File-Access Extensions word set 3412*a1bf3f78SToomas Soome */ 3413*a1bf3f78SToomas Soome #if FICL_WANT_FILE 3414*a1bf3f78SToomas Soome ficlSystemCompileFile(system); 3415*a1bf3f78SToomas Soome #endif 3416*a1bf3f78SToomas Soome 3417*a1bf3f78SToomas Soome /* 3418*a1bf3f78SToomas Soome * Ficl extras 3419*a1bf3f78SToomas Soome */ 3420*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, ".ver", ficlPrimitiveVersion, 3421*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3422*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, ">name", ficlPrimitiveToName, 3423*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3424*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "add-parse-step", 3425*a1bf3f78SToomas Soome ficlPrimitiveAddParseStep, FICL_WORD_DEFAULT); 3426*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "body>", ficlPrimitiveFromBody, 3427*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3428*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "compile-only", 3429*a1bf3f78SToomas Soome ficlPrimitiveCompileOnly, FICL_WORD_DEFAULT); 3430*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "endif", ficlPrimitiveEndifCoIm, 3431*a1bf3f78SToomas Soome FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3432*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "last-word", 3433*a1bf3f78SToomas Soome ficlPrimitiveLastWord, FICL_WORD_DEFAULT); 3434*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "hash", ficlPrimitiveHash, 3435*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3436*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "objectify", 3437*a1bf3f78SToomas Soome ficlPrimitiveSetObjectFlag, FICL_WORD_DEFAULT); 3438*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "?object", 3439*a1bf3f78SToomas Soome ficlPrimitiveIsObject, FICL_WORD_DEFAULT); 3440*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "parse-word", 3441*a1bf3f78SToomas Soome ficlPrimitiveParseNoCopy, FICL_WORD_DEFAULT); 3442*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "sfind", ficlPrimitiveSFind, 3443*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3444*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "sliteral", 3445*a1bf3f78SToomas Soome ficlPrimitiveSLiteralCoIm, FICL_WORD_COMPILE_ONLY_IMMEDIATE); 3446*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "sprintf", ficlPrimitiveSprintf, 3447*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3448*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "strlen", ficlPrimitiveStrlen, 3449*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3450*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "x.", ficlPrimitiveHexDot, 3451*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3452*a1bf3f78SToomas Soome #if FICL_WANT_USER 3453*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "user", ficlPrimitiveUser, 3454*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3455*a1bf3f78SToomas Soome #endif 3456*a1bf3f78SToomas Soome 3457*a1bf3f78SToomas Soome /* 3458*a1bf3f78SToomas Soome * internal support words 3459*a1bf3f78SToomas Soome */ 3460*a1bf3f78SToomas Soome interpret = ficlDictionarySetPrimitive(dictionary, "interpret", 3461*a1bf3f78SToomas Soome ficlPrimitiveInterpret, FICL_WORD_DEFAULT); 3462*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "lookup", ficlPrimitiveLookup, 3463*a1bf3f78SToomas Soome FICL_WORD_DEFAULT); 3464*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "(parse-step)", 3465*a1bf3f78SToomas Soome ficlPrimitiveParseStepParen, FICL_WORD_DEFAULT); 3466*a1bf3f78SToomas Soome system->exitInnerWord = ficlDictionarySetPrimitive(dictionary, 3467*a1bf3f78SToomas Soome "exit-inner", ficlPrimitiveExitInner, FICL_WORD_DEFAULT); 3468*a1bf3f78SToomas Soome 3469*a1bf3f78SToomas Soome /* 3470*a1bf3f78SToomas Soome * Set constants representing the internal instruction words 3471*a1bf3f78SToomas Soome * If you want all of 'em, turn that "#if 0" to "#if 1". 3472*a1bf3f78SToomas Soome * By default you only get the numbers (fi0, fiNeg1, etc). 3473*a1bf3f78SToomas Soome */ 3474*a1bf3f78SToomas Soome #define FICL_TOKEN(token, description) \ 3475*a1bf3f78SToomas Soome ficlDictionarySetConstant(dictionary, #token, token); 3476*a1bf3f78SToomas Soome #if 0 3477*a1bf3f78SToomas Soome #define FICL_INSTRUCTION_TOKEN(token, description, flags) \ 3478*a1bf3f78SToomas Soome ficlDictionarySetConstant(dictionary, #token, token); 3479*a1bf3f78SToomas Soome #else 3480*a1bf3f78SToomas Soome #define FICL_INSTRUCTION_TOKEN(token, description, flags) 3481*a1bf3f78SToomas Soome #endif /* 0 */ 3482*a1bf3f78SToomas Soome #include "ficltokens.h" 3483*a1bf3f78SToomas Soome #undef FICL_TOKEN 3484*a1bf3f78SToomas Soome #undef FICL_INSTRUCTION_TOKEN 3485*a1bf3f78SToomas Soome 3486*a1bf3f78SToomas Soome /* 3487*a1bf3f78SToomas Soome * Set up system's outer interpreter loop - maybe this should 3488*a1bf3f78SToomas Soome * be in initSystem? 3489*a1bf3f78SToomas Soome */ 3490*a1bf3f78SToomas Soome system->interpreterLoop[0] = interpret; 3491*a1bf3f78SToomas Soome system->interpreterLoop[1] = (ficlWord *)ficlInstructionBranchParen; 3492*a1bf3f78SToomas Soome system->interpreterLoop[2] = (ficlWord *)(void *)(-2); 3493*a1bf3f78SToomas Soome 3494*a1bf3f78SToomas Soome FICL_SYSTEM_ASSERT(system, 3495*a1bf3f78SToomas Soome ficlDictionaryCellsAvailable(dictionary) > 0); 3496*a1bf3f78SToomas Soome } 3497