prefix.c revision 76116
1/******************************************************************* 2** p r e f i x . c 3** Forth Inspired Command Language 4** Parser extensions for Ficl 5** Authors: Larry Hastings & John Sadler (john_sadler@alum.mit.edu) 6** Created: April 2001 7** $Id: prefix.c,v 1.1 2001-04-26 21:41:33-07 jsadler Exp jsadler $ 8*******************************************************************/ 9/* 10** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) 11** All rights reserved. 12** 13** Get the latest Ficl release at http://ficl.sourceforge.net 14** 15** L I C E N S E and D I S C L A I M E R 16** 17** Redistribution and use in source and binary forms, with or without 18** modification, are permitted provided that the following conditions 19** are met: 20** 1. Redistributions of source code must retain the above copyright 21** notice, this list of conditions and the following disclaimer. 22** 2. Redistributions in binary form must reproduce the above copyright 23** notice, this list of conditions and the following disclaimer in the 24** documentation and/or other materials provided with the distribution. 25** 26** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 27** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 30** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36** SUCH DAMAGE. 37** 38** I am interested in hearing from anyone who uses ficl. If you have 39** a problem, a success story, a defect, an enhancement request, or 40** if you would like to contribute to the ficl release, please send 41** contact me by email at the address above. 42** 43** $Id: prefix.c,v 1.1 2001-04-26 21:41:33-07 jsadler Exp jsadler $ 44*/ 45 46/* $FreeBSD: head/sys/boot/ficl/prefix.c 76116 2001-04-29 02:36:36Z dcs $ */ 47 48#include <string.h> 49#include <ctype.h> 50#include "ficl.h" 51#include "math64.h" 52 53/* 54** (jws) revisions: 55** A prefix is a word in a dedicated wordlist (name stored in list_name below) 56** that is searched in a special way by the prefix parse step. When a prefix 57** matches the beginning of an incoming token, push the non-prefix part of the 58** token back onto the input stream and execute the prefix code. 59** 60** The parse step is called ficlParsePrefix. 61** Storing prefix entries in the dictionary greatly simplifies 62** the process of matching and dispatching prefixes, avoids the 63** need to clean up a dynamically allocated prefix list when the system 64** goes away, but still allows prefixes to be allocated at runtime. 65*/ 66 67static char list_name[] = "<prefixes>"; 68 69/************************************************************************** 70 f i c l P a r s e P r e f i x 71** This is the parse step for prefixes - it checks an incoming word 72** to see if it starts with a prefix, and if so runs the corrseponding 73** code against the remainder of the word and returns true. 74**************************************************************************/ 75int ficlParsePrefix(FICL_VM *pVM, STRINGINFO si) 76{ 77 int i; 78 FICL_HASH *pHash; 79 FICL_WORD *pFW = ficlLookup(list_name); 80 81 assert(pFW); 82 pHash = (FICL_HASH *)(pFW->param[0].p); 83 /* 84 ** Walk the list looking for a match with the beginning of the incoming token 85 */ 86 for (i = 0; i < (int)pHash->size; i++) 87 { 88 pFW = pHash->table[i]; 89 while (pFW != NULL) 90 { 91 int n; 92 n = pFW->nName; 93 /* 94 ** If we find a match, adjust the TIB to give back the non-prefix characters 95 ** and execute the prefix word. 96 */ 97 if (!strincmp(SI_PTR(si), pFW->name, (FICL_UNS)n)) 98 { 99 vmSetTibIndex(pVM, vmGetTibIndex(pVM) - 1 - SI_COUNT(si) + n); 100 vmExecute(pVM, pFW); 101 102 return FICL_TRUE; 103 } 104 pFW = pFW->link; 105 } 106 } 107 108 return FICL_FALSE; 109} 110 111 112static void tempBase(FICL_VM *pVM, int base) 113{ 114 int oldbase = pVM->base; 115 STRINGINFO si = vmGetWord0(pVM); 116 117 pVM->base = base; 118 if (!ficlParseNumber(pVM, si)) 119 { 120 int i = SI_COUNT(si); 121 vmThrowErr(pVM, "0x%.*s is not a valid hex value", i, SI_PTR(si)); 122 } 123 124 pVM->base = oldbase; 125 return; 126} 127 128static void fTempBase(FICL_VM *pVM) 129{ 130 int base = stackPopINT(pVM->pStack); 131 tempBase(pVM, base); 132 return; 133} 134 135static void prefixHex(FICL_VM *pVM) 136{ 137 tempBase(pVM, 16); 138} 139 140static void prefixTen(FICL_VM *pVM) 141{ 142 tempBase(pVM, 10); 143} 144 145 146/************************************************************************** 147 f i c l C o m p i l e P r e f i x 148** Build prefix support into the dictionary and the parser 149** Note: since prefixes always execute, they are effectively IMMEDIATE. 150** If they need to generate code in compile state you must add 151** this code explicitly. 152**************************************************************************/ 153void ficlCompilePrefix(FICL_SYSTEM *pSys) 154{ 155 FICL_DICT *dp = pSys->dp; 156 FICL_HASH *pHash; 157 FICL_HASH *pPrevCompile = dp->pCompile; 158#if (FICL_EXTENDED_PREFIX) 159 FICL_WORD *pFW; 160#endif 161 162 /* 163 ** Create a named wordlist for prefixes to reside in... 164 ** Since we're doing a special kind of search, make it 165 ** a single bucket hashtable - hashing does not help here. 166 */ 167 pHash = dictCreateWordlist(dp, 1); 168 pHash->name = list_name; 169 dictAppendWord(dp, list_name, constantParen, FW_DEFAULT); 170 dictAppendCell(dp, LVALUEtoCELL(pHash)); 171 dictAppendWord(dp, "__tempbase", fTempBase, FW_DEFAULT); 172 173 /* 174 ** Temporarily make the prefix list the compile wordlist so that 175 ** we can create some precompiled prefixes. 176 */ 177 dp->pCompile = pHash; 178 dictAppendWord(dp, "0x", prefixHex, FW_DEFAULT); 179 dictAppendWord(dp, "0d", prefixTen, FW_DEFAULT); 180#if (FICL_EXTENDED_PREFIX) 181 pFW = ficlLookup("\\"); 182 if (pFW) 183 { 184 dictAppendWord(dp, "//", pFW->code, FW_DEFAULT); 185 } 186#endif 187 dp->pCompile = pPrevCompile; 188 189 ficlAddPrecompiledParseStep(pSys, "prefix?", ficlParsePrefix); 190 return; 191} 192