diff options
Diffstat (limited to 'stand/ficl/prefix.c')
-rw-r--r-- | stand/ficl/prefix.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/stand/ficl/prefix.c b/stand/ficl/prefix.c new file mode 100644 index 0000000..a34fc6c --- /dev/null +++ b/stand/ficl/prefix.c @@ -0,0 +1,199 @@ +/******************************************************************* +** p r e f i x . c +** Forth Inspired Command Language +** Parser extensions for Ficl +** Authors: Larry Hastings & John Sadler (john_sadler@alum.mit.edu) +** Created: April 2001 +** $Id: prefix.c,v 1.6 2001/12/05 07:21:34 jsadler Exp $ +*******************************************************************/ +/* +** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) +** All rights reserved. +** +** Get the latest Ficl release at http://ficl.sourceforge.net +** +** I am interested in hearing from anyone who uses ficl. If you have +** a problem, a success story, a defect, an enhancement request, or +** if you would like to contribute to the ficl release, please +** contact me by email at the address above. +** +** L I C E N S E and D I S C L A I M E R +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +** SUCH DAMAGE. +*/ + +/* $FreeBSD$ */ + +#include <string.h> +#include <ctype.h> +#include "ficl.h" +#include "math64.h" + +/* +** (jws) revisions: +** A prefix is a word in a dedicated wordlist (name stored in list_name below) +** that is searched in a special way by the prefix parse step. When a prefix +** matches the beginning of an incoming token, push the non-prefix part of the +** token back onto the input stream and execute the prefix code. +** +** The parse step is called ficlParsePrefix. +** Storing prefix entries in the dictionary greatly simplifies +** the process of matching and dispatching prefixes, avoids the +** need to clean up a dynamically allocated prefix list when the system +** goes away, but still allows prefixes to be allocated at runtime. +*/ + +static char list_name[] = "<prefixes>"; + +/************************************************************************** + f i c l P a r s e P r e f i x +** This is the parse step for prefixes - it checks an incoming word +** to see if it starts with a prefix, and if so runs the corrseponding +** code against the remainder of the word and returns true. +**************************************************************************/ +int ficlParsePrefix(FICL_VM *pVM, STRINGINFO si) +{ + int i; + FICL_HASH *pHash; + FICL_WORD *pFW = ficlLookup(pVM->pSys, list_name); + + /* + ** Make sure we found the prefix dictionary - otherwise silently fail + ** If forth-wordlist is not in the search order, we won't find the prefixes. + */ + if (!pFW) + return FICL_FALSE; + + pHash = (FICL_HASH *)(pFW->param[0].p); + /* + ** Walk the list looking for a match with the beginning of the incoming token + */ + for (i = 0; i < (int)pHash->size; i++) + { + pFW = pHash->table[i]; + while (pFW != NULL) + { + int n; + n = pFW->nName; + /* + ** If we find a match, adjust the TIB to give back the non-prefix characters + ** and execute the prefix word. + */ + if (!strincmp(SI_PTR(si), pFW->name, (FICL_UNS)n)) + { + /* (sadler) fixed off-by-one error when the token has no trailing space in the TIB */ + vmSetTibIndex(pVM, si.cp + n - pVM->tib.cp ); + vmExecute(pVM, pFW); + + return (int)FICL_TRUE; + } + pFW = pFW->link; + } + } + + return FICL_FALSE; +} + + +static void tempBase(FICL_VM *pVM, int base) +{ + int oldbase = pVM->base; + STRINGINFO si = vmGetWord0(pVM); + + pVM->base = base; + if (!ficlParseNumber(pVM, si)) + { + int i = SI_COUNT(si); + vmThrowErr(pVM, "%.*s not recognized", i, SI_PTR(si)); + } + + pVM->base = oldbase; + return; +} + +static void fTempBase(FICL_VM *pVM) +{ + int base = stackPopINT(pVM->pStack); + tempBase(pVM, base); + return; +} + +static void prefixHex(FICL_VM *pVM) +{ + tempBase(pVM, 16); +} + +static void prefixTen(FICL_VM *pVM) +{ + tempBase(pVM, 10); +} + + +/************************************************************************** + f i c l C o m p i l e P r e f i x +** Build prefix support into the dictionary and the parser +** Note: since prefixes always execute, they are effectively IMMEDIATE. +** If they need to generate code in compile state you must add +** this code explicitly. +**************************************************************************/ +void ficlCompilePrefix(FICL_SYSTEM *pSys) +{ + FICL_DICT *dp = pSys->dp; + FICL_HASH *pHash; + FICL_HASH *pPrevCompile = dp->pCompile; +#if (FICL_EXTENDED_PREFIX) + FICL_WORD *pFW; +#endif + + /* + ** Create a named wordlist for prefixes to reside in... + ** Since we're doing a special kind of search, make it + ** a single bucket hashtable - hashing does not help here. + */ + pHash = dictCreateWordlist(dp, 1); + pHash->name = list_name; + dictAppendWord(dp, list_name, constantParen, FW_DEFAULT); + dictAppendCell(dp, LVALUEtoCELL(pHash)); + + /* + ** Put __tempbase in the forth-wordlist + */ + dictAppendWord(dp, "__tempbase", fTempBase, FW_DEFAULT); + + /* + ** Temporarily make the prefix list the compile wordlist so that + ** we can create some precompiled prefixes. + */ + dp->pCompile = pHash; + dictAppendWord(dp, "0x", prefixHex, FW_DEFAULT); + dictAppendWord(dp, "0d", prefixTen, FW_DEFAULT); +#if (FICL_EXTENDED_PREFIX) + pFW = ficlLookup(pSys, "\\"); + if (pFW) + { + dictAppendWord(dp, "//", pFW->code, FW_DEFAULT); + } +#endif + dp->pCompile = pPrevCompile; + + return; +} |