1*a1bf3f78SToomas Soome /* 2*a1bf3f78SToomas Soome * p r e f i x . c 3*a1bf3f78SToomas Soome * Forth Inspired Command Language 4*a1bf3f78SToomas Soome * Parser extensions for Ficl 5*a1bf3f78SToomas Soome * Authors: Larry Hastings & John Sadler (john_sadler@alum.mit.edu) 6*a1bf3f78SToomas Soome * Created: April 2001 7*a1bf3f78SToomas Soome * $Id: prefix.c,v 1.8 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 46*a1bf3f78SToomas Soome /* 47*a1bf3f78SToomas Soome * (jws) revisions: 48*a1bf3f78SToomas Soome * A prefix is a word in a dedicated wordlist (name stored in list_name below) 49*a1bf3f78SToomas Soome * that is searched in a special way by the prefix parse step. When a prefix 50*a1bf3f78SToomas Soome * matches the beginning of an incoming token, push the non-prefix part of the 51*a1bf3f78SToomas Soome * token back onto the input stream and execute the prefix code. 52*a1bf3f78SToomas Soome * 53*a1bf3f78SToomas Soome * The parse step is called ficlParsePrefix. 54*a1bf3f78SToomas Soome * Storing prefix entries in the dictionary greatly simplifies 55*a1bf3f78SToomas Soome * the process of matching and dispatching prefixes, avoids the 56*a1bf3f78SToomas Soome * need to clean up a dynamically allocated prefix list when the system 57*a1bf3f78SToomas Soome * goes away, but still allows prefixes to be allocated at runtime. 58*a1bf3f78SToomas Soome */ 59*a1bf3f78SToomas Soome 60*a1bf3f78SToomas Soome static char list_name[] = "<prefixes>"; 61*a1bf3f78SToomas Soome 62*a1bf3f78SToomas Soome /* 63*a1bf3f78SToomas Soome * f i c l P a r s e P r e f i x 64*a1bf3f78SToomas Soome * This is the parse step for prefixes - it checks an incoming word 65*a1bf3f78SToomas Soome * to see if it starts with a prefix, and if so runs the corresponding 66*a1bf3f78SToomas Soome * code against the remainder of the word and returns true. 67*a1bf3f78SToomas Soome */ 68*a1bf3f78SToomas Soome int 69*a1bf3f78SToomas Soome ficlVmParsePrefix(ficlVm *vm, ficlString s) 70*a1bf3f78SToomas Soome { 71*a1bf3f78SToomas Soome int i; 72*a1bf3f78SToomas Soome ficlHash *hash; 73*a1bf3f78SToomas Soome ficlWord *word = ficlSystemLookup(vm->callback.system, list_name); 74*a1bf3f78SToomas Soome 75*a1bf3f78SToomas Soome /* 76*a1bf3f78SToomas Soome * Make sure we found the prefix dictionary - otherwise silently fail 77*a1bf3f78SToomas Soome * If forth-wordlist is not in the search order, we won't find the 78*a1bf3f78SToomas Soome * prefixes. 79*a1bf3f78SToomas Soome */ 80*a1bf3f78SToomas Soome if (!word) 81*a1bf3f78SToomas Soome return (0); /* false */ 82*a1bf3f78SToomas Soome 83*a1bf3f78SToomas Soome hash = (ficlHash *)(word->param[0].p); 84*a1bf3f78SToomas Soome /* 85*a1bf3f78SToomas Soome * Walk the list looking for a match with the beginning of the 86*a1bf3f78SToomas Soome * incoming token 87*a1bf3f78SToomas Soome */ 88*a1bf3f78SToomas Soome for (i = 0; i < (int)hash->size; i++) { 89*a1bf3f78SToomas Soome word = hash->table[i]; 90*a1bf3f78SToomas Soome while (word != NULL) { 91*a1bf3f78SToomas Soome int n; 92*a1bf3f78SToomas Soome n = word->length; 93*a1bf3f78SToomas Soome /* 94*a1bf3f78SToomas Soome * If we find a match, adjust the TIB to give back 95*a1bf3f78SToomas Soome * the non-prefix characters and execute the prefix 96*a1bf3f78SToomas Soome * word. 97*a1bf3f78SToomas Soome */ 98*a1bf3f78SToomas Soome if (!ficlStrincmp(FICL_STRING_GET_POINTER(s), 99*a1bf3f78SToomas Soome word->name, (ficlUnsigned)n)) { 100*a1bf3f78SToomas Soome /* 101*a1bf3f78SToomas Soome * (sadler) fixed off-by-one error when the 102*a1bf3f78SToomas Soome * token has no trailing space in the TIB 103*a1bf3f78SToomas Soome */ 104*a1bf3f78SToomas Soome ficlVmSetTibIndex(vm, 105*a1bf3f78SToomas Soome s.text + n - vm->tib.text); 106*a1bf3f78SToomas Soome ficlVmExecuteWord(vm, word); 107*a1bf3f78SToomas Soome 108*a1bf3f78SToomas Soome return (1); /* true */ 109*a1bf3f78SToomas Soome } 110*a1bf3f78SToomas Soome word = word->link; 111*a1bf3f78SToomas Soome } 112*a1bf3f78SToomas Soome } 113*a1bf3f78SToomas Soome 114*a1bf3f78SToomas Soome return (0); /* false */ 115*a1bf3f78SToomas Soome } 116*a1bf3f78SToomas Soome 117*a1bf3f78SToomas Soome static void 118*a1bf3f78SToomas Soome ficlPrimitiveTempBase(ficlVm *vm) 119*a1bf3f78SToomas Soome { 120*a1bf3f78SToomas Soome int oldbase = vm->base; 121*a1bf3f78SToomas Soome ficlString number = ficlVmGetWord0(vm); 122*a1bf3f78SToomas Soome int base = ficlStackPopInteger(vm->dataStack); 123*a1bf3f78SToomas Soome 124*a1bf3f78SToomas Soome vm->base = base; 125*a1bf3f78SToomas Soome if (!ficlVmParseNumber(vm, number)) 126*a1bf3f78SToomas Soome ficlVmThrowError(vm, "%.*s not recognized", 127*a1bf3f78SToomas Soome FICL_STRING_GET_LENGTH(number), 128*a1bf3f78SToomas Soome FICL_STRING_GET_POINTER(number)); 129*a1bf3f78SToomas Soome 130*a1bf3f78SToomas Soome vm->base = oldbase; 131*a1bf3f78SToomas Soome } 132*a1bf3f78SToomas Soome 133*a1bf3f78SToomas Soome /* 134*a1bf3f78SToomas Soome * f i c l C o m p i l e P r e f i x 135*a1bf3f78SToomas Soome * Build prefix support into the dictionary and the parser 136*a1bf3f78SToomas Soome * Note: since prefixes always execute, they are effectively IMMEDIATE. 137*a1bf3f78SToomas Soome * If they need to generate code in compile state you must add 138*a1bf3f78SToomas Soome * this code explicitly. 139*a1bf3f78SToomas Soome */ 140*a1bf3f78SToomas Soome void 141*a1bf3f78SToomas Soome ficlSystemCompilePrefix(ficlSystem *system) 142*a1bf3f78SToomas Soome { 143*a1bf3f78SToomas Soome ficlDictionary *dictionary = system->dictionary; 144*a1bf3f78SToomas Soome ficlHash *hash; 145*a1bf3f78SToomas Soome 146*a1bf3f78SToomas Soome /* 147*a1bf3f78SToomas Soome * Create a named wordlist for prefixes to reside in... 148*a1bf3f78SToomas Soome * Since we're doing a special kind of search, make it 149*a1bf3f78SToomas Soome * a single bucket hashtable - hashing does not help here. 150*a1bf3f78SToomas Soome */ 151*a1bf3f78SToomas Soome hash = ficlDictionaryCreateWordlist(dictionary, 1); 152*a1bf3f78SToomas Soome hash->name = list_name; 153*a1bf3f78SToomas Soome ficlDictionaryAppendConstantPointer(dictionary, list_name, hash); 154*a1bf3f78SToomas Soome 155*a1bf3f78SToomas Soome /* 156*a1bf3f78SToomas Soome * Put __tempbase in the forth-wordlist 157*a1bf3f78SToomas Soome */ 158*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(dictionary, "__tempbase", 159*a1bf3f78SToomas Soome ficlPrimitiveTempBase, FICL_WORD_DEFAULT); 160*a1bf3f78SToomas Soome 161*a1bf3f78SToomas Soome /* 162*a1bf3f78SToomas Soome * If you want to add some prefixes at compilation-time, copy this 163*a1bf3f78SToomas Soome * line to the top of this function: 164*a1bf3f78SToomas Soome * 165*a1bf3f78SToomas Soome * ficlHash *oldCompilationWordlist; 166*a1bf3f78SToomas Soome * 167*a1bf3f78SToomas Soome * then copy this code to the bottom, just above the return: 168*a1bf3f78SToomas Soome * 169*a1bf3f78SToomas Soome * 170*a1bf3f78SToomas Soome * oldCompilationWordlist = dictionary->compilationWordlist; 171*a1bf3f78SToomas Soome * dictionary->compilationWordlist = hash; 172*a1bf3f78SToomas Soome * ficlDictionarySetPrimitive(dictionary, YOUR WORD HERE, 173*a1bf3f78SToomas Soome * FICL_WORD_DEFAULT); 174*a1bf3f78SToomas Soome * dictionary->compilationWordlist = oldCompilationWordlist; 175*a1bf3f78SToomas Soome * 176*a1bf3f78SToomas Soome * and substitute in your own actual calls to 177*a1bf3f78SToomas Soome * ficlDictionarySetPrimitive() as needed. 178*a1bf3f78SToomas Soome * 179*a1bf3f78SToomas Soome * Or--better yet--do it in your own code, so you don't have 180*a1bf3f78SToomas Soome * to re-modify the Ficl source code every time we cut a new release! 181*a1bf3f78SToomas Soome */ 182*a1bf3f78SToomas Soome } 183