/*******************************************************************1** s e a r c h . c2** Forth Inspired Command Language3** ANS Forth SEARCH and SEARCH-EXT word-set written in C4** Author: John Sadler ([email protected])5** Created: 6 June 20006** $Id: search.c,v 1.9 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 "ficl.h"46#include "math64.h"4748/**************************************************************************49d e f i n i t i o n s50** SEARCH ( -- )51** Make the compilation word list the same as the first word list in the52** search order. Specifies that the names of subsequent definitions will53** be placed in the compilation word list. Subsequent changes in the search54** order will not affect the compilation word list.55**************************************************************************/56static void definitions(FICL_VM *pVM)57{58FICL_DICT *pDict = vmGetDict(pVM);5960assert(pDict);61if (pDict->nLists < 1)62{63vmThrowErr(pVM, "DEFINITIONS error - empty search order");64}6566pDict->pCompile = pDict->pSearch[pDict->nLists-1];67return;68}697071/**************************************************************************72f o r t h - w o r d l i s t73** SEARCH ( -- wid )74** Return wid, the identifier of the word list that includes all standard75** words provided by the implementation. This word list is initially the76** compilation word list and is part of the initial search order.77**************************************************************************/78static void forthWordlist(FICL_VM *pVM)79{80FICL_HASH *pHash = vmGetDict(pVM)->pForthWords;81stackPushPtr(pVM->pStack, pHash);82return;83}848586/**************************************************************************87g e t - c u r r e n t88** SEARCH ( -- wid )89** Return wid, the identifier of the compilation word list.90**************************************************************************/91static void getCurrent(FICL_VM *pVM)92{93ficlLockDictionary(TRUE);94stackPushPtr(pVM->pStack, vmGetDict(pVM)->pCompile);95ficlLockDictionary(FALSE);96return;97}9899100/**************************************************************************101g e t - o r d e r102** SEARCH ( -- widn ... wid1 n )103** Returns the number of word lists n in the search order and the word list104** identifiers widn ... wid1 identifying these word lists. wid1 identifies105** the word list that is searched first, and widn the word list that is106** searched last. The search order is unaffected.107**************************************************************************/108static void getOrder(FICL_VM *pVM)109{110FICL_DICT *pDict = vmGetDict(pVM);111int nLists = pDict->nLists;112int i;113114ficlLockDictionary(TRUE);115for (i = 0; i < nLists; i++)116{117stackPushPtr(pVM->pStack, pDict->pSearch[i]);118}119120stackPushUNS(pVM->pStack, nLists);121ficlLockDictionary(FALSE);122return;123}124125126/**************************************************************************127s e a r c h - w o r d l i s t128** SEARCH ( c-addr u wid -- 0 | xt 1 | xt -1 )129** Find the definition identified by the string c-addr u in the word list130** identified by wid. If the definition is not found, return zero. If the131** definition is found, return its execution token xt and one (1) if the132** definition is immediate, minus-one (-1) otherwise.133**************************************************************************/134static void searchWordlist(FICL_VM *pVM)135{136STRINGINFO si;137UNS16 hashCode;138FICL_WORD *pFW;139FICL_HASH *pHash = stackPopPtr(pVM->pStack);140141si.count = (FICL_COUNT)stackPopUNS(pVM->pStack);142si.cp = stackPopPtr(pVM->pStack);143hashCode = hashHashCode(si);144145ficlLockDictionary(TRUE);146pFW = hashLookup(pHash, si, hashCode);147ficlLockDictionary(FALSE);148149if (pFW)150{151stackPushPtr(pVM->pStack, pFW);152stackPushINT(pVM->pStack, (wordIsImmediate(pFW) ? 1 : -1));153}154else155{156stackPushUNS(pVM->pStack, 0);157}158159return;160}161162163/**************************************************************************164s e t - c u r r e n t165** SEARCH ( wid -- )166** Set the compilation word list to the word list identified by wid.167**************************************************************************/168static void setCurrent(FICL_VM *pVM)169{170FICL_HASH *pHash = stackPopPtr(pVM->pStack);171FICL_DICT *pDict = vmGetDict(pVM);172ficlLockDictionary(TRUE);173pDict->pCompile = pHash;174ficlLockDictionary(FALSE);175return;176}177178179/**************************************************************************180s e t - o r d e r181** SEARCH ( widn ... wid1 n -- )182** Set the search order to the word lists identified by widn ... wid1.183** Subsequently, word list wid1 will be searched first, and word list184** widn searched last. If n is zero, empty the search order. If n is minus185** one, set the search order to the implementation-defined minimum186** search order. The minimum search order shall include the words187** FORTH-WORDLIST and SET-ORDER. A system shall allow n to188** be at least eight.189**************************************************************************/190static void setOrder(FICL_VM *pVM)191{192int i;193int nLists = stackPopINT(pVM->pStack);194FICL_DICT *dp = vmGetDict(pVM);195196if (nLists > FICL_DEFAULT_VOCS)197{198vmThrowErr(pVM, "set-order error: list would be too large");199}200201ficlLockDictionary(TRUE);202203if (nLists >= 0)204{205dp->nLists = nLists;206for (i = nLists-1; i >= 0; --i)207{208dp->pSearch[i] = stackPopPtr(pVM->pStack);209}210}211else212{213dictResetSearchOrder(dp);214}215216ficlLockDictionary(FALSE);217return;218}219220221/**************************************************************************222f i c l - w o r d l i s t223** SEARCH ( -- wid )224** Create a new empty word list, returning its word list identifier wid.225** The new word list may be returned from a pool of preallocated word226** lists or may be dynamically allocated in data space. A system shall227** allow the creation of at least 8 new word lists in addition to any228** provided as part of the system.229** Notes:230** 1. ficl creates a new single-list hash in the dictionary and returns231** its address.232** 2. ficl-wordlist takes an arg off the stack indicating the number of233** hash entries in the wordlist. Ficl 2.02 and later define WORDLIST as234** : wordlist 1 ficl-wordlist ;235**************************************************************************/236static void ficlWordlist(FICL_VM *pVM)237{238FICL_DICT *dp = vmGetDict(pVM);239FICL_HASH *pHash;240FICL_UNS nBuckets;241242#if FICL_ROBUST > 1243vmCheckStack(pVM, 1, 1);244#endif245nBuckets = stackPopUNS(pVM->pStack);246pHash = dictCreateWordlist(dp, nBuckets);247stackPushPtr(pVM->pStack, pHash);248return;249}250251252/**************************************************************************253S E A R C H >254** ficl ( -- wid )255** Pop wid off the search order. Error if the search order is empty256**************************************************************************/257static void searchPop(FICL_VM *pVM)258{259FICL_DICT *dp = vmGetDict(pVM);260int nLists;261262ficlLockDictionary(TRUE);263nLists = dp->nLists;264if (nLists == 0)265{266vmThrowErr(pVM, "search> error: empty search order");267}268stackPushPtr(pVM->pStack, dp->pSearch[--dp->nLists]);269ficlLockDictionary(FALSE);270return;271}272273274/**************************************************************************275> S E A R C H276** ficl ( wid -- )277** Push wid onto the search order. Error if the search order is full.278**************************************************************************/279static void searchPush(FICL_VM *pVM)280{281FICL_DICT *dp = vmGetDict(pVM);282283ficlLockDictionary(TRUE);284if (dp->nLists > FICL_DEFAULT_VOCS)285{286vmThrowErr(pVM, ">search error: search order overflow");287}288dp->pSearch[dp->nLists++] = stackPopPtr(pVM->pStack);289ficlLockDictionary(FALSE);290return;291}292293294/**************************************************************************295W I D - G E T - N A M E296** ficl ( wid -- c-addr u )297** Get wid's (optional) name and push onto stack as a counted string298**************************************************************************/299static void widGetName(FICL_VM *pVM)300{301FICL_HASH *pHash = vmPop(pVM).p;302char *cp = pHash->name;303FICL_INT len = 0;304305if (cp)306len = strlen(cp);307308vmPush(pVM, LVALUEtoCELL(cp));309vmPush(pVM, LVALUEtoCELL(len));310return;311}312313/**************************************************************************314W I D - S E T - N A M E315** ficl ( wid c-addr -- )316** Set wid's name pointer to the \0 terminated string address supplied317**************************************************************************/318static void widSetName(FICL_VM *pVM)319{320char *cp = (char *)vmPop(pVM).p;321FICL_HASH *pHash = vmPop(pVM).p;322pHash->name = cp;323return;324}325326327/**************************************************************************328setParentWid329** FICL330** setparentwid ( parent-wid wid -- )331** Set WID's link field to the parent-wid. search-wordlist will332** iterate through all the links when finding words in the child wid.333**************************************************************************/334static void setParentWid(FICL_VM *pVM)335{336FICL_HASH *parent, *child;337#if FICL_ROBUST > 1338vmCheckStack(pVM, 2, 0);339#endif340child = (FICL_HASH *)stackPopPtr(pVM->pStack);341parent = (FICL_HASH *)stackPopPtr(pVM->pStack);342343child->link = parent;344return;345}346347348/**************************************************************************349f i c l C o m p i l e S e a r c h350** Builds the primitive wordset and the environment-query namespace.351**************************************************************************/352353void ficlCompileSearch(FICL_SYSTEM *pSys)354{355FICL_DICT *dp = pSys->dp;356assert (dp);357358/*359** optional SEARCH-ORDER word set360*/361dictAppendWord(dp, ">search", searchPush, FW_DEFAULT);362dictAppendWord(dp, "search>", searchPop, FW_DEFAULT);363dictAppendWord(dp, "definitions",364definitions, FW_DEFAULT);365dictAppendWord(dp, "forth-wordlist",366forthWordlist, FW_DEFAULT);367dictAppendWord(dp, "get-current",368getCurrent, FW_DEFAULT);369dictAppendWord(dp, "get-order", getOrder, FW_DEFAULT);370dictAppendWord(dp, "search-wordlist",371searchWordlist, FW_DEFAULT);372dictAppendWord(dp, "set-current",373setCurrent, FW_DEFAULT);374dictAppendWord(dp, "set-order", setOrder, FW_DEFAULT);375dictAppendWord(dp, "ficl-wordlist",376ficlWordlist, FW_DEFAULT);377378/*379** Set SEARCH environment query values380*/381ficlSetEnv(pSys, "search-order", FICL_TRUE);382ficlSetEnv(pSys, "search-order-ext", FICL_TRUE);383ficlSetEnv(pSys, "wordlists", FICL_DEFAULT_VOCS);384385dictAppendWord(dp, "wid-get-name", widGetName, FW_DEFAULT);386dictAppendWord(dp, "wid-set-name", widSetName, FW_DEFAULT);387dictAppendWord(dp, "wid-set-super",388setParentWid, FW_DEFAULT);389return;390}391392393394