1 /*******************************************************************
3 ** Forth Inspired Command Language
4 ** ANS Forth SEARCH and SEARCH-EXT word-set written in C
5 ** Author: John Sadler (john_sadler@alum.mit.edu)
6 ** Created: 6 June 2000
7 ** $Id: search.c,v 1.9 2001/12/05 07:21:34 jsadler Exp $
8 *******************************************************************/
10 ** Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
11 ** All rights reserved.
13 ** Get the latest Ficl release at http://ficl.sourceforge.net
15 ** I am interested in hearing from anyone who uses ficl. If you have
16 ** a problem, a success story, a defect, an enhancement request, or
17 ** if you would like to contribute to the ficl release, please
18 ** contact me by email at the address above.
20 ** L I C E N S E and D I S C L A I M E R
22 ** Redistribution and use in source and binary forms, with or without
23 ** modification, are permitted provided that the following conditions
25 ** 1. Redistributions of source code must retain the above copyright
26 ** notice, this list of conditions and the following disclaimer.
27 ** 2. Redistributions in binary form must reproduce the above copyright
28 ** notice, this list of conditions and the following disclaimer in the
29 ** documentation and/or other materials provided with the distribution.
31 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
32 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
35 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 * $FreeBSD: src/sys/boot/ficl/search.c,v 1.2 2002/04/09 17:45:11 dcs Exp $
46 * $DragonFly: src/sys/boot/ficl/search.c,v 1.1 2003/11/10 06:08:33 dillon Exp $
53 /**************************************************************************
56 ** Make the compilation word list the same as the first word list in the
57 ** search order. Specifies that the names of subsequent definitions will
58 ** be placed in the compilation word list. Subsequent changes in the search
59 ** order will not affect the compilation word list.
60 **************************************************************************/
61 static void definitions(FICL_VM
*pVM
)
63 FICL_DICT
*pDict
= vmGetDict(pVM
);
66 if (pDict
->nLists
< 1)
68 vmThrowErr(pVM
, "DEFINITIONS error - empty search order");
71 pDict
->pCompile
= pDict
->pSearch
[pDict
->nLists
-1];
76 /**************************************************************************
77 f o r t h - w o r d l i s t
79 ** Return wid, the identifier of the word list that includes all standard
80 ** words provided by the implementation. This word list is initially the
81 ** compilation word list and is part of the initial search order.
82 **************************************************************************/
83 static void forthWordlist(FICL_VM
*pVM
)
85 FICL_HASH
*pHash
= vmGetDict(pVM
)->pForthWords
;
86 stackPushPtr(pVM
->pStack
, pHash
);
91 /**************************************************************************
94 ** Return wid, the identifier of the compilation word list.
95 **************************************************************************/
96 static void getCurrent(FICL_VM
*pVM
)
98 ficlLockDictionary(TRUE
);
99 stackPushPtr(pVM
->pStack
, vmGetDict(pVM
)->pCompile
);
100 ficlLockDictionary(FALSE
);
105 /**************************************************************************
107 ** SEARCH ( -- widn ... wid1 n )
108 ** Returns the number of word lists n in the search order and the word list
109 ** identifiers widn ... wid1 identifying these word lists. wid1 identifies
110 ** the word list that is searched first, and widn the word list that is
111 ** searched last. The search order is unaffected.
112 **************************************************************************/
113 static void getOrder(FICL_VM
*pVM
)
115 FICL_DICT
*pDict
= vmGetDict(pVM
);
116 int nLists
= pDict
->nLists
;
119 ficlLockDictionary(TRUE
);
120 for (i
= 0; i
< nLists
; i
++)
122 stackPushPtr(pVM
->pStack
, pDict
->pSearch
[i
]);
125 stackPushUNS(pVM
->pStack
, nLists
);
126 ficlLockDictionary(FALSE
);
131 /**************************************************************************
132 s e a r c h - w o r d l i s t
133 ** SEARCH ( c-addr u wid -- 0 | xt 1 | xt -1 )
134 ** Find the definition identified by the string c-addr u in the word list
135 ** identified by wid. If the definition is not found, return zero. If the
136 ** definition is found, return its execution token xt and one (1) if the
137 ** definition is immediate, minus-one (-1) otherwise.
138 **************************************************************************/
139 static void searchWordlist(FICL_VM
*pVM
)
144 FICL_HASH
*pHash
= stackPopPtr(pVM
->pStack
);
146 si
.count
= (FICL_COUNT
)stackPopUNS(pVM
->pStack
);
147 si
.cp
= stackPopPtr(pVM
->pStack
);
148 hashCode
= hashHashCode(si
);
150 ficlLockDictionary(TRUE
);
151 pFW
= hashLookup(pHash
, si
, hashCode
);
152 ficlLockDictionary(FALSE
);
156 stackPushPtr(pVM
->pStack
, pFW
);
157 stackPushINT(pVM
->pStack
, (wordIsImmediate(pFW
) ? 1 : -1));
161 stackPushUNS(pVM
->pStack
, 0);
168 /**************************************************************************
169 s e t - c u r r e n t
171 ** Set the compilation word list to the word list identified by wid.
172 **************************************************************************/
173 static void setCurrent(FICL_VM
*pVM
)
175 FICL_HASH
*pHash
= stackPopPtr(pVM
->pStack
);
176 FICL_DICT
*pDict
= vmGetDict(pVM
);
177 ficlLockDictionary(TRUE
);
178 pDict
->pCompile
= pHash
;
179 ficlLockDictionary(FALSE
);
184 /**************************************************************************
186 ** SEARCH ( widn ... wid1 n -- )
187 ** Set the search order to the word lists identified by widn ... wid1.
188 ** Subsequently, word list wid1 will be searched first, and word list
189 ** widn searched last. If n is zero, empty the search order. If n is minus
190 ** one, set the search order to the implementation-defined minimum
191 ** search order. The minimum search order shall include the words
192 ** FORTH-WORDLIST and SET-ORDER. A system shall allow n to
193 ** be at least eight.
194 **************************************************************************/
195 static void setOrder(FICL_VM
*pVM
)
198 int nLists
= stackPopINT(pVM
->pStack
);
199 FICL_DICT
*dp
= vmGetDict(pVM
);
201 if (nLists
> FICL_DEFAULT_VOCS
)
203 vmThrowErr(pVM
, "set-order error: list would be too large");
206 ficlLockDictionary(TRUE
);
211 for (i
= nLists
-1; i
>= 0; --i
)
213 dp
->pSearch
[i
] = stackPopPtr(pVM
->pStack
);
218 dictResetSearchOrder(dp
);
221 ficlLockDictionary(FALSE
);
226 /**************************************************************************
227 f i c l - w o r d l i s t
229 ** Create a new empty word list, returning its word list identifier wid.
230 ** The new word list may be returned from a pool of preallocated word
231 ** lists or may be dynamically allocated in data space. A system shall
232 ** allow the creation of at least 8 new word lists in addition to any
233 ** provided as part of the system.
235 ** 1. ficl creates a new single-list hash in the dictionary and returns
237 ** 2. ficl-wordlist takes an arg off the stack indicating the number of
238 ** hash entries in the wordlist. Ficl 2.02 and later define WORDLIST as
239 ** : wordlist 1 ficl-wordlist ;
240 **************************************************************************/
241 static void ficlWordlist(FICL_VM
*pVM
)
243 FICL_DICT
*dp
= vmGetDict(pVM
);
248 vmCheckStack(pVM
, 1, 1);
250 nBuckets
= stackPopUNS(pVM
->pStack
);
251 pHash
= dictCreateWordlist(dp
, nBuckets
);
252 stackPushPtr(pVM
->pStack
, pHash
);
257 /**************************************************************************
260 ** Pop wid off the search order. Error if the search order is empty
261 **************************************************************************/
262 static void searchPop(FICL_VM
*pVM
)
264 FICL_DICT
*dp
= vmGetDict(pVM
);
267 ficlLockDictionary(TRUE
);
271 vmThrowErr(pVM
, "search> error: empty search order");
273 stackPushPtr(pVM
->pStack
, dp
->pSearch
[--dp
->nLists
]);
274 ficlLockDictionary(FALSE
);
279 /**************************************************************************
282 ** Push wid onto the search order. Error if the search order is full.
283 **************************************************************************/
284 static void searchPush(FICL_VM
*pVM
)
286 FICL_DICT
*dp
= vmGetDict(pVM
);
288 ficlLockDictionary(TRUE
);
289 if (dp
->nLists
> FICL_DEFAULT_VOCS
)
291 vmThrowErr(pVM
, ">search error: search order overflow");
293 dp
->pSearch
[dp
->nLists
++] = stackPopPtr(pVM
->pStack
);
294 ficlLockDictionary(FALSE
);
299 /**************************************************************************
300 W I D - G E T - N A M E
301 ** ficl ( wid -- c-addr u )
302 ** Get wid's (optional) name and push onto stack as a counted string
303 **************************************************************************/
304 static void widGetName(FICL_VM
*pVM
)
306 FICL_HASH
*pHash
= vmPop(pVM
).p
;
307 char *cp
= pHash
->name
;
313 vmPush(pVM
, LVALUEtoCELL(cp
));
314 vmPush(pVM
, LVALUEtoCELL(len
));
318 /**************************************************************************
319 W I D - S E T - N A M E
320 ** ficl ( wid c-addr -- )
321 ** Set wid's name pointer to the \0 terminated string address supplied
322 **************************************************************************/
323 static void widSetName(FICL_VM
*pVM
)
325 char *cp
= (char *)vmPop(pVM
).p
;
326 FICL_HASH
*pHash
= vmPop(pVM
).p
;
332 /**************************************************************************
335 ** setparentwid ( parent-wid wid -- )
336 ** Set WID's link field to the parent-wid. search-wordlist will
337 ** iterate through all the links when finding words in the child wid.
338 **************************************************************************/
339 static void setParentWid(FICL_VM
*pVM
)
341 FICL_HASH
*parent
, *child
;
343 vmCheckStack(pVM
, 2, 0);
345 child
= (FICL_HASH
*)stackPopPtr(pVM
->pStack
);
346 parent
= (FICL_HASH
*)stackPopPtr(pVM
->pStack
);
348 child
->link
= parent
;
353 /**************************************************************************
354 f i c l C o m p i l e S e a r c h
355 ** Builds the primitive wordset and the environment-query namespace.
356 **************************************************************************/
358 void ficlCompileSearch(FICL_SYSTEM
*pSys
)
360 FICL_DICT
*dp
= pSys
->dp
;
364 ** optional SEARCH-ORDER word set
366 dictAppendWord(dp
, ">search", searchPush
, FW_DEFAULT
);
367 dictAppendWord(dp
, "search>", searchPop
, FW_DEFAULT
);
368 dictAppendWord(dp
, "definitions",
369 definitions
, FW_DEFAULT
);
370 dictAppendWord(dp
, "forth-wordlist",
371 forthWordlist
, FW_DEFAULT
);
372 dictAppendWord(dp
, "get-current",
373 getCurrent
, FW_DEFAULT
);
374 dictAppendWord(dp
, "get-order", getOrder
, FW_DEFAULT
);
375 dictAppendWord(dp
, "search-wordlist",
376 searchWordlist
, FW_DEFAULT
);
377 dictAppendWord(dp
, "set-current",
378 setCurrent
, FW_DEFAULT
);
379 dictAppendWord(dp
, "set-order", setOrder
, FW_DEFAULT
);
380 dictAppendWord(dp
, "ficl-wordlist",
381 ficlWordlist
, FW_DEFAULT
);
384 ** Set SEARCH environment query values
386 ficlSetEnv(pSys
, "search-order", FICL_TRUE
);
387 ficlSetEnv(pSys
, "search-order-ext", FICL_TRUE
);
388 ficlSetEnv(pSys
, "wordlists", FICL_DEFAULT_VOCS
);
390 dictAppendWord(dp
, "wid-get-name", widGetName
, FW_DEFAULT
);
391 dictAppendWord(dp
, "wid-set-name", widSetName
, FW_DEFAULT
);
392 dictAppendWord(dp
, "wid-set-super",
393 setParentWid
, FW_DEFAULT
);