/*******************************************************************1** p r e f i x . c2** Forth Inspired Command Language3** Parser extensions for Ficl4** Authors: Larry Hastings & John Sadler ([email protected])5** Created: April 20016** $Id: prefix.c,v 1.6 2001/12/05 07:21:34 jsadler Exp $7*******************************************************************/8/*9** Copyright (c) 1997-2001 John Sadler ([email protected])10** All rights reserved.11**12** Get the latest Ficl release at http://ficl.sourceforge.net13**14** I am interested in hearing from anyone who uses ficl. If you have15** a problem, a success story, a defect, an enhancement request, or16** if you would like to contribute to the ficl release, please17** contact me by email at the address above.18**19** L I C E N S E and D I S C L A I M E R20**21** Redistribution and use in source and binary forms, with or without22** modification, are permitted provided that the following conditions23** are met:24** 1. Redistributions of source code must retain the above copyright25** notice, this list of conditions and the following disclaimer.26** 2. Redistributions in binary form must reproduce the above copyright27** notice, this list of conditions and the following disclaimer in the28** documentation and/or other materials provided with the distribution.29**30** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND31** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE32** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE33** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE34** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL35** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS36** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)37** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT38** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY39** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF40** SUCH DAMAGE.41*/424344#include <string.h>45#include <ctype.h>46#include "ficl.h"47#include "math64.h"4849/*50** (jws) revisions:51** A prefix is a word in a dedicated wordlist (name stored in list_name below)52** that is searched in a special way by the prefix parse step. When a prefix53** matches the beginning of an incoming token, push the non-prefix part of the54** token back onto the input stream and execute the prefix code.55**56** The parse step is called ficlParsePrefix.57** Storing prefix entries in the dictionary greatly simplifies58** the process of matching and dispatching prefixes, avoids the59** need to clean up a dynamically allocated prefix list when the system60** goes away, but still allows prefixes to be allocated at runtime.61*/6263static char list_name[] = "<prefixes>";6465/**************************************************************************66f i c l P a r s e P r e f i x67** This is the parse step for prefixes - it checks an incoming word68** to see if it starts with a prefix, and if so runs the corrseponding69** code against the remainder of the word and returns true.70**************************************************************************/71int ficlParsePrefix(FICL_VM *pVM, STRINGINFO si)72{73int i;74FICL_HASH *pHash;75FICL_WORD *pFW = ficlLookup(pVM->pSys, list_name);7677/*78** Make sure we found the prefix dictionary - otherwise silently fail79** If forth-wordlist is not in the search order, we won't find the prefixes.80*/81if (!pFW)82return FICL_FALSE;8384pHash = (FICL_HASH *)(pFW->param[0].p);85/*86** Walk the list looking for a match with the beginning of the incoming token87*/88for (i = 0; i < (int)pHash->size; i++)89{90pFW = pHash->table[i];91while (pFW != NULL)92{93int n;94n = pFW->nName;95/*96** If we find a match, adjust the TIB to give back the non-prefix characters97** and execute the prefix word.98*/99if (!strincmp(SI_PTR(si), pFW->name, (FICL_UNS)n))100{101/* (sadler) fixed off-by-one error when the token has no trailing space in the TIB */102vmSetTibIndex(pVM, si.cp + n - pVM->tib.cp );103vmExecute(pVM, pFW);104105return (int)FICL_TRUE;106}107pFW = pFW->link;108}109}110111return FICL_FALSE;112}113114115static void tempBase(FICL_VM *pVM, int base)116{117int oldbase = pVM->base;118STRINGINFO si = vmGetWord0(pVM);119120pVM->base = base;121if (!ficlParseNumber(pVM, si))122{123int i = SI_COUNT(si);124vmThrowErr(pVM, "%.*s not recognized", i, SI_PTR(si));125}126127pVM->base = oldbase;128return;129}130131static void fTempBase(FICL_VM *pVM)132{133int base = stackPopINT(pVM->pStack);134tempBase(pVM, base);135return;136}137138static void prefixHex(FICL_VM *pVM)139{140tempBase(pVM, 16);141}142143static void prefixTen(FICL_VM *pVM)144{145tempBase(pVM, 10);146}147148149/**************************************************************************150f i c l C o m p i l e P r e f i x151** Build prefix support into the dictionary and the parser152** Note: since prefixes always execute, they are effectively IMMEDIATE.153** If they need to generate code in compile state you must add154** this code explicitly.155**************************************************************************/156void ficlCompilePrefix(FICL_SYSTEM *pSys)157{158FICL_DICT *dp = pSys->dp;159FICL_HASH *pHash;160FICL_HASH *pPrevCompile = dp->pCompile;161#if (FICL_EXTENDED_PREFIX)162FICL_WORD *pFW;163#endif164165/*166** Create a named wordlist for prefixes to reside in...167** Since we're doing a special kind of search, make it168** a single bucket hashtable - hashing does not help here.169*/170pHash = dictCreateWordlist(dp, 1);171pHash->name = list_name;172dictAppendWord(dp, list_name, constantParen, FW_DEFAULT);173dictAppendCell(dp, LVALUEtoCELL(pHash));174175/*176** Put __tempbase in the forth-wordlist177*/178dictAppendWord(dp, "__tempbase", fTempBase, FW_DEFAULT);179180/*181** Temporarily make the prefix list the compile wordlist so that182** we can create some precompiled prefixes.183*/184dp->pCompile = pHash;185dictAppendWord(dp, "0x", prefixHex, FW_DEFAULT);186dictAppendWord(dp, "0d", prefixTen, FW_DEFAULT);187#if (FICL_EXTENDED_PREFIX)188pFW = ficlLookup(pSys, "\\");189if (pFW)190{191dictAppendWord(dp, "//", pFW->code, FW_DEFAULT);192}193#endif194dp->pCompile = pPrevCompile;195196return;197}198199200