176116Sdcs/******************************************************************* 276116Sdcs** p r e f i x . c 376116Sdcs** Forth Inspired Command Language 476116Sdcs** Parser extensions for Ficl 576116Sdcs** Authors: Larry Hastings & John Sadler (john_sadler@alum.mit.edu) 676116Sdcs** Created: April 2001 794290Sdcs** $Id: prefix.c,v 1.6 2001/12/05 07:21:34 jsadler Exp $ 876116Sdcs*******************************************************************/ 976116Sdcs/* 1076116Sdcs** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu) 1176116Sdcs** All rights reserved. 1276116Sdcs** 1376116Sdcs** Get the latest Ficl release at http://ficl.sourceforge.net 1476116Sdcs** 1594290Sdcs** I am interested in hearing from anyone who uses ficl. If you have 1694290Sdcs** a problem, a success story, a defect, an enhancement request, or 1794290Sdcs** if you would like to contribute to the ficl release, please 1894290Sdcs** contact me by email at the address above. 1994290Sdcs** 2076116Sdcs** L I C E N S E and D I S C L A I M E R 2176116Sdcs** 2276116Sdcs** Redistribution and use in source and binary forms, with or without 2376116Sdcs** modification, are permitted provided that the following conditions 2476116Sdcs** are met: 2576116Sdcs** 1. Redistributions of source code must retain the above copyright 2676116Sdcs** notice, this list of conditions and the following disclaimer. 2776116Sdcs** 2. Redistributions in binary form must reproduce the above copyright 2876116Sdcs** notice, this list of conditions and the following disclaimer in the 2976116Sdcs** documentation and/or other materials provided with the distribution. 3076116Sdcs** 3176116Sdcs** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 3276116Sdcs** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3376116Sdcs** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3476116Sdcs** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 3576116Sdcs** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3676116Sdcs** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3776116Sdcs** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3876116Sdcs** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3976116Sdcs** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 4076116Sdcs** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 4176116Sdcs** SUCH DAMAGE. 4276116Sdcs*/ 4376116Sdcs 4476116Sdcs/* $FreeBSD$ */ 4576116Sdcs 4676116Sdcs#include <string.h> 4776116Sdcs#include <ctype.h> 4876116Sdcs#include "ficl.h" 4976116Sdcs#include "math64.h" 5076116Sdcs 5176116Sdcs/* 5276116Sdcs** (jws) revisions: 5376116Sdcs** A prefix is a word in a dedicated wordlist (name stored in list_name below) 5476116Sdcs** that is searched in a special way by the prefix parse step. When a prefix 5576116Sdcs** matches the beginning of an incoming token, push the non-prefix part of the 5676116Sdcs** token back onto the input stream and execute the prefix code. 5776116Sdcs** 5876116Sdcs** The parse step is called ficlParsePrefix. 5976116Sdcs** Storing prefix entries in the dictionary greatly simplifies 6076116Sdcs** the process of matching and dispatching prefixes, avoids the 6176116Sdcs** need to clean up a dynamically allocated prefix list when the system 6276116Sdcs** goes away, but still allows prefixes to be allocated at runtime. 6376116Sdcs*/ 6476116Sdcs 6576116Sdcsstatic char list_name[] = "<prefixes>"; 6676116Sdcs 6776116Sdcs/************************************************************************** 6876116Sdcs f i c l P a r s e P r e f i x 6976116Sdcs** This is the parse step for prefixes - it checks an incoming word 7076116Sdcs** to see if it starts with a prefix, and if so runs the corrseponding 7176116Sdcs** code against the remainder of the word and returns true. 7276116Sdcs**************************************************************************/ 7376116Sdcsint ficlParsePrefix(FICL_VM *pVM, STRINGINFO si) 7476116Sdcs{ 7576116Sdcs int i; 7676116Sdcs FICL_HASH *pHash; 7794290Sdcs FICL_WORD *pFW = ficlLookup(pVM->pSys, list_name); 7876116Sdcs 7994290Sdcs /* 8094290Sdcs ** Make sure we found the prefix dictionary - otherwise silently fail 8194290Sdcs ** If forth-wordlist is not in the search order, we won't find the prefixes. 8294290Sdcs */ 8394290Sdcs if (!pFW) 8494290Sdcs return FICL_FALSE; 8594290Sdcs 8676116Sdcs pHash = (FICL_HASH *)(pFW->param[0].p); 8776116Sdcs /* 8876116Sdcs ** Walk the list looking for a match with the beginning of the incoming token 8976116Sdcs */ 9076116Sdcs for (i = 0; i < (int)pHash->size; i++) 9176116Sdcs { 9276116Sdcs pFW = pHash->table[i]; 9376116Sdcs while (pFW != NULL) 9476116Sdcs { 9576116Sdcs int n; 9676116Sdcs n = pFW->nName; 9776116Sdcs /* 9876116Sdcs ** If we find a match, adjust the TIB to give back the non-prefix characters 9976116Sdcs ** and execute the prefix word. 10076116Sdcs */ 10176116Sdcs if (!strincmp(SI_PTR(si), pFW->name, (FICL_UNS)n)) 10276116Sdcs { 10394290Sdcs /* (sadler) fixed off-by-one error when the token has no trailing space in the TIB */ 10494290Sdcs vmSetTibIndex(pVM, si.cp + n - pVM->tib.cp ); 10576116Sdcs vmExecute(pVM, pFW); 10676116Sdcs 107102657Sscottl return (int)FICL_TRUE; 10876116Sdcs } 10976116Sdcs pFW = pFW->link; 11076116Sdcs } 11176116Sdcs } 11276116Sdcs 11376116Sdcs return FICL_FALSE; 11476116Sdcs} 11576116Sdcs 11676116Sdcs 11776116Sdcsstatic void tempBase(FICL_VM *pVM, int base) 11876116Sdcs{ 11976116Sdcs int oldbase = pVM->base; 12076116Sdcs STRINGINFO si = vmGetWord0(pVM); 12176116Sdcs 12276116Sdcs pVM->base = base; 12376116Sdcs if (!ficlParseNumber(pVM, si)) 12476116Sdcs { 12576116Sdcs int i = SI_COUNT(si); 12694290Sdcs vmThrowErr(pVM, "%.*s not recognized", i, SI_PTR(si)); 12776116Sdcs } 12876116Sdcs 12976116Sdcs pVM->base = oldbase; 13076116Sdcs return; 13176116Sdcs} 13276116Sdcs 13376116Sdcsstatic void fTempBase(FICL_VM *pVM) 13476116Sdcs{ 13576116Sdcs int base = stackPopINT(pVM->pStack); 13676116Sdcs tempBase(pVM, base); 13776116Sdcs return; 13876116Sdcs} 13976116Sdcs 14076116Sdcsstatic void prefixHex(FICL_VM *pVM) 14176116Sdcs{ 14276116Sdcs tempBase(pVM, 16); 14376116Sdcs} 14476116Sdcs 14576116Sdcsstatic void prefixTen(FICL_VM *pVM) 14676116Sdcs{ 14776116Sdcs tempBase(pVM, 10); 14876116Sdcs} 14976116Sdcs 15076116Sdcs 15176116Sdcs/************************************************************************** 15276116Sdcs f i c l C o m p i l e P r e f i x 15376116Sdcs** Build prefix support into the dictionary and the parser 15476116Sdcs** Note: since prefixes always execute, they are effectively IMMEDIATE. 15576116Sdcs** If they need to generate code in compile state you must add 15676116Sdcs** this code explicitly. 15776116Sdcs**************************************************************************/ 15876116Sdcsvoid ficlCompilePrefix(FICL_SYSTEM *pSys) 15976116Sdcs{ 16076116Sdcs FICL_DICT *dp = pSys->dp; 16176116Sdcs FICL_HASH *pHash; 16276116Sdcs FICL_HASH *pPrevCompile = dp->pCompile; 16376116Sdcs#if (FICL_EXTENDED_PREFIX) 16476116Sdcs FICL_WORD *pFW; 16576116Sdcs#endif 16676116Sdcs 16776116Sdcs /* 16876116Sdcs ** Create a named wordlist for prefixes to reside in... 16976116Sdcs ** Since we're doing a special kind of search, make it 17076116Sdcs ** a single bucket hashtable - hashing does not help here. 17176116Sdcs */ 17276116Sdcs pHash = dictCreateWordlist(dp, 1); 17376116Sdcs pHash->name = list_name; 17476116Sdcs dictAppendWord(dp, list_name, constantParen, FW_DEFAULT); 17576116Sdcs dictAppendCell(dp, LVALUEtoCELL(pHash)); 17694290Sdcs 17794290Sdcs /* 17894290Sdcs ** Put __tempbase in the forth-wordlist 17994290Sdcs */ 18076116Sdcs dictAppendWord(dp, "__tempbase", fTempBase, FW_DEFAULT); 18176116Sdcs 18276116Sdcs /* 18376116Sdcs ** Temporarily make the prefix list the compile wordlist so that 18476116Sdcs ** we can create some precompiled prefixes. 18576116Sdcs */ 18676116Sdcs dp->pCompile = pHash; 18776116Sdcs dictAppendWord(dp, "0x", prefixHex, FW_DEFAULT); 18876116Sdcs dictAppendWord(dp, "0d", prefixTen, FW_DEFAULT); 18976116Sdcs#if (FICL_EXTENDED_PREFIX) 19094290Sdcs pFW = ficlLookup(pSys, "\\"); 19176116Sdcs if (pFW) 19276116Sdcs { 19376116Sdcs dictAppendWord(dp, "//", pFW->code, FW_DEFAULT); 19476116Sdcs } 19576116Sdcs#endif 19676116Sdcs dp->pCompile = pPrevCompile; 19776116Sdcs 19876116Sdcs return; 19976116Sdcs} 200