xref: /titanic_52/usr/src/common/ficl/dictionary.c (revision a1bf3f785ae05c419b339c3a2061f2b18c024f61)
1*a1bf3f78SToomas Soome /*
2*a1bf3f78SToomas Soome  * d i c t . c
3*a1bf3f78SToomas Soome  * Forth Inspired Command Language - dictionary methods
4*a1bf3f78SToomas Soome  * Author: John Sadler (john_sadler@alum.mit.edu)
5*a1bf3f78SToomas Soome  * Created: 19 July 1997
6*a1bf3f78SToomas Soome  * $Id: dictionary.c,v 1.2 2010/09/12 15:14:52 asau Exp $
7*a1bf3f78SToomas Soome  */
8*a1bf3f78SToomas Soome /*
9*a1bf3f78SToomas Soome  * This file implements the dictionary -- Ficl's model of
10*a1bf3f78SToomas Soome  * memory management. All Ficl words are stored in the
11*a1bf3f78SToomas Soome  * dictionary. A word is a named chunk of data with its
12*a1bf3f78SToomas Soome  * associated code. Ficl treats all words the same, even
13*a1bf3f78SToomas Soome  * precompiled ones, so your words become first-class
14*a1bf3f78SToomas Soome  * extensions of the language. You can even define new
15*a1bf3f78SToomas Soome  * control structures.
16*a1bf3f78SToomas Soome  *
17*a1bf3f78SToomas Soome  * 29 jun 1998 (sadler) added variable sized hash table support
18*a1bf3f78SToomas Soome  */
19*a1bf3f78SToomas Soome /*
20*a1bf3f78SToomas Soome  * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
21*a1bf3f78SToomas Soome  * All rights reserved.
22*a1bf3f78SToomas Soome  *
23*a1bf3f78SToomas Soome  * Get the latest Ficl release at http://ficl.sourceforge.net
24*a1bf3f78SToomas Soome  *
25*a1bf3f78SToomas Soome  * I am interested in hearing from anyone who uses Ficl. If you have
26*a1bf3f78SToomas Soome  * a problem, a success story, a defect, an enhancement request, or
27*a1bf3f78SToomas Soome  * if you would like to contribute to the Ficl release, please
28*a1bf3f78SToomas Soome  * contact me by email at the address above.
29*a1bf3f78SToomas Soome  *
30*a1bf3f78SToomas Soome  * L I C E N S E  and  D I S C L A I M E R
31*a1bf3f78SToomas Soome  *
32*a1bf3f78SToomas Soome  * Redistribution and use in source and binary forms, with or without
33*a1bf3f78SToomas Soome  * modification, are permitted provided that the following conditions
34*a1bf3f78SToomas Soome  * are met:
35*a1bf3f78SToomas Soome  * 1. Redistributions of source code must retain the above copyright
36*a1bf3f78SToomas Soome  *    notice, this list of conditions and the following disclaimer.
37*a1bf3f78SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
38*a1bf3f78SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
39*a1bf3f78SToomas Soome  *    documentation and/or other materials provided with the distribution.
40*a1bf3f78SToomas Soome  *
41*a1bf3f78SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
42*a1bf3f78SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43*a1bf3f78SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44*a1bf3f78SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45*a1bf3f78SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46*a1bf3f78SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47*a1bf3f78SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48*a1bf3f78SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49*a1bf3f78SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50*a1bf3f78SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51*a1bf3f78SToomas Soome  * SUCH DAMAGE.
52*a1bf3f78SToomas Soome  */
53*a1bf3f78SToomas Soome 
54*a1bf3f78SToomas Soome #include "ficl.h"
55*a1bf3f78SToomas Soome 
56*a1bf3f78SToomas Soome #define	FICL_SAFE_CALLBACK_FROM_SYSTEM(system)		\
57*a1bf3f78SToomas Soome 	(((system) != NULL) ? &((system)->callback) : NULL)
58*a1bf3f78SToomas Soome #define	FICL_SAFE_SYSTEM_FROM_DICTIONARY(dictionary)	\
59*a1bf3f78SToomas Soome 	(((dictionary) != NULL) ? (dictionary)->system : NULL)
60*a1bf3f78SToomas Soome #define	FICL_DICTIONARY_ASSERT(dictionary, expression)	\
61*a1bf3f78SToomas Soome 	FICL_SYSTEM_ASSERT(FICL_SAFE_SYSTEM_FROM_DICTIONARY(dictionary), \
62*a1bf3f78SToomas Soome 	expression)
63*a1bf3f78SToomas Soome 
64*a1bf3f78SToomas Soome /*
65*a1bf3f78SToomas Soome  * d i c t A b o r t D e f i n i t i o n
66*a1bf3f78SToomas Soome  * Abort a definition in process: reclaim its memory and unlink it
67*a1bf3f78SToomas Soome  * from the dictionary list. Assumes that there is a smudged
68*a1bf3f78SToomas Soome  * definition in process...otherwise does nothing.
69*a1bf3f78SToomas Soome  * NOTE: this function is not smart enough to unlink a word that
70*a1bf3f78SToomas Soome  * has been successfully defined (ie linked into a hash). It
71*a1bf3f78SToomas Soome  * only works for defs in process. If the def has been unsmudged,
72*a1bf3f78SToomas Soome  * nothing happens.
73*a1bf3f78SToomas Soome  */
74*a1bf3f78SToomas Soome void
75*a1bf3f78SToomas Soome ficlDictionaryAbortDefinition(ficlDictionary *dictionary)
76*a1bf3f78SToomas Soome {
77*a1bf3f78SToomas Soome 	ficlWord *word;
78*a1bf3f78SToomas Soome 	ficlDictionaryLock(dictionary, FICL_TRUE);
79*a1bf3f78SToomas Soome 	word = dictionary->smudge;
80*a1bf3f78SToomas Soome 
81*a1bf3f78SToomas Soome 	if (word->flags & FICL_WORD_SMUDGED)
82*a1bf3f78SToomas Soome 		dictionary->here = (ficlCell *)word->name;
83*a1bf3f78SToomas Soome 
84*a1bf3f78SToomas Soome 	ficlDictionaryLock(dictionary, FICL_FALSE);
85*a1bf3f78SToomas Soome }
86*a1bf3f78SToomas Soome 
87*a1bf3f78SToomas Soome /*
88*a1bf3f78SToomas Soome  * d i c t A l i g n
89*a1bf3f78SToomas Soome  * Align the dictionary's free space pointer
90*a1bf3f78SToomas Soome  */
91*a1bf3f78SToomas Soome void
92*a1bf3f78SToomas Soome ficlDictionaryAlign(ficlDictionary *dictionary)
93*a1bf3f78SToomas Soome {
94*a1bf3f78SToomas Soome 	dictionary->here = ficlAlignPointer(dictionary->here);
95*a1bf3f78SToomas Soome }
96*a1bf3f78SToomas Soome 
97*a1bf3f78SToomas Soome /*
98*a1bf3f78SToomas Soome  * d i c t A l l o t
99*a1bf3f78SToomas Soome  * Allocate or remove n chars of dictionary space, with
100*a1bf3f78SToomas Soome  * checks for underrun and overrun
101*a1bf3f78SToomas Soome  */
102*a1bf3f78SToomas Soome void
103*a1bf3f78SToomas Soome ficlDictionaryAllot(ficlDictionary *dictionary, int n)
104*a1bf3f78SToomas Soome {
105*a1bf3f78SToomas Soome 	char *here = (char *)dictionary->here;
106*a1bf3f78SToomas Soome 	here += n;
107*a1bf3f78SToomas Soome 	dictionary->here = FICL_POINTER_TO_CELL(here);
108*a1bf3f78SToomas Soome }
109*a1bf3f78SToomas Soome 
110*a1bf3f78SToomas Soome /*
111*a1bf3f78SToomas Soome  * d i c t A l l o t C e l l s
112*a1bf3f78SToomas Soome  * Reserve space for the requested number of ficlCells in the
113*a1bf3f78SToomas Soome  * dictionary. If nficlCells < 0 , removes space from the dictionary.
114*a1bf3f78SToomas Soome  */
115*a1bf3f78SToomas Soome void
116*a1bf3f78SToomas Soome ficlDictionaryAllotCells(ficlDictionary *dictionary, int nficlCells)
117*a1bf3f78SToomas Soome {
118*a1bf3f78SToomas Soome 	dictionary->here += nficlCells;
119*a1bf3f78SToomas Soome }
120*a1bf3f78SToomas Soome 
121*a1bf3f78SToomas Soome /*
122*a1bf3f78SToomas Soome  * d i c t A p p e n d C e l l
123*a1bf3f78SToomas Soome  * Append the specified ficlCell to the dictionary
124*a1bf3f78SToomas Soome  */
125*a1bf3f78SToomas Soome void
126*a1bf3f78SToomas Soome ficlDictionaryAppendCell(ficlDictionary *dictionary, ficlCell c)
127*a1bf3f78SToomas Soome {
128*a1bf3f78SToomas Soome 	*dictionary->here++ = c;
129*a1bf3f78SToomas Soome }
130*a1bf3f78SToomas Soome 
131*a1bf3f78SToomas Soome /*
132*a1bf3f78SToomas Soome  * d i c t A p p e n d C h a r
133*a1bf3f78SToomas Soome  * Append the specified char to the dictionary
134*a1bf3f78SToomas Soome  */
135*a1bf3f78SToomas Soome void
136*a1bf3f78SToomas Soome ficlDictionaryAppendCharacter(ficlDictionary *dictionary, char c)
137*a1bf3f78SToomas Soome {
138*a1bf3f78SToomas Soome 	char *here = (char *)dictionary->here;
139*a1bf3f78SToomas Soome 	*here++ = c;
140*a1bf3f78SToomas Soome 	dictionary->here = FICL_POINTER_TO_CELL(here);
141*a1bf3f78SToomas Soome }
142*a1bf3f78SToomas Soome 
143*a1bf3f78SToomas Soome /*
144*a1bf3f78SToomas Soome  * d i c t A p p e n d U N S
145*a1bf3f78SToomas Soome  * Append the specified ficlUnsigned to the dictionary
146*a1bf3f78SToomas Soome  */
147*a1bf3f78SToomas Soome void
148*a1bf3f78SToomas Soome ficlDictionaryAppendUnsigned(ficlDictionary *dictionary, ficlUnsigned u)
149*a1bf3f78SToomas Soome {
150*a1bf3f78SToomas Soome 	ficlCell c;
151*a1bf3f78SToomas Soome 
152*a1bf3f78SToomas Soome 	c.u = u;
153*a1bf3f78SToomas Soome 	ficlDictionaryAppendCell(dictionary, c);
154*a1bf3f78SToomas Soome }
155*a1bf3f78SToomas Soome 
156*a1bf3f78SToomas Soome void *
157*a1bf3f78SToomas Soome ficlDictionaryAppendData(ficlDictionary *dictionary, void *data,
158*a1bf3f78SToomas Soome     ficlInteger length)
159*a1bf3f78SToomas Soome {
160*a1bf3f78SToomas Soome 	char *here = (char *)dictionary->here;
161*a1bf3f78SToomas Soome 	char *oldHere = here;
162*a1bf3f78SToomas Soome 	char *from = (char *)data;
163*a1bf3f78SToomas Soome 
164*a1bf3f78SToomas Soome 	if (length == 0) {
165*a1bf3f78SToomas Soome 		ficlDictionaryAlign(dictionary);
166*a1bf3f78SToomas Soome 		return ((char *)dictionary->here);
167*a1bf3f78SToomas Soome 	}
168*a1bf3f78SToomas Soome 
169*a1bf3f78SToomas Soome 	while (length) {
170*a1bf3f78SToomas Soome 		*here++ = *from++;
171*a1bf3f78SToomas Soome 		length--;
172*a1bf3f78SToomas Soome 	}
173*a1bf3f78SToomas Soome 
174*a1bf3f78SToomas Soome 	*here++ = '\0';
175*a1bf3f78SToomas Soome 
176*a1bf3f78SToomas Soome 	dictionary->here = FICL_POINTER_TO_CELL(here);
177*a1bf3f78SToomas Soome 	ficlDictionaryAlign(dictionary);
178*a1bf3f78SToomas Soome 	return (oldHere);
179*a1bf3f78SToomas Soome }
180*a1bf3f78SToomas Soome 
181*a1bf3f78SToomas Soome /*
182*a1bf3f78SToomas Soome  * d i c t C o p y N a m e
183*a1bf3f78SToomas Soome  * Copy up to FICL_NAME_LENGTH characters of the name specified by s into
184*a1bf3f78SToomas Soome  * the dictionary starting at "here", then NULL-terminate the name,
185*a1bf3f78SToomas Soome  * point "here" to the next available byte, and return the address of
186*a1bf3f78SToomas Soome  * the beginning of the name. Used by dictAppendWord.
187*a1bf3f78SToomas Soome  * N O T E S :
188*a1bf3f78SToomas Soome  * 1. "here" is guaranteed to be aligned after this operation.
189*a1bf3f78SToomas Soome  * 2. If the string has zero length, align and return "here"
190*a1bf3f78SToomas Soome  */
191*a1bf3f78SToomas Soome char *
192*a1bf3f78SToomas Soome ficlDictionaryAppendString(ficlDictionary *dictionary, ficlString s)
193*a1bf3f78SToomas Soome {
194*a1bf3f78SToomas Soome 	void *data = FICL_STRING_GET_POINTER(s);
195*a1bf3f78SToomas Soome 	ficlInteger length = FICL_STRING_GET_LENGTH(s);
196*a1bf3f78SToomas Soome 
197*a1bf3f78SToomas Soome 	if (length > FICL_NAME_LENGTH)
198*a1bf3f78SToomas Soome 		length = FICL_NAME_LENGTH;
199*a1bf3f78SToomas Soome 
200*a1bf3f78SToomas Soome 	return (ficlDictionaryAppendData(dictionary, data, length));
201*a1bf3f78SToomas Soome }
202*a1bf3f78SToomas Soome 
203*a1bf3f78SToomas Soome ficlWord *
204*a1bf3f78SToomas Soome ficlDictionaryAppendConstantInstruction(ficlDictionary *dictionary,
205*a1bf3f78SToomas Soome     ficlString name, ficlInstruction instruction, ficlInteger value)
206*a1bf3f78SToomas Soome {
207*a1bf3f78SToomas Soome 	ficlWord *word = ficlDictionaryAppendWord(dictionary, name,
208*a1bf3f78SToomas Soome 	    (ficlPrimitive)instruction, FICL_WORD_DEFAULT);
209*a1bf3f78SToomas Soome 
210*a1bf3f78SToomas Soome 	if (word != NULL)
211*a1bf3f78SToomas Soome 		ficlDictionaryAppendUnsigned(dictionary, value);
212*a1bf3f78SToomas Soome 	return (word);
213*a1bf3f78SToomas Soome }
214*a1bf3f78SToomas Soome 
215*a1bf3f78SToomas Soome ficlWord *
216*a1bf3f78SToomas Soome ficlDictionaryAppend2ConstantInstruction(ficlDictionary *dictionary,
217*a1bf3f78SToomas Soome     ficlString name, ficlInstruction instruction, ficl2Integer value)
218*a1bf3f78SToomas Soome {
219*a1bf3f78SToomas Soome 	ficlWord *word = ficlDictionaryAppendWord(dictionary, name,
220*a1bf3f78SToomas Soome 	    (ficlPrimitive)instruction, FICL_WORD_DEFAULT);
221*a1bf3f78SToomas Soome 
222*a1bf3f78SToomas Soome 	if (word != NULL) {
223*a1bf3f78SToomas Soome 		ficlDictionaryAppendUnsigned(dictionary,
224*a1bf3f78SToomas Soome 		    FICL_2UNSIGNED_GET_HIGH(value));
225*a1bf3f78SToomas Soome 		ficlDictionaryAppendUnsigned(dictionary,
226*a1bf3f78SToomas Soome 		    FICL_2UNSIGNED_GET_LOW(value));
227*a1bf3f78SToomas Soome 	}
228*a1bf3f78SToomas Soome 	return (word);
229*a1bf3f78SToomas Soome }
230*a1bf3f78SToomas Soome 
231*a1bf3f78SToomas Soome ficlWord *
232*a1bf3f78SToomas Soome ficlDictionaryAppendConstant(ficlDictionary *dictionary, char *name,
233*a1bf3f78SToomas Soome     ficlInteger value)
234*a1bf3f78SToomas Soome {
235*a1bf3f78SToomas Soome 	ficlString s;
236*a1bf3f78SToomas Soome 	FICL_STRING_SET_FROM_CSTRING(s, name);
237*a1bf3f78SToomas Soome 	return (ficlDictionaryAppendConstantInstruction(dictionary, s,
238*a1bf3f78SToomas Soome 	    ficlInstructionConstantParen, value));
239*a1bf3f78SToomas Soome }
240*a1bf3f78SToomas Soome 
241*a1bf3f78SToomas Soome ficlWord *
242*a1bf3f78SToomas Soome ficlDictionaryAppend2Constant(ficlDictionary *dictionary, char *name,
243*a1bf3f78SToomas Soome     ficl2Integer value)
244*a1bf3f78SToomas Soome {
245*a1bf3f78SToomas Soome 	ficlString s;
246*a1bf3f78SToomas Soome 	FICL_STRING_SET_FROM_CSTRING(s, name);
247*a1bf3f78SToomas Soome 	return (ficlDictionaryAppend2ConstantInstruction(dictionary, s,
248*a1bf3f78SToomas Soome 	    ficlInstruction2ConstantParen, value));
249*a1bf3f78SToomas Soome }
250*a1bf3f78SToomas Soome 
251*a1bf3f78SToomas Soome ficlWord *
252*a1bf3f78SToomas Soome ficlDictionarySetConstantInstruction(ficlDictionary *dictionary,
253*a1bf3f78SToomas Soome     ficlString name, ficlInstruction instruction, ficlInteger value)
254*a1bf3f78SToomas Soome {
255*a1bf3f78SToomas Soome 	ficlWord *word = ficlDictionaryLookup(dictionary, name);
256*a1bf3f78SToomas Soome 	ficlCell c;
257*a1bf3f78SToomas Soome 
258*a1bf3f78SToomas Soome 	if (word == NULL) {
259*a1bf3f78SToomas Soome 		word = ficlDictionaryAppendConstantInstruction(dictionary,
260*a1bf3f78SToomas Soome 		    name, instruction, value);
261*a1bf3f78SToomas Soome 	} else {
262*a1bf3f78SToomas Soome 		word->code = (ficlPrimitive)instruction;
263*a1bf3f78SToomas Soome 		c.i = value;
264*a1bf3f78SToomas Soome 		word->param[0] = c;
265*a1bf3f78SToomas Soome 	}
266*a1bf3f78SToomas Soome 	return (word);
267*a1bf3f78SToomas Soome }
268*a1bf3f78SToomas Soome 
269*a1bf3f78SToomas Soome ficlWord *
270*a1bf3f78SToomas Soome ficlDictionarySetConstant(ficlDictionary *dictionary, char *name,
271*a1bf3f78SToomas Soome     ficlInteger value)
272*a1bf3f78SToomas Soome {
273*a1bf3f78SToomas Soome 	ficlString s;
274*a1bf3f78SToomas Soome 	FICL_STRING_SET_FROM_CSTRING(s, name);
275*a1bf3f78SToomas Soome 	return (ficlDictionarySetConstantInstruction(dictionary, s,
276*a1bf3f78SToomas Soome 	    ficlInstructionConstantParen, value));
277*a1bf3f78SToomas Soome }
278*a1bf3f78SToomas Soome 
279*a1bf3f78SToomas Soome ficlWord *
280*a1bf3f78SToomas Soome ficlDictionarySet2ConstantInstruction(ficlDictionary *dictionary, ficlString s,
281*a1bf3f78SToomas Soome     ficlInstruction instruction, ficl2Integer value)
282*a1bf3f78SToomas Soome {
283*a1bf3f78SToomas Soome 	ficlWord *word;
284*a1bf3f78SToomas Soome 	word = ficlDictionaryLookup(dictionary, s);
285*a1bf3f78SToomas Soome 
286*a1bf3f78SToomas Soome 	/*
287*a1bf3f78SToomas Soome 	 * only reuse the existing word if we're sure it has space for a
288*a1bf3f78SToomas Soome 	 * 2constant
289*a1bf3f78SToomas Soome 	 */
290*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
291*a1bf3f78SToomas Soome 	if ((word != NULL) &&
292*a1bf3f78SToomas Soome 	    ((((ficlInstruction)word->code) == ficlInstruction2ConstantParen) ||
293*a1bf3f78SToomas Soome 	    (((ficlInstruction)word->code) == ficlInstructionF2ConstantParen)))
294*a1bf3f78SToomas Soome #else
295*a1bf3f78SToomas Soome 	if ((word != NULL) &&
296*a1bf3f78SToomas Soome 	    ((((ficlInstruction)word->code) == ficlInstruction2ConstantParen)))
297*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */
298*a1bf3f78SToomas Soome 	{
299*a1bf3f78SToomas Soome 		word->code = (ficlPrimitive)instruction;
300*a1bf3f78SToomas Soome 		word->param[0].u = FICL_2UNSIGNED_GET_HIGH(value);
301*a1bf3f78SToomas Soome 		word->param[1].u = FICL_2UNSIGNED_GET_LOW(value);
302*a1bf3f78SToomas Soome 	} else {
303*a1bf3f78SToomas Soome 		word = ficlDictionaryAppend2ConstantInstruction(dictionary, s,
304*a1bf3f78SToomas Soome 		    instruction, value);
305*a1bf3f78SToomas Soome 	}
306*a1bf3f78SToomas Soome 
307*a1bf3f78SToomas Soome 	return (word);
308*a1bf3f78SToomas Soome }
309*a1bf3f78SToomas Soome 
310*a1bf3f78SToomas Soome ficlWord *
311*a1bf3f78SToomas Soome ficlDictionarySet2Constant(ficlDictionary *dictionary, char *name,
312*a1bf3f78SToomas Soome     ficl2Integer value)
313*a1bf3f78SToomas Soome {
314*a1bf3f78SToomas Soome 	ficlString s;
315*a1bf3f78SToomas Soome 	FICL_STRING_SET_FROM_CSTRING(s, name);
316*a1bf3f78SToomas Soome 
317*a1bf3f78SToomas Soome 	return (ficlDictionarySet2ConstantInstruction(dictionary, s,
318*a1bf3f78SToomas Soome 	    ficlInstruction2ConstantParen, value));
319*a1bf3f78SToomas Soome }
320*a1bf3f78SToomas Soome 
321*a1bf3f78SToomas Soome ficlWord *
322*a1bf3f78SToomas Soome ficlDictionarySetConstantString(ficlDictionary *dictionary, char *name,
323*a1bf3f78SToomas Soome     char *value)
324*a1bf3f78SToomas Soome {
325*a1bf3f78SToomas Soome 	ficlString s;
326*a1bf3f78SToomas Soome 	ficl2Integer valueAs2Integer;
327*a1bf3f78SToomas Soome 	FICL_2INTEGER_SET(strlen(value), (intptr_t)value, valueAs2Integer);
328*a1bf3f78SToomas Soome 	FICL_STRING_SET_FROM_CSTRING(s, name);
329*a1bf3f78SToomas Soome 
330*a1bf3f78SToomas Soome 	return (ficlDictionarySet2ConstantInstruction(dictionary, s,
331*a1bf3f78SToomas Soome 	    ficlInstruction2ConstantParen, valueAs2Integer));
332*a1bf3f78SToomas Soome }
333*a1bf3f78SToomas Soome 
334*a1bf3f78SToomas Soome /*
335*a1bf3f78SToomas Soome  * d i c t A p p e n d W o r d
336*a1bf3f78SToomas Soome  * Create a new word in the dictionary with the specified
337*a1bf3f78SToomas Soome  * ficlString, code, and flags. Does not require a NULL-terminated
338*a1bf3f78SToomas Soome  * name.
339*a1bf3f78SToomas Soome  */
340*a1bf3f78SToomas Soome ficlWord *
341*a1bf3f78SToomas Soome ficlDictionaryAppendWord(ficlDictionary *dictionary, ficlString name,
342*a1bf3f78SToomas Soome     ficlPrimitive code, ficlUnsigned8 flags)
343*a1bf3f78SToomas Soome {
344*a1bf3f78SToomas Soome 	ficlUnsigned8 length = (ficlUnsigned8)FICL_STRING_GET_LENGTH(name);
345*a1bf3f78SToomas Soome 	char *nameCopy;
346*a1bf3f78SToomas Soome 	ficlWord *word;
347*a1bf3f78SToomas Soome 
348*a1bf3f78SToomas Soome 	ficlDictionaryLock(dictionary, FICL_TRUE);
349*a1bf3f78SToomas Soome 
350*a1bf3f78SToomas Soome 	/*
351*a1bf3f78SToomas Soome 	 * NOTE: ficlDictionaryAppendString advances "here" as a side-effect.
352*a1bf3f78SToomas Soome 	 * It must execute before word is initialized.
353*a1bf3f78SToomas Soome 	 */
354*a1bf3f78SToomas Soome 	nameCopy = ficlDictionaryAppendString(dictionary, name);
355*a1bf3f78SToomas Soome 	word = (ficlWord *)dictionary->here;
356*a1bf3f78SToomas Soome 	dictionary->smudge = word;
357*a1bf3f78SToomas Soome 	word->hash = ficlHashCode(name);
358*a1bf3f78SToomas Soome 	word->code = code;
359*a1bf3f78SToomas Soome 	word->semiParen = ficlInstructionSemiParen;
360*a1bf3f78SToomas Soome 	word->flags = (ficlUnsigned8)(flags | FICL_WORD_SMUDGED);
361*a1bf3f78SToomas Soome 	word->length = length;
362*a1bf3f78SToomas Soome 	word->name = nameCopy;
363*a1bf3f78SToomas Soome 
364*a1bf3f78SToomas Soome 	/*
365*a1bf3f78SToomas Soome 	 * Point "here" to first ficlCell of new word's param area...
366*a1bf3f78SToomas Soome 	 */
367*a1bf3f78SToomas Soome 	dictionary->here = word->param;
368*a1bf3f78SToomas Soome 
369*a1bf3f78SToomas Soome 	if (!(flags & FICL_WORD_SMUDGED))
370*a1bf3f78SToomas Soome 		ficlDictionaryUnsmudge(dictionary);
371*a1bf3f78SToomas Soome 
372*a1bf3f78SToomas Soome 	ficlDictionaryLock(dictionary, FICL_FALSE);
373*a1bf3f78SToomas Soome 	return (word);
374*a1bf3f78SToomas Soome }
375*a1bf3f78SToomas Soome 
376*a1bf3f78SToomas Soome /*
377*a1bf3f78SToomas Soome  * d i c t A p p e n d W o r d
378*a1bf3f78SToomas Soome  * Create a new word in the dictionary with the specified
379*a1bf3f78SToomas Soome  * name, code, and flags. Name must be NULL-terminated.
380*a1bf3f78SToomas Soome  */
381*a1bf3f78SToomas Soome ficlWord *
382*a1bf3f78SToomas Soome ficlDictionaryAppendPrimitive(ficlDictionary *dictionary, char *name,
383*a1bf3f78SToomas Soome     ficlPrimitive code, ficlUnsigned8 flags)
384*a1bf3f78SToomas Soome {
385*a1bf3f78SToomas Soome 	ficlString s;
386*a1bf3f78SToomas Soome 	FICL_STRING_SET_FROM_CSTRING(s, name);
387*a1bf3f78SToomas Soome 
388*a1bf3f78SToomas Soome 	return (ficlDictionaryAppendWord(dictionary, s, code, flags));
389*a1bf3f78SToomas Soome }
390*a1bf3f78SToomas Soome 
391*a1bf3f78SToomas Soome ficlWord *
392*a1bf3f78SToomas Soome ficlDictionarySetPrimitive(ficlDictionary *dictionary, char *name,
393*a1bf3f78SToomas Soome     ficlPrimitive code, ficlUnsigned8 flags)
394*a1bf3f78SToomas Soome {
395*a1bf3f78SToomas Soome 	ficlString s;
396*a1bf3f78SToomas Soome 	ficlWord *word;
397*a1bf3f78SToomas Soome 
398*a1bf3f78SToomas Soome 	FICL_STRING_SET_FROM_CSTRING(s, name);
399*a1bf3f78SToomas Soome 	word = ficlDictionaryLookup(dictionary, s);
400*a1bf3f78SToomas Soome 
401*a1bf3f78SToomas Soome 	if (word == NULL) {
402*a1bf3f78SToomas Soome 		word = ficlDictionaryAppendPrimitive(dictionary, name,
403*a1bf3f78SToomas Soome 		    code, flags);
404*a1bf3f78SToomas Soome 	} else {
405*a1bf3f78SToomas Soome 		word->code = (ficlPrimitive)code;
406*a1bf3f78SToomas Soome 		word->flags = flags;
407*a1bf3f78SToomas Soome 	}
408*a1bf3f78SToomas Soome 	return (word);
409*a1bf3f78SToomas Soome }
410*a1bf3f78SToomas Soome 
411*a1bf3f78SToomas Soome ficlWord *
412*a1bf3f78SToomas Soome ficlDictionaryAppendInstruction(ficlDictionary *dictionary, char *name,
413*a1bf3f78SToomas Soome     ficlInstruction i, ficlUnsigned8 flags)
414*a1bf3f78SToomas Soome {
415*a1bf3f78SToomas Soome 	return (ficlDictionaryAppendPrimitive(dictionary, name,
416*a1bf3f78SToomas Soome 	    (ficlPrimitive)i, (ficlUnsigned8)(FICL_WORD_INSTRUCTION | flags)));
417*a1bf3f78SToomas Soome }
418*a1bf3f78SToomas Soome 
419*a1bf3f78SToomas Soome ficlWord *
420*a1bf3f78SToomas Soome ficlDictionarySetInstruction(ficlDictionary *dictionary, char *name,
421*a1bf3f78SToomas Soome     ficlInstruction i, ficlUnsigned8 flags)
422*a1bf3f78SToomas Soome {
423*a1bf3f78SToomas Soome 	return (ficlDictionarySetPrimitive(dictionary, name,
424*a1bf3f78SToomas Soome 	    (ficlPrimitive)i, (ficlUnsigned8)(FICL_WORD_INSTRUCTION | flags)));
425*a1bf3f78SToomas Soome }
426*a1bf3f78SToomas Soome 
427*a1bf3f78SToomas Soome /*
428*a1bf3f78SToomas Soome  * d i c t C e l l s A v a i l
429*a1bf3f78SToomas Soome  * Returns the number of empty ficlCells left in the dictionary
430*a1bf3f78SToomas Soome  */
431*a1bf3f78SToomas Soome int
432*a1bf3f78SToomas Soome ficlDictionaryCellsAvailable(ficlDictionary *dictionary)
433*a1bf3f78SToomas Soome {
434*a1bf3f78SToomas Soome 	return (dictionary->size - ficlDictionaryCellsUsed(dictionary));
435*a1bf3f78SToomas Soome }
436*a1bf3f78SToomas Soome 
437*a1bf3f78SToomas Soome /*
438*a1bf3f78SToomas Soome  * d i c t C e l l s U s e d
439*a1bf3f78SToomas Soome  * Returns the number of ficlCells consumed in the dicionary
440*a1bf3f78SToomas Soome  */
441*a1bf3f78SToomas Soome int
442*a1bf3f78SToomas Soome ficlDictionaryCellsUsed(ficlDictionary *dictionary)
443*a1bf3f78SToomas Soome {
444*a1bf3f78SToomas Soome 	return (dictionary->here - dictionary->base);
445*a1bf3f78SToomas Soome }
446*a1bf3f78SToomas Soome 
447*a1bf3f78SToomas Soome /*
448*a1bf3f78SToomas Soome  * d i c t C r e a t e
449*a1bf3f78SToomas Soome  * Create and initialize a dictionary with the specified number
450*a1bf3f78SToomas Soome  * of ficlCells capacity, and no hashing (hash size == 1).
451*a1bf3f78SToomas Soome  */
452*a1bf3f78SToomas Soome ficlDictionary *
453*a1bf3f78SToomas Soome ficlDictionaryCreate(ficlSystem *system, unsigned size)
454*a1bf3f78SToomas Soome {
455*a1bf3f78SToomas Soome 	return (ficlDictionaryCreateHashed(system, size, 1));
456*a1bf3f78SToomas Soome }
457*a1bf3f78SToomas Soome 
458*a1bf3f78SToomas Soome ficlDictionary *
459*a1bf3f78SToomas Soome ficlDictionaryCreateHashed(ficlSystem *system, unsigned size,
460*a1bf3f78SToomas Soome     unsigned bucketCount)
461*a1bf3f78SToomas Soome {
462*a1bf3f78SToomas Soome 	ficlDictionary *dictionary;
463*a1bf3f78SToomas Soome 	size_t nAlloc;
464*a1bf3f78SToomas Soome 
465*a1bf3f78SToomas Soome 	nAlloc =  sizeof (ficlDictionary) + (size * sizeof (ficlCell))
466*a1bf3f78SToomas Soome 	    + sizeof (ficlHash) + (bucketCount - 1) * sizeof (ficlWord *);
467*a1bf3f78SToomas Soome 
468*a1bf3f78SToomas Soome 	dictionary = ficlMalloc(nAlloc);
469*a1bf3f78SToomas Soome 	FICL_SYSTEM_ASSERT(system, dictionary != NULL);
470*a1bf3f78SToomas Soome 
471*a1bf3f78SToomas Soome 	dictionary->size = size;
472*a1bf3f78SToomas Soome 	dictionary->system = system;
473*a1bf3f78SToomas Soome 
474*a1bf3f78SToomas Soome 	ficlDictionaryEmpty(dictionary, bucketCount);
475*a1bf3f78SToomas Soome 	return (dictionary);
476*a1bf3f78SToomas Soome }
477*a1bf3f78SToomas Soome 
478*a1bf3f78SToomas Soome /*
479*a1bf3f78SToomas Soome  * d i c t C r e a t e W o r d l i s t
480*a1bf3f78SToomas Soome  * Create and initialize an anonymous wordlist
481*a1bf3f78SToomas Soome  */
482*a1bf3f78SToomas Soome ficlHash *
483*a1bf3f78SToomas Soome ficlDictionaryCreateWordlist(ficlDictionary *dictionary, int bucketCount)
484*a1bf3f78SToomas Soome {
485*a1bf3f78SToomas Soome 	ficlHash *hash;
486*a1bf3f78SToomas Soome 
487*a1bf3f78SToomas Soome 	ficlDictionaryAlign(dictionary);
488*a1bf3f78SToomas Soome 	hash = (ficlHash *)dictionary->here;
489*a1bf3f78SToomas Soome 	ficlDictionaryAllot(dictionary,
490*a1bf3f78SToomas Soome 	    sizeof (ficlHash) + (bucketCount - 1) * sizeof (ficlWord *));
491*a1bf3f78SToomas Soome 
492*a1bf3f78SToomas Soome 	hash->size = bucketCount;
493*a1bf3f78SToomas Soome 	ficlHashReset(hash);
494*a1bf3f78SToomas Soome 	return (hash);
495*a1bf3f78SToomas Soome }
496*a1bf3f78SToomas Soome 
497*a1bf3f78SToomas Soome /*
498*a1bf3f78SToomas Soome  * d i c t D e l e t e
499*a1bf3f78SToomas Soome  * Free all memory allocated for the given dictionary
500*a1bf3f78SToomas Soome  */
501*a1bf3f78SToomas Soome void
502*a1bf3f78SToomas Soome ficlDictionaryDestroy(ficlDictionary *dictionary)
503*a1bf3f78SToomas Soome {
504*a1bf3f78SToomas Soome 	FICL_DICTIONARY_ASSERT(dictionary, dictionary != NULL);
505*a1bf3f78SToomas Soome 	ficlFree(dictionary);
506*a1bf3f78SToomas Soome }
507*a1bf3f78SToomas Soome 
508*a1bf3f78SToomas Soome /*
509*a1bf3f78SToomas Soome  * d i c t E m p t y
510*a1bf3f78SToomas Soome  * Empty the dictionary, reset its hash table, and reset its search order.
511*a1bf3f78SToomas Soome  * Clears and (re-)creates the hash table with the size specified by nHash.
512*a1bf3f78SToomas Soome  */
513*a1bf3f78SToomas Soome void
514*a1bf3f78SToomas Soome ficlDictionaryEmpty(ficlDictionary *dictionary, unsigned bucketCount)
515*a1bf3f78SToomas Soome {
516*a1bf3f78SToomas Soome 	ficlHash *hash;
517*a1bf3f78SToomas Soome 
518*a1bf3f78SToomas Soome 	dictionary->here = dictionary->base;
519*a1bf3f78SToomas Soome 
520*a1bf3f78SToomas Soome 	ficlDictionaryAlign(dictionary);
521*a1bf3f78SToomas Soome 	hash = (ficlHash *)dictionary->here;
522*a1bf3f78SToomas Soome 	ficlDictionaryAllot(dictionary,
523*a1bf3f78SToomas Soome 	    sizeof (ficlHash) + (bucketCount - 1) * sizeof (ficlWord *));
524*a1bf3f78SToomas Soome 
525*a1bf3f78SToomas Soome 	hash->size = bucketCount;
526*a1bf3f78SToomas Soome 	ficlHashReset(hash);
527*a1bf3f78SToomas Soome 
528*a1bf3f78SToomas Soome 	dictionary->forthWordlist = hash;
529*a1bf3f78SToomas Soome 	dictionary->smudge = NULL;
530*a1bf3f78SToomas Soome 	ficlDictionaryResetSearchOrder(dictionary);
531*a1bf3f78SToomas Soome }
532*a1bf3f78SToomas Soome 
533*a1bf3f78SToomas Soome /*
534*a1bf3f78SToomas Soome  * i s A F i c l W o r d
535*a1bf3f78SToomas Soome  * Vet a candidate pointer carefully to make sure
536*a1bf3f78SToomas Soome  * it's not some chunk o' inline data...
537*a1bf3f78SToomas Soome  * It has to have a name, and it has to look
538*a1bf3f78SToomas Soome  * like it's in the dictionary address range.
539*a1bf3f78SToomas Soome  * NOTE: this excludes :noname words!
540*a1bf3f78SToomas Soome  */
541*a1bf3f78SToomas Soome int
542*a1bf3f78SToomas Soome ficlDictionaryIsAWord(ficlDictionary *dictionary, ficlWord *word)
543*a1bf3f78SToomas Soome {
544*a1bf3f78SToomas Soome 	if ((((ficlInstruction)word) > ficlInstructionInvalid) &&
545*a1bf3f78SToomas Soome 	    (((ficlInstruction)word) < ficlInstructionLast))
546*a1bf3f78SToomas Soome 		return (1);
547*a1bf3f78SToomas Soome 
548*a1bf3f78SToomas Soome 	if (!ficlDictionaryIncludes(dictionary, word))
549*a1bf3f78SToomas Soome 		return (0);
550*a1bf3f78SToomas Soome 
551*a1bf3f78SToomas Soome 	if (!ficlDictionaryIncludes(dictionary, word->name))
552*a1bf3f78SToomas Soome 		return (0);
553*a1bf3f78SToomas Soome 
554*a1bf3f78SToomas Soome 	if ((word->link != NULL) &&
555*a1bf3f78SToomas Soome 	    !ficlDictionaryIncludes(dictionary, word->link))
556*a1bf3f78SToomas Soome 		return (0);
557*a1bf3f78SToomas Soome 
558*a1bf3f78SToomas Soome 	if ((word->length <= 0) || (word->name[word->length] != '\0'))
559*a1bf3f78SToomas Soome 		return (0);
560*a1bf3f78SToomas Soome 
561*a1bf3f78SToomas Soome 	if (strlen(word->name) != word->length)
562*a1bf3f78SToomas Soome 		return (0);
563*a1bf3f78SToomas Soome 
564*a1bf3f78SToomas Soome 	return (1);
565*a1bf3f78SToomas Soome }
566*a1bf3f78SToomas Soome 
567*a1bf3f78SToomas Soome /*
568*a1bf3f78SToomas Soome  * f i n d E n c l o s i n g W o r d
569*a1bf3f78SToomas Soome  * Given a pointer to something, check to make sure it's an address in the
570*a1bf3f78SToomas Soome  * dictionary. If so, search backwards until we find something that looks
571*a1bf3f78SToomas Soome  * like a dictionary header. If successful, return the address of the
572*a1bf3f78SToomas Soome  * ficlWord found. Otherwise return NULL. nSEARCH_CELLS sets the maximum
573*a1bf3f78SToomas Soome  * neighborhood this func will search before giving up
574*a1bf3f78SToomas Soome  */
575*a1bf3f78SToomas Soome #define	nSEARCH_CELLS	100
576*a1bf3f78SToomas Soome 
577*a1bf3f78SToomas Soome ficlWord *
578*a1bf3f78SToomas Soome ficlDictionaryFindEnclosingWord(ficlDictionary *dictionary, ficlCell *cell)
579*a1bf3f78SToomas Soome {
580*a1bf3f78SToomas Soome 	ficlWord *word;
581*a1bf3f78SToomas Soome 	int i;
582*a1bf3f78SToomas Soome 
583*a1bf3f78SToomas Soome 	if (!ficlDictionaryIncludes(dictionary, (void *)cell))
584*a1bf3f78SToomas Soome 		return (NULL);
585*a1bf3f78SToomas Soome 
586*a1bf3f78SToomas Soome 	for (i = nSEARCH_CELLS; i > 0; --i, --cell) {
587*a1bf3f78SToomas Soome 		word = (ficlWord *)
588*a1bf3f78SToomas Soome 		    (cell + 1 - (sizeof (ficlWord) / sizeof (ficlCell)));
589*a1bf3f78SToomas Soome 		if (ficlDictionaryIsAWord(dictionary, word))
590*a1bf3f78SToomas Soome 			return (word);
591*a1bf3f78SToomas Soome 	}
592*a1bf3f78SToomas Soome 
593*a1bf3f78SToomas Soome 	return (NULL);
594*a1bf3f78SToomas Soome }
595*a1bf3f78SToomas Soome 
596*a1bf3f78SToomas Soome /*
597*a1bf3f78SToomas Soome  * d i c t I n c l u d e s
598*a1bf3f78SToomas Soome  * Returns FICL_TRUE iff the given pointer is within the address range of
599*a1bf3f78SToomas Soome  * the dictionary.
600*a1bf3f78SToomas Soome  */
601*a1bf3f78SToomas Soome int
602*a1bf3f78SToomas Soome ficlDictionaryIncludes(ficlDictionary *dictionary, void *p)
603*a1bf3f78SToomas Soome {
604*a1bf3f78SToomas Soome 	return ((p >= (void *) &dictionary->base) &&
605*a1bf3f78SToomas Soome 	    (p <  (void *)(&dictionary->base + dictionary->size)));
606*a1bf3f78SToomas Soome }
607*a1bf3f78SToomas Soome 
608*a1bf3f78SToomas Soome /*
609*a1bf3f78SToomas Soome  * d i c t L o o k u p
610*a1bf3f78SToomas Soome  * Find the ficlWord that matches the given name and length.
611*a1bf3f78SToomas Soome  * If found, returns the word's address. Otherwise returns NULL.
612*a1bf3f78SToomas Soome  * Uses the search order list to search multiple wordlists.
613*a1bf3f78SToomas Soome  */
614*a1bf3f78SToomas Soome ficlWord *
615*a1bf3f78SToomas Soome ficlDictionaryLookup(ficlDictionary *dictionary, ficlString name)
616*a1bf3f78SToomas Soome {
617*a1bf3f78SToomas Soome 	ficlWord *word = NULL;
618*a1bf3f78SToomas Soome 	ficlHash *hash;
619*a1bf3f78SToomas Soome 	int i;
620*a1bf3f78SToomas Soome 	ficlUnsigned16 hashCode = ficlHashCode(name);
621*a1bf3f78SToomas Soome 
622*a1bf3f78SToomas Soome 	FICL_DICTIONARY_ASSERT(dictionary, dictionary != NULL);
623*a1bf3f78SToomas Soome 
624*a1bf3f78SToomas Soome 	ficlDictionaryLock(dictionary, FICL_TRUE);
625*a1bf3f78SToomas Soome 
626*a1bf3f78SToomas Soome 	for (i = (int)dictionary->wordlistCount - 1; (i >= 0) && (!word); --i) {
627*a1bf3f78SToomas Soome 		hash = dictionary->wordlists[i];
628*a1bf3f78SToomas Soome 		word = ficlHashLookup(hash, name, hashCode);
629*a1bf3f78SToomas Soome 	}
630*a1bf3f78SToomas Soome 
631*a1bf3f78SToomas Soome 	ficlDictionaryLock(dictionary, FICL_FALSE);
632*a1bf3f78SToomas Soome 	return (word);
633*a1bf3f78SToomas Soome }
634*a1bf3f78SToomas Soome 
635*a1bf3f78SToomas Soome /*
636*a1bf3f78SToomas Soome  * s e e
637*a1bf3f78SToomas Soome  * TOOLS ( "<spaces>name" -- )
638*a1bf3f78SToomas Soome  * Display a human-readable representation of the named word's definition.
639*a1bf3f78SToomas Soome  * The source of the representation (object-code decompilation, source
640*a1bf3f78SToomas Soome  * block, etc.) and the particular form of the display is implementation
641*a1bf3f78SToomas Soome  * defined.
642*a1bf3f78SToomas Soome  */
643*a1bf3f78SToomas Soome /*
644*a1bf3f78SToomas Soome  * ficlSeeColon (for proctologists only)
645*a1bf3f78SToomas Soome  * Walks a colon definition, decompiling
646*a1bf3f78SToomas Soome  * on the fly. Knows about primitive control structures.
647*a1bf3f78SToomas Soome  */
648*a1bf3f78SToomas Soome char *ficlDictionaryInstructionNames[] =
649*a1bf3f78SToomas Soome {
650*a1bf3f78SToomas Soome #define	FICL_TOKEN(token, description)	description,
651*a1bf3f78SToomas Soome #define	FICL_INSTRUCTION_TOKEN(token, description, flags)	description,
652*a1bf3f78SToomas Soome #include "ficltokens.h"
653*a1bf3f78SToomas Soome #undef FICL_TOKEN
654*a1bf3f78SToomas Soome #undef FICL_INSTRUCTION_TOKEN
655*a1bf3f78SToomas Soome };
656*a1bf3f78SToomas Soome 
657*a1bf3f78SToomas Soome void
658*a1bf3f78SToomas Soome ficlDictionarySee(ficlDictionary *dictionary, ficlWord *word,
659*a1bf3f78SToomas Soome     ficlCallback *callback)
660*a1bf3f78SToomas Soome {
661*a1bf3f78SToomas Soome 	char *trace;
662*a1bf3f78SToomas Soome 	ficlCell *cell = word->param;
663*a1bf3f78SToomas Soome 	ficlCell *param0 = cell;
664*a1bf3f78SToomas Soome 	char buffer[128];
665*a1bf3f78SToomas Soome 
666*a1bf3f78SToomas Soome 	for (; cell->i != ficlInstructionSemiParen; cell++) {
667*a1bf3f78SToomas Soome 		ficlWord *word = (ficlWord *)(cell->p);
668*a1bf3f78SToomas Soome 
669*a1bf3f78SToomas Soome 		trace = buffer;
670*a1bf3f78SToomas Soome 		if ((void *)cell == (void *)buffer)
671*a1bf3f78SToomas Soome 			*trace++ = '>';
672*a1bf3f78SToomas Soome 		else
673*a1bf3f78SToomas Soome 			*trace++ = ' ';
674*a1bf3f78SToomas Soome 		trace += sprintf(trace, "%3ld   ", (long)(cell - param0));
675*a1bf3f78SToomas Soome 
676*a1bf3f78SToomas Soome 		if (ficlDictionaryIsAWord(dictionary, word)) {
677*a1bf3f78SToomas Soome 			ficlWordKind kind = ficlWordClassify(word);
678*a1bf3f78SToomas Soome 			ficlCell c, c2;
679*a1bf3f78SToomas Soome 
680*a1bf3f78SToomas Soome 			switch (kind) {
681*a1bf3f78SToomas Soome 			case FICL_WORDKIND_INSTRUCTION:
682*a1bf3f78SToomas Soome 				sprintf(trace, "%s (instruction %ld)",
683*a1bf3f78SToomas Soome 				    ficlDictionaryInstructionNames[(long)word],
684*a1bf3f78SToomas Soome 				    (long)word);
685*a1bf3f78SToomas Soome 			break;
686*a1bf3f78SToomas Soome 			case FICL_WORDKIND_INSTRUCTION_WITH_ARGUMENT:
687*a1bf3f78SToomas Soome 				c = *++cell;
688*a1bf3f78SToomas Soome 				sprintf(trace, "%s (instruction %ld), with "
689*a1bf3f78SToomas Soome 				    "argument %ld (%#lx)",
690*a1bf3f78SToomas Soome 				    ficlDictionaryInstructionNames[(long)word],
691*a1bf3f78SToomas Soome 				    (long)word, (long)c.i, (unsigned long)c.u);
692*a1bf3f78SToomas Soome 			break;
693*a1bf3f78SToomas Soome 			case FICL_WORDKIND_INSTRUCTION_WORD:
694*a1bf3f78SToomas Soome 				sprintf(trace,
695*a1bf3f78SToomas Soome 				    "%s :: executes %s (instruction word %ld)",
696*a1bf3f78SToomas Soome 				    word->name,
697*a1bf3f78SToomas Soome 				    ficlDictionaryInstructionNames[
698*a1bf3f78SToomas Soome 				    (long)word->code], (long)word->code);
699*a1bf3f78SToomas Soome 			break;
700*a1bf3f78SToomas Soome 			case FICL_WORDKIND_LITERAL:
701*a1bf3f78SToomas Soome 				c = *++cell;
702*a1bf3f78SToomas Soome 				if (ficlDictionaryIsAWord(dictionary, c.p) &&
703*a1bf3f78SToomas Soome 				    (c.i >= ficlInstructionLast)) {
704*a1bf3f78SToomas Soome 					ficlWord *word = (ficlWord *)c.p;
705*a1bf3f78SToomas Soome 					sprintf(trace, "%.*s ( %#lx literal )",
706*a1bf3f78SToomas Soome 					    word->length, word->name,
707*a1bf3f78SToomas Soome 					    (unsigned long)c.u);
708*a1bf3f78SToomas Soome 				} else
709*a1bf3f78SToomas Soome 					sprintf(trace,
710*a1bf3f78SToomas Soome 					    "literal %ld (%#lx)", (long)c.i,
711*a1bf3f78SToomas Soome 					    (unsigned long)c.u);
712*a1bf3f78SToomas Soome 			break;
713*a1bf3f78SToomas Soome 			case FICL_WORDKIND_2LITERAL:
714*a1bf3f78SToomas Soome 				c = *++cell;
715*a1bf3f78SToomas Soome 				c2 = *++cell;
716*a1bf3f78SToomas Soome 				sprintf(trace, "2literal %ld %ld (%#lx %#lx)",
717*a1bf3f78SToomas Soome 				    (long)c2.i, (long)c.i, (unsigned long)c2.u,
718*a1bf3f78SToomas Soome 				    (unsigned long)c.u);
719*a1bf3f78SToomas Soome 			break;
720*a1bf3f78SToomas Soome #if FICL_WANT_FLOAT
721*a1bf3f78SToomas Soome 			case FICL_WORDKIND_FLITERAL:
722*a1bf3f78SToomas Soome 				c = *++cell;
723*a1bf3f78SToomas Soome 				sprintf(trace, "fliteral %f (%#lx)",
724*a1bf3f78SToomas Soome 				    (double)c.f, (unsigned long)c.u);
725*a1bf3f78SToomas Soome 			break;
726*a1bf3f78SToomas Soome #endif /* FICL_WANT_FLOAT */
727*a1bf3f78SToomas Soome 			case FICL_WORDKIND_STRING_LITERAL: {
728*a1bf3f78SToomas Soome 				ficlCountedString *counted;
729*a1bf3f78SToomas Soome 				counted = (ficlCountedString *)(void *)++cell;
730*a1bf3f78SToomas Soome 				cell = (ficlCell *)
731*a1bf3f78SToomas Soome 				    ficlAlignPointer(counted->text +
732*a1bf3f78SToomas Soome 				    counted->length + 1) - 1;
733*a1bf3f78SToomas Soome 				sprintf(trace, "s\" %.*s\"", counted->length,
734*a1bf3f78SToomas Soome 				    counted->text);
735*a1bf3f78SToomas Soome 			}
736*a1bf3f78SToomas Soome 			break;
737*a1bf3f78SToomas Soome 			case FICL_WORDKIND_CSTRING_LITERAL: {
738*a1bf3f78SToomas Soome 				ficlCountedString *counted;
739*a1bf3f78SToomas Soome 				counted = (ficlCountedString *)(void *)++cell;
740*a1bf3f78SToomas Soome 				cell = (ficlCell *)
741*a1bf3f78SToomas Soome 				    ficlAlignPointer(counted->text +
742*a1bf3f78SToomas Soome 				    counted->length + 1) - 1;
743*a1bf3f78SToomas Soome 				sprintf(trace, "c\" %.*s\"", counted->length,
744*a1bf3f78SToomas Soome 				    counted->text);
745*a1bf3f78SToomas Soome 			}
746*a1bf3f78SToomas Soome 			break;
747*a1bf3f78SToomas Soome 			case FICL_WORDKIND_BRANCH0:
748*a1bf3f78SToomas Soome 				c = *++cell;
749*a1bf3f78SToomas Soome 				sprintf(trace, "branch0 %ld",
750*a1bf3f78SToomas Soome 				    (long)(cell + c.i - param0));
751*a1bf3f78SToomas Soome 			break;
752*a1bf3f78SToomas Soome 			case FICL_WORDKIND_BRANCH:
753*a1bf3f78SToomas Soome 				c = *++cell;
754*a1bf3f78SToomas Soome 				sprintf(trace, "branch %ld",
755*a1bf3f78SToomas Soome 				    (long)(cell + c.i - param0));
756*a1bf3f78SToomas Soome 			break;
757*a1bf3f78SToomas Soome 
758*a1bf3f78SToomas Soome 			case FICL_WORDKIND_QDO:
759*a1bf3f78SToomas Soome 				c = *++cell;
760*a1bf3f78SToomas Soome 				sprintf(trace, "?do (leave %ld)",
761*a1bf3f78SToomas Soome 				    (long)((ficlCell *)c.p - param0));
762*a1bf3f78SToomas Soome 			break;
763*a1bf3f78SToomas Soome 			case FICL_WORDKIND_DO:
764*a1bf3f78SToomas Soome 				c = *++cell;
765*a1bf3f78SToomas Soome 				sprintf(trace, "do (leave %ld)",
766*a1bf3f78SToomas Soome 				    (long)((ficlCell *)c.p - param0));
767*a1bf3f78SToomas Soome 			break;
768*a1bf3f78SToomas Soome 			case FICL_WORDKIND_LOOP:
769*a1bf3f78SToomas Soome 				c = *++cell;
770*a1bf3f78SToomas Soome 				sprintf(trace, "loop (branch %ld)",
771*a1bf3f78SToomas Soome 				    (long)(cell + c.i - param0));
772*a1bf3f78SToomas Soome 			break;
773*a1bf3f78SToomas Soome 			case FICL_WORDKIND_OF:
774*a1bf3f78SToomas Soome 				c = *++cell;
775*a1bf3f78SToomas Soome 				sprintf(trace, "of (branch %ld)",
776*a1bf3f78SToomas Soome 				    (long)(cell + c.i - param0));
777*a1bf3f78SToomas Soome 			break;
778*a1bf3f78SToomas Soome 			case FICL_WORDKIND_PLOOP:
779*a1bf3f78SToomas Soome 				c = *++cell;
780*a1bf3f78SToomas Soome 				sprintf(trace, "+loop (branch %ld)",
781*a1bf3f78SToomas Soome 				    (long)(cell + c.i - param0));
782*a1bf3f78SToomas Soome 			break;
783*a1bf3f78SToomas Soome 			default:
784*a1bf3f78SToomas Soome 				sprintf(trace, "%.*s", word->length,
785*a1bf3f78SToomas Soome 				    word->name);
786*a1bf3f78SToomas Soome 			break;
787*a1bf3f78SToomas Soome 			}
788*a1bf3f78SToomas Soome 		} else {
789*a1bf3f78SToomas Soome 			/* probably not a word - punt and print value */
790*a1bf3f78SToomas Soome 			sprintf(trace, "%ld ( %#lx )", (long)cell->i,
791*a1bf3f78SToomas Soome 			    (unsigned long)cell->u);
792*a1bf3f78SToomas Soome 		}
793*a1bf3f78SToomas Soome 
794*a1bf3f78SToomas Soome 		ficlCallbackTextOut(callback, buffer);
795*a1bf3f78SToomas Soome 		ficlCallbackTextOut(callback, "\n");
796*a1bf3f78SToomas Soome 	}
797*a1bf3f78SToomas Soome 
798*a1bf3f78SToomas Soome 	ficlCallbackTextOut(callback, ";\n");
799*a1bf3f78SToomas Soome }
800*a1bf3f78SToomas Soome 
801*a1bf3f78SToomas Soome /*
802*a1bf3f78SToomas Soome  * d i c t R e s e t S e a r c h O r d e r
803*a1bf3f78SToomas Soome  * Initialize the dictionary search order list to sane state
804*a1bf3f78SToomas Soome  */
805*a1bf3f78SToomas Soome void
806*a1bf3f78SToomas Soome ficlDictionaryResetSearchOrder(ficlDictionary *dictionary)
807*a1bf3f78SToomas Soome {
808*a1bf3f78SToomas Soome 	FICL_DICTIONARY_ASSERT(dictionary, dictionary);
809*a1bf3f78SToomas Soome 	dictionary->compilationWordlist = dictionary->forthWordlist;
810*a1bf3f78SToomas Soome 	dictionary->wordlistCount = 1;
811*a1bf3f78SToomas Soome 	dictionary->wordlists[0] = dictionary->forthWordlist;
812*a1bf3f78SToomas Soome }
813*a1bf3f78SToomas Soome 
814*a1bf3f78SToomas Soome /*
815*a1bf3f78SToomas Soome  * d i c t S e t F l a g s
816*a1bf3f78SToomas Soome  * Changes the flags field of the most recently defined word:
817*a1bf3f78SToomas Soome  * Set all bits that are ones in the set parameter.
818*a1bf3f78SToomas Soome  */
819*a1bf3f78SToomas Soome void
820*a1bf3f78SToomas Soome ficlDictionarySetFlags(ficlDictionary *dictionary, ficlUnsigned8 set)
821*a1bf3f78SToomas Soome {
822*a1bf3f78SToomas Soome 	FICL_DICTIONARY_ASSERT(dictionary, dictionary->smudge);
823*a1bf3f78SToomas Soome 	dictionary->smudge->flags |= set;
824*a1bf3f78SToomas Soome }
825*a1bf3f78SToomas Soome 
826*a1bf3f78SToomas Soome 
827*a1bf3f78SToomas Soome /*
828*a1bf3f78SToomas Soome  * d i c t C l e a r F l a g s
829*a1bf3f78SToomas Soome  * Changes the flags field of the most recently defined word:
830*a1bf3f78SToomas Soome  * Clear all bits that are ones in the clear parameter.
831*a1bf3f78SToomas Soome  */
832*a1bf3f78SToomas Soome void
833*a1bf3f78SToomas Soome ficlDictionaryClearFlags(ficlDictionary *dictionary, ficlUnsigned8 clear)
834*a1bf3f78SToomas Soome {
835*a1bf3f78SToomas Soome 	FICL_DICTIONARY_ASSERT(dictionary, dictionary->smudge);
836*a1bf3f78SToomas Soome 	dictionary->smudge->flags &= ~clear;
837*a1bf3f78SToomas Soome }
838*a1bf3f78SToomas Soome 
839*a1bf3f78SToomas Soome /*
840*a1bf3f78SToomas Soome  * d i c t S e t I m m e d i a t e
841*a1bf3f78SToomas Soome  * Set the most recently defined word as IMMEDIATE
842*a1bf3f78SToomas Soome  */
843*a1bf3f78SToomas Soome void
844*a1bf3f78SToomas Soome ficlDictionarySetImmediate(ficlDictionary *dictionary)
845*a1bf3f78SToomas Soome {
846*a1bf3f78SToomas Soome 	FICL_DICTIONARY_ASSERT(dictionary, dictionary->smudge);
847*a1bf3f78SToomas Soome 	dictionary->smudge->flags |= FICL_WORD_IMMEDIATE;
848*a1bf3f78SToomas Soome }
849*a1bf3f78SToomas Soome 
850*a1bf3f78SToomas Soome /*
851*a1bf3f78SToomas Soome  * d i c t U n s m u d g e
852*a1bf3f78SToomas Soome  * Completes the definition of a word by linking it
853*a1bf3f78SToomas Soome  * into the main list
854*a1bf3f78SToomas Soome  */
855*a1bf3f78SToomas Soome void
856*a1bf3f78SToomas Soome ficlDictionaryUnsmudge(ficlDictionary *dictionary)
857*a1bf3f78SToomas Soome {
858*a1bf3f78SToomas Soome 	ficlWord *word = dictionary->smudge;
859*a1bf3f78SToomas Soome 	ficlHash *hash = dictionary->compilationWordlist;
860*a1bf3f78SToomas Soome 
861*a1bf3f78SToomas Soome 	FICL_DICTIONARY_ASSERT(dictionary, hash);
862*a1bf3f78SToomas Soome 	FICL_DICTIONARY_ASSERT(dictionary, word);
863*a1bf3f78SToomas Soome 
864*a1bf3f78SToomas Soome 	/*
865*a1bf3f78SToomas Soome 	 * :noname words never get linked into the list...
866*a1bf3f78SToomas Soome 	 */
867*a1bf3f78SToomas Soome 	if (word->length > 0)
868*a1bf3f78SToomas Soome 		ficlHashInsertWord(hash, word);
869*a1bf3f78SToomas Soome 	word->flags &= ~(FICL_WORD_SMUDGED);
870*a1bf3f78SToomas Soome }
871*a1bf3f78SToomas Soome 
872*a1bf3f78SToomas Soome /*
873*a1bf3f78SToomas Soome  * d i c t W h e r e
874*a1bf3f78SToomas Soome  * Returns the value of the HERE pointer -- the address
875*a1bf3f78SToomas Soome  * of the next free ficlCell in the dictionary
876*a1bf3f78SToomas Soome  */
877*a1bf3f78SToomas Soome ficlCell *
878*a1bf3f78SToomas Soome ficlDictionaryWhere(ficlDictionary *dictionary)
879*a1bf3f78SToomas Soome {
880*a1bf3f78SToomas Soome 	return (dictionary->here);
881*a1bf3f78SToomas Soome }
882