1*a1bf3f78SToomas Soome /* 2*a1bf3f78SToomas Soome * f i c l . c 3*a1bf3f78SToomas Soome * Forth Inspired Command Language - external interface 4*a1bf3f78SToomas Soome * Author: John Sadler (john_sadler@alum.mit.edu) 5*a1bf3f78SToomas Soome * Created: 19 July 1997 6*a1bf3f78SToomas Soome * $Id: system.c,v 1.2 2010/09/10 10:35:54 asau Exp $ 7*a1bf3f78SToomas Soome */ 8*a1bf3f78SToomas Soome /* 9*a1bf3f78SToomas Soome * This is an ANS Forth interpreter written in C. 10*a1bf3f78SToomas Soome * Ficl uses Forth syntax for its commands, but turns the Forth 11*a1bf3f78SToomas Soome * model on its head in other respects. 12*a1bf3f78SToomas Soome * Ficl provides facilities for interoperating 13*a1bf3f78SToomas Soome * with programs written in C: C functions can be exported to Ficl, 14*a1bf3f78SToomas Soome * and Ficl commands can be executed via a C calling interface. The 15*a1bf3f78SToomas Soome * interpreter is re-entrant, so it can be used in multiple instances 16*a1bf3f78SToomas Soome * in a multitasking system. Unlike Forth, Ficl's outer interpreter 17*a1bf3f78SToomas Soome * expects a text block as input, and returns to the caller after each 18*a1bf3f78SToomas Soome * text block, so the data pump is somewhere in external code in the 19*a1bf3f78SToomas Soome * style of TCL. 20*a1bf3f78SToomas Soome * 21*a1bf3f78SToomas Soome * Code is written in ANSI C for portability. 22*a1bf3f78SToomas Soome */ 23*a1bf3f78SToomas Soome /* 24*a1bf3f78SToomas Soome * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) 25*a1bf3f78SToomas Soome * All rights reserved. 26*a1bf3f78SToomas Soome * 27*a1bf3f78SToomas Soome * Get the latest Ficl release at http://ficl.sourceforge.net 28*a1bf3f78SToomas Soome * 29*a1bf3f78SToomas Soome * I am interested in hearing from anyone who uses Ficl. If you have 30*a1bf3f78SToomas Soome * a problem, a success story, a defect, an enhancement request, or 31*a1bf3f78SToomas Soome * if you would like to contribute to the Ficl release, please 32*a1bf3f78SToomas Soome * contact me by email at the address above. 33*a1bf3f78SToomas Soome * 34*a1bf3f78SToomas Soome * L I C E N S E and D I S C L A I M E R 35*a1bf3f78SToomas Soome * 36*a1bf3f78SToomas Soome * Redistribution and use in source and binary forms, with or without 37*a1bf3f78SToomas Soome * modification, are permitted provided that the following conditions 38*a1bf3f78SToomas Soome * are met: 39*a1bf3f78SToomas Soome * 1. Redistributions of source code must retain the above copyright 40*a1bf3f78SToomas Soome * notice, this list of conditions and the following disclaimer. 41*a1bf3f78SToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 42*a1bf3f78SToomas Soome * notice, this list of conditions and the following disclaimer in the 43*a1bf3f78SToomas Soome * documentation and/or other materials provided with the distribution. 44*a1bf3f78SToomas Soome * 45*a1bf3f78SToomas Soome * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46*a1bf3f78SToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47*a1bf3f78SToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48*a1bf3f78SToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49*a1bf3f78SToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50*a1bf3f78SToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51*a1bf3f78SToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52*a1bf3f78SToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53*a1bf3f78SToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54*a1bf3f78SToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55*a1bf3f78SToomas Soome * SUCH DAMAGE. 56*a1bf3f78SToomas Soome */ 57*a1bf3f78SToomas Soome 58*a1bf3f78SToomas Soome #include "ficl.h" 59*a1bf3f78SToomas Soome 60*a1bf3f78SToomas Soome /* 61*a1bf3f78SToomas Soome * System statics 62*a1bf3f78SToomas Soome * Each ficlSystem builds a global dictionary during its start 63*a1bf3f78SToomas Soome * sequence. This is shared by all virtual machines of that system. 64*a1bf3f78SToomas Soome * Therefore only one VM can update the dictionary 65*a1bf3f78SToomas Soome * at a time. The system imports a locking function that 66*a1bf3f78SToomas Soome * you can override in order to control update access to 67*a1bf3f78SToomas Soome * the dictionary. The function is stubbed out by default, 68*a1bf3f78SToomas Soome * but you can insert one: #define FICL_WANT_MULTITHREADED 1 69*a1bf3f78SToomas Soome * and supply your own version of ficlDictionaryLock. 70*a1bf3f78SToomas Soome */ 71*a1bf3f78SToomas Soome 72*a1bf3f78SToomas Soome ficlSystem *ficlSystemGlobal = NULL; 73*a1bf3f78SToomas Soome 74*a1bf3f78SToomas Soome /* 75*a1bf3f78SToomas Soome * f i c l S e t V e r s i o n E n v 76*a1bf3f78SToomas Soome * Create a double ficlCell environment constant for the version ID 77*a1bf3f78SToomas Soome */ 78*a1bf3f78SToomas Soome static void 79*a1bf3f78SToomas Soome ficlSystemSetVersion(ficlSystem *system) 80*a1bf3f78SToomas Soome { 81*a1bf3f78SToomas Soome int major = FICL_VERSION_MAJOR; 82*a1bf3f78SToomas Soome int minor = FICL_VERSION_MINOR; 83*a1bf3f78SToomas Soome ficl2Integer combined; 84*a1bf3f78SToomas Soome ficlDictionary *environment = ficlSystemGetEnvironment(system); 85*a1bf3f78SToomas Soome FICL_2INTEGER_SET(major, minor, combined); 86*a1bf3f78SToomas Soome ficlDictionarySet2Constant(environment, "ficl-version", combined); 87*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, "ficl-robust", FICL_ROBUST); 88*a1bf3f78SToomas Soome } 89*a1bf3f78SToomas Soome 90*a1bf3f78SToomas Soome /* 91*a1bf3f78SToomas Soome * f i c l I n i t S y s t e m 92*a1bf3f78SToomas Soome * Binds a global dictionary to the interpreter system. 93*a1bf3f78SToomas Soome * You specify the address and size of the allocated area. 94*a1bf3f78SToomas Soome * After that, Ficl manages it. 95*a1bf3f78SToomas Soome * First step is to set up the static pointers to the area. 96*a1bf3f78SToomas Soome * Then write the "precompiled" portion of the dictionary in. 97*a1bf3f78SToomas Soome * The dictionary needs to be at least large enough to hold the 98*a1bf3f78SToomas Soome * precompiled part. Try 1K cells minimum. Use "words" to find 99*a1bf3f78SToomas Soome * out how much of the dictionary is used at any time. 100*a1bf3f78SToomas Soome */ 101*a1bf3f78SToomas Soome ficlSystem * 102*a1bf3f78SToomas Soome ficlSystemCreate(ficlSystemInformation *fsi) 103*a1bf3f78SToomas Soome { 104*a1bf3f78SToomas Soome ficlInteger dictionarySize; 105*a1bf3f78SToomas Soome ficlInteger environmentSize; 106*a1bf3f78SToomas Soome ficlInteger stackSize; 107*a1bf3f78SToomas Soome ficlSystem *system; 108*a1bf3f78SToomas Soome ficlCallback callback; 109*a1bf3f78SToomas Soome ficlSystemInformation fauxInfo; 110*a1bf3f78SToomas Soome ficlDictionary *environment; 111*a1bf3f78SToomas Soome 112*a1bf3f78SToomas Soome if (fsi == NULL) { 113*a1bf3f78SToomas Soome fsi = &fauxInfo; 114*a1bf3f78SToomas Soome ficlSystemInformationInitialize(fsi); 115*a1bf3f78SToomas Soome } 116*a1bf3f78SToomas Soome 117*a1bf3f78SToomas Soome callback.context = fsi->context; 118*a1bf3f78SToomas Soome callback.textOut = fsi->textOut; 119*a1bf3f78SToomas Soome callback.errorOut = fsi->errorOut; 120*a1bf3f78SToomas Soome callback.system = NULL; 121*a1bf3f78SToomas Soome callback.vm = NULL; 122*a1bf3f78SToomas Soome 123*a1bf3f78SToomas Soome FICL_ASSERT(&callback, sizeof (ficlInteger) >= sizeof (void *)); 124*a1bf3f78SToomas Soome FICL_ASSERT(&callback, sizeof (ficlUnsigned) >= sizeof (void *)); 125*a1bf3f78SToomas Soome #if (FICL_WANT_FLOAT) 126*a1bf3f78SToomas Soome FICL_ASSERT(&callback, sizeof (ficlFloat) <= sizeof (ficlInteger)); 127*a1bf3f78SToomas Soome #endif 128*a1bf3f78SToomas Soome 129*a1bf3f78SToomas Soome system = ficlMalloc(sizeof (ficlSystem)); 130*a1bf3f78SToomas Soome 131*a1bf3f78SToomas Soome FICL_ASSERT(&callback, system); 132*a1bf3f78SToomas Soome 133*a1bf3f78SToomas Soome memset(system, 0, sizeof (ficlSystem)); 134*a1bf3f78SToomas Soome 135*a1bf3f78SToomas Soome dictionarySize = fsi->dictionarySize; 136*a1bf3f78SToomas Soome if (dictionarySize <= 0) 137*a1bf3f78SToomas Soome dictionarySize = FICL_DEFAULT_DICTIONARY_SIZE; 138*a1bf3f78SToomas Soome 139*a1bf3f78SToomas Soome environmentSize = fsi->environmentSize; 140*a1bf3f78SToomas Soome if (environmentSize <= 0) 141*a1bf3f78SToomas Soome environmentSize = FICL_DEFAULT_ENVIRONMENT_SIZE; 142*a1bf3f78SToomas Soome 143*a1bf3f78SToomas Soome stackSize = fsi->stackSize; 144*a1bf3f78SToomas Soome if (stackSize < FICL_DEFAULT_STACK_SIZE) 145*a1bf3f78SToomas Soome stackSize = FICL_DEFAULT_STACK_SIZE; 146*a1bf3f78SToomas Soome 147*a1bf3f78SToomas Soome system->dictionary = ficlDictionaryCreateHashed(system, 148*a1bf3f78SToomas Soome (unsigned)dictionarySize, FICL_HASH_SIZE); 149*a1bf3f78SToomas Soome system->dictionary->forthWordlist->name = "forth-wordlist"; 150*a1bf3f78SToomas Soome 151*a1bf3f78SToomas Soome environment = ficlDictionaryCreate(system, (unsigned)environmentSize); 152*a1bf3f78SToomas Soome system->environment = environment; 153*a1bf3f78SToomas Soome system->environment->forthWordlist->name = "environment"; 154*a1bf3f78SToomas Soome 155*a1bf3f78SToomas Soome system->callback.textOut = fsi->textOut; 156*a1bf3f78SToomas Soome system->callback.errorOut = fsi->errorOut; 157*a1bf3f78SToomas Soome system->callback.context = fsi->context; 158*a1bf3f78SToomas Soome system->callback.system = system; 159*a1bf3f78SToomas Soome system->callback.vm = NULL; 160*a1bf3f78SToomas Soome system->stackSize = stackSize; 161*a1bf3f78SToomas Soome 162*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 163*a1bf3f78SToomas Soome /* 164*a1bf3f78SToomas Soome * The locals dictionary is only searched while compiling, 165*a1bf3f78SToomas Soome * but this is where speed is most important. On the other 166*a1bf3f78SToomas Soome * hand, the dictionary gets emptied after each use of locals 167*a1bf3f78SToomas Soome * The need to balance search speed with the cost of the 'empty' 168*a1bf3f78SToomas Soome * operation led me to select a single-threaded list... 169*a1bf3f78SToomas Soome */ 170*a1bf3f78SToomas Soome system->locals = ficlDictionaryCreate(system, 171*a1bf3f78SToomas Soome (unsigned)FICL_MAX_LOCALS * FICL_CELLS_PER_WORD); 172*a1bf3f78SToomas Soome #endif /* FICL_WANT_LOCALS */ 173*a1bf3f78SToomas Soome 174*a1bf3f78SToomas Soome /* 175*a1bf3f78SToomas Soome * Build the precompiled dictionary and load softwords. We need 176*a1bf3f78SToomas Soome * a temporary VM to do this - ficlNewVM links one to the head of 177*a1bf3f78SToomas Soome * the system VM list. ficlCompilePlatform (defined in win32.c, 178*a1bf3f78SToomas Soome * for example) adds platform specific words. 179*a1bf3f78SToomas Soome */ 180*a1bf3f78SToomas Soome ficlSystemCompileCore(system); 181*a1bf3f78SToomas Soome ficlSystemCompilePrefix(system); 182*a1bf3f78SToomas Soome 183*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT 184*a1bf3f78SToomas Soome ficlSystemCompileFloat(system); 185*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */ 186*a1bf3f78SToomas Soome 187*a1bf3f78SToomas Soome #if FICL_WANT_PLATFORM 188*a1bf3f78SToomas Soome ficlSystemCompilePlatform(system); 189*a1bf3f78SToomas Soome #endif /* FICL_WANT_PLATFORM */ 190*a1bf3f78SToomas Soome 191*a1bf3f78SToomas Soome ficlSystemSetVersion(system); 192*a1bf3f78SToomas Soome 193*a1bf3f78SToomas Soome /* 194*a1bf3f78SToomas Soome * Establish the parse order. Note that prefixes precede numbers - 195*a1bf3f78SToomas Soome * this allows constructs like "0b101010" which might parse as a 196*a1bf3f78SToomas Soome * hex value otherwise. 197*a1bf3f78SToomas Soome */ 198*a1bf3f78SToomas Soome ficlSystemAddPrimitiveParseStep(system, "?word", ficlVmParseWord); 199*a1bf3f78SToomas Soome ficlSystemAddPrimitiveParseStep(system, "?prefix", ficlVmParsePrefix); 200*a1bf3f78SToomas Soome ficlSystemAddPrimitiveParseStep(system, "?number", ficlVmParseNumber); 201*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT 202*a1bf3f78SToomas Soome ficlSystemAddPrimitiveParseStep(system, "?float", 203*a1bf3f78SToomas Soome ficlVmParseFloatNumber); 204*a1bf3f78SToomas Soome #endif 205*a1bf3f78SToomas Soome 206*a1bf3f78SToomas Soome /* 207*a1bf3f78SToomas Soome * Now create a temporary VM to compile the softwords. Since all VMs 208*a1bf3f78SToomas Soome * are linked into the vmList of ficlSystem, we don't have to pass 209*a1bf3f78SToomas Soome * the VM to ficlCompileSoftCore -- it just hijacks whatever it finds 210*a1bf3f78SToomas Soome * in the VM list. Ficl 2.05: vmCreate no longer depends on the 211*a1bf3f78SToomas Soome * presence of INTERPRET in the dictionary, so a VM can be created 212*a1bf3f78SToomas Soome * before the dictionary is built. It just can't do much... 213*a1bf3f78SToomas Soome */ 214*a1bf3f78SToomas Soome ficlSystemCreateVm(system); 215*a1bf3f78SToomas Soome #define ADD_COMPILE_FLAG(name) \ 216*a1bf3f78SToomas Soome ficlDictionarySetConstant(environment, #name, name) 217*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_LZ4_SOFTCORE); 218*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_FILE); 219*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_FLOAT); 220*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_DEBUGGER); 221*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_EXTENDED_PREFIX); 222*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_USER); 223*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_LOCALS); 224*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_OOP); 225*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_SOFTWORDS); 226*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_MULTITHREADED); 227*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_OPTIMIZE); 228*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_WANT_VCALL); 229*a1bf3f78SToomas Soome 230*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_PLATFORM_ALIGNMENT); 231*a1bf3f78SToomas Soome 232*a1bf3f78SToomas Soome ADD_COMPILE_FLAG(FICL_ROBUST); 233*a1bf3f78SToomas Soome 234*a1bf3f78SToomas Soome #define ADD_COMPILE_STRING(name) \ 235*a1bf3f78SToomas Soome ficlDictionarySetConstantString(environment, #name, name) 236*a1bf3f78SToomas Soome ADD_COMPILE_STRING(FICL_PLATFORM_ARCHITECTURE); 237*a1bf3f78SToomas Soome ADD_COMPILE_STRING(FICL_PLATFORM_OS); 238*a1bf3f78SToomas Soome 239*a1bf3f78SToomas Soome ficlSystemCompileSoftCore(system); 240*a1bf3f78SToomas Soome ficlSystemDestroyVm(system->vmList); 241*a1bf3f78SToomas Soome 242*a1bf3f78SToomas Soome if (ficlSystemGlobal == NULL) 243*a1bf3f78SToomas Soome ficlSystemGlobal = system; 244*a1bf3f78SToomas Soome 245*a1bf3f78SToomas Soome return (system); 246*a1bf3f78SToomas Soome } 247*a1bf3f78SToomas Soome 248*a1bf3f78SToomas Soome /* 249*a1bf3f78SToomas Soome * f i c l T e r m S y s t e m 250*a1bf3f78SToomas Soome * Tear the system down by deleting the dictionaries and all VMs. 251*a1bf3f78SToomas Soome * This saves you from having to keep track of all that stuff. 252*a1bf3f78SToomas Soome */ 253*a1bf3f78SToomas Soome void 254*a1bf3f78SToomas Soome ficlSystemDestroy(ficlSystem *system) 255*a1bf3f78SToomas Soome { 256*a1bf3f78SToomas Soome if (system->dictionary) 257*a1bf3f78SToomas Soome ficlDictionaryDestroy(system->dictionary); 258*a1bf3f78SToomas Soome system->dictionary = NULL; 259*a1bf3f78SToomas Soome 260*a1bf3f78SToomas Soome if (system->environment) 261*a1bf3f78SToomas Soome ficlDictionaryDestroy(system->environment); 262*a1bf3f78SToomas Soome system->environment = NULL; 263*a1bf3f78SToomas Soome 264*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 265*a1bf3f78SToomas Soome if (system->locals) 266*a1bf3f78SToomas Soome ficlDictionaryDestroy(system->locals); 267*a1bf3f78SToomas Soome system->locals = NULL; 268*a1bf3f78SToomas Soome #endif 269*a1bf3f78SToomas Soome 270*a1bf3f78SToomas Soome while (system->vmList != NULL) { 271*a1bf3f78SToomas Soome ficlVm *vm = system->vmList; 272*a1bf3f78SToomas Soome system->vmList = system->vmList->link; 273*a1bf3f78SToomas Soome ficlVmDestroy(vm); 274*a1bf3f78SToomas Soome } 275*a1bf3f78SToomas Soome 276*a1bf3f78SToomas Soome if (ficlSystemGlobal == system) 277*a1bf3f78SToomas Soome ficlSystemGlobal = NULL; 278*a1bf3f78SToomas Soome 279*a1bf3f78SToomas Soome ficlFree(system); 280*a1bf3f78SToomas Soome system = NULL; 281*a1bf3f78SToomas Soome } 282*a1bf3f78SToomas Soome 283*a1bf3f78SToomas Soome /* 284*a1bf3f78SToomas Soome * f i c l A d d P a r s e S t e p 285*a1bf3f78SToomas Soome * Appends a parse step function to the end of the parse list (see 286*a1bf3f78SToomas Soome * ficlParseStep notes in ficl.h for details). Returns 0 if successful, 287*a1bf3f78SToomas Soome * nonzero if there's no more room in the list. 288*a1bf3f78SToomas Soome */ 289*a1bf3f78SToomas Soome int 290*a1bf3f78SToomas Soome ficlSystemAddParseStep(ficlSystem *system, ficlWord *word) 291*a1bf3f78SToomas Soome { 292*a1bf3f78SToomas Soome int i; 293*a1bf3f78SToomas Soome for (i = 0; i < FICL_MAX_PARSE_STEPS; i++) { 294*a1bf3f78SToomas Soome if (system->parseList[i] == NULL) { 295*a1bf3f78SToomas Soome system->parseList[i] = word; 296*a1bf3f78SToomas Soome return (0); 297*a1bf3f78SToomas Soome } 298*a1bf3f78SToomas Soome } 299*a1bf3f78SToomas Soome 300*a1bf3f78SToomas Soome return (1); 301*a1bf3f78SToomas Soome } 302*a1bf3f78SToomas Soome 303*a1bf3f78SToomas Soome /* 304*a1bf3f78SToomas Soome * Compile a word into the dictionary that invokes the specified ficlParseStep 305*a1bf3f78SToomas Soome * function. It is up to the user (as usual in Forth) to make sure the stack 306*a1bf3f78SToomas Soome * preconditions are valid (there needs to be a counted string on top of the 307*a1bf3f78SToomas Soome * stack) before using the resulting word. 308*a1bf3f78SToomas Soome */ 309*a1bf3f78SToomas Soome void 310*a1bf3f78SToomas Soome ficlSystemAddPrimitiveParseStep(ficlSystem *system, char *name, 311*a1bf3f78SToomas Soome ficlParseStep pStep) 312*a1bf3f78SToomas Soome { 313*a1bf3f78SToomas Soome ficlDictionary *dictionary = system->dictionary; 314*a1bf3f78SToomas Soome ficlWord *word; 315*a1bf3f78SToomas Soome ficlCell c; 316*a1bf3f78SToomas Soome 317*a1bf3f78SToomas Soome word = ficlDictionaryAppendPrimitive(dictionary, name, 318*a1bf3f78SToomas Soome ficlPrimitiveParseStepParen, FICL_WORD_DEFAULT); 319*a1bf3f78SToomas Soome 320*a1bf3f78SToomas Soome c.fn = (void (*)(void))pStep; 321*a1bf3f78SToomas Soome ficlDictionaryAppendCell(dictionary, c); 322*a1bf3f78SToomas Soome ficlSystemAddParseStep(system, word); 323*a1bf3f78SToomas Soome } 324*a1bf3f78SToomas Soome 325*a1bf3f78SToomas Soome /* 326*a1bf3f78SToomas Soome * f i c l N e w V M 327*a1bf3f78SToomas Soome * Create a new virtual machine and link it into the system list 328*a1bf3f78SToomas Soome * of VMs for later cleanup by ficlTermSystem. 329*a1bf3f78SToomas Soome */ 330*a1bf3f78SToomas Soome ficlVm * 331*a1bf3f78SToomas Soome ficlSystemCreateVm(ficlSystem *system) 332*a1bf3f78SToomas Soome { 333*a1bf3f78SToomas Soome ficlVm *vm = ficlVmCreate(NULL, system->stackSize, system->stackSize); 334*a1bf3f78SToomas Soome vm->link = system->vmList; 335*a1bf3f78SToomas Soome 336*a1bf3f78SToomas Soome memcpy(&(vm->callback), &(system->callback), sizeof (system->callback)); 337*a1bf3f78SToomas Soome vm->callback.vm = vm; 338*a1bf3f78SToomas Soome vm->callback.system = system; 339*a1bf3f78SToomas Soome 340*a1bf3f78SToomas Soome system->vmList = vm; 341*a1bf3f78SToomas Soome return (vm); 342*a1bf3f78SToomas Soome } 343*a1bf3f78SToomas Soome 344*a1bf3f78SToomas Soome /* 345*a1bf3f78SToomas Soome * f i c l F r e e V M 346*a1bf3f78SToomas Soome * Removes the VM in question from the system VM list and deletes the 347*a1bf3f78SToomas Soome * memory allocated to it. This is an optional call, since ficlTermSystem 348*a1bf3f78SToomas Soome * will do this cleanup for you. This function is handy if you're going to 349*a1bf3f78SToomas Soome * do a lot of dynamic creation of VMs. 350*a1bf3f78SToomas Soome */ 351*a1bf3f78SToomas Soome void 352*a1bf3f78SToomas Soome ficlSystemDestroyVm(ficlVm *vm) 353*a1bf3f78SToomas Soome { 354*a1bf3f78SToomas Soome ficlSystem *system = vm->callback.system; 355*a1bf3f78SToomas Soome ficlVm *pList = system->vmList; 356*a1bf3f78SToomas Soome 357*a1bf3f78SToomas Soome FICL_VM_ASSERT(vm, vm != NULL); 358*a1bf3f78SToomas Soome 359*a1bf3f78SToomas Soome if (system->vmList == vm) { 360*a1bf3f78SToomas Soome system->vmList = system->vmList->link; 361*a1bf3f78SToomas Soome } else 362*a1bf3f78SToomas Soome for (; pList != NULL; pList = pList->link) { 363*a1bf3f78SToomas Soome if (pList->link == vm) { 364*a1bf3f78SToomas Soome pList->link = vm->link; 365*a1bf3f78SToomas Soome break; 366*a1bf3f78SToomas Soome } 367*a1bf3f78SToomas Soome } 368*a1bf3f78SToomas Soome 369*a1bf3f78SToomas Soome if (pList) 370*a1bf3f78SToomas Soome ficlVmDestroy(vm); 371*a1bf3f78SToomas Soome } 372*a1bf3f78SToomas Soome 373*a1bf3f78SToomas Soome /* 374*a1bf3f78SToomas Soome * f i c l L o o k u p 375*a1bf3f78SToomas Soome * Look in the system dictionary for a match to the given name. If 376*a1bf3f78SToomas Soome * found, return the address of the corresponding ficlWord. Otherwise 377*a1bf3f78SToomas Soome * return NULL. 378*a1bf3f78SToomas Soome */ 379*a1bf3f78SToomas Soome ficlWord * 380*a1bf3f78SToomas Soome ficlSystemLookup(ficlSystem *system, char *name) 381*a1bf3f78SToomas Soome { 382*a1bf3f78SToomas Soome ficlString s; 383*a1bf3f78SToomas Soome FICL_STRING_SET_FROM_CSTRING(s, name); 384*a1bf3f78SToomas Soome return (ficlDictionaryLookup(system->dictionary, s)); 385*a1bf3f78SToomas Soome } 386*a1bf3f78SToomas Soome 387*a1bf3f78SToomas Soome /* 388*a1bf3f78SToomas Soome * f i c l G e t D i c t 389*a1bf3f78SToomas Soome * Returns the address of the system dictionary 390*a1bf3f78SToomas Soome */ 391*a1bf3f78SToomas Soome ficlDictionary * 392*a1bf3f78SToomas Soome ficlSystemGetDictionary(ficlSystem *system) 393*a1bf3f78SToomas Soome { 394*a1bf3f78SToomas Soome return (system->dictionary); 395*a1bf3f78SToomas Soome } 396*a1bf3f78SToomas Soome 397*a1bf3f78SToomas Soome /* 398*a1bf3f78SToomas Soome * f i c l G e t E n v 399*a1bf3f78SToomas Soome * Returns the address of the system environment space 400*a1bf3f78SToomas Soome */ 401*a1bf3f78SToomas Soome ficlDictionary * 402*a1bf3f78SToomas Soome ficlSystemGetEnvironment(ficlSystem *system) 403*a1bf3f78SToomas Soome { 404*a1bf3f78SToomas Soome return (system->environment); 405*a1bf3f78SToomas Soome } 406*a1bf3f78SToomas Soome 407*a1bf3f78SToomas Soome /* 408*a1bf3f78SToomas Soome * f i c l G e t L o c 409*a1bf3f78SToomas Soome * Returns the address of the system locals dictionary. This dictionary is 410*a1bf3f78SToomas Soome * only used during compilation, and is shared by all VMs. 411*a1bf3f78SToomas Soome */ 412*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 413*a1bf3f78SToomas Soome ficlDictionary * 414*a1bf3f78SToomas Soome ficlSystemGetLocals(ficlSystem *system) 415*a1bf3f78SToomas Soome { 416*a1bf3f78SToomas Soome return (system->locals); 417*a1bf3f78SToomas Soome } 418*a1bf3f78SToomas Soome #endif 419*a1bf3f78SToomas Soome 420*a1bf3f78SToomas Soome /* 421*a1bf3f78SToomas Soome * f i c l L o o k u p L o c 422*a1bf3f78SToomas Soome * Same as dictLookup, but looks in system locals dictionary first... 423*a1bf3f78SToomas Soome * Assumes locals dictionary has only one wordlist... 424*a1bf3f78SToomas Soome */ 425*a1bf3f78SToomas Soome #if FICL_WANT_LOCALS 426*a1bf3f78SToomas Soome ficlWord * 427*a1bf3f78SToomas Soome ficlSystemLookupLocal(ficlSystem *system, ficlString name) 428*a1bf3f78SToomas Soome { 429*a1bf3f78SToomas Soome ficlWord *word = NULL; 430*a1bf3f78SToomas Soome ficlDictionary *dictionary = system->dictionary; 431*a1bf3f78SToomas Soome ficlHash *hash = ficlSystemGetLocals(system)->forthWordlist; 432*a1bf3f78SToomas Soome int i; 433*a1bf3f78SToomas Soome ficlUnsigned16 hashCode = ficlHashCode(name); 434*a1bf3f78SToomas Soome 435*a1bf3f78SToomas Soome FICL_SYSTEM_ASSERT(system, hash); 436*a1bf3f78SToomas Soome FICL_SYSTEM_ASSERT(system, dictionary); 437*a1bf3f78SToomas Soome 438*a1bf3f78SToomas Soome ficlDictionaryLock(dictionary, FICL_TRUE); 439*a1bf3f78SToomas Soome /* 440*a1bf3f78SToomas Soome * check the locals dictionary first... 441*a1bf3f78SToomas Soome */ 442*a1bf3f78SToomas Soome word = ficlHashLookup(hash, name, hashCode); 443*a1bf3f78SToomas Soome 444*a1bf3f78SToomas Soome /* 445*a1bf3f78SToomas Soome * If no joy, (!word) ------------------------------v 446*a1bf3f78SToomas Soome * iterate over the search list in the main dictionary 447*a1bf3f78SToomas Soome */ 448*a1bf3f78SToomas Soome for (i = (int)dictionary->wordlistCount - 1; (i >= 0) && (!word); --i) { 449*a1bf3f78SToomas Soome hash = dictionary->wordlists[i]; 450*a1bf3f78SToomas Soome word = ficlHashLookup(hash, name, hashCode); 451*a1bf3f78SToomas Soome } 452*a1bf3f78SToomas Soome 453*a1bf3f78SToomas Soome ficlDictionaryLock(dictionary, FICL_FALSE); 454*a1bf3f78SToomas Soome return (word); 455*a1bf3f78SToomas Soome } 456*a1bf3f78SToomas Soome #endif 457