xref: /illumos-gate/usr/src/common/ficl/system.c (revision c0bb4f73)
1afc2ba1dSToomas Soome /*
2afc2ba1dSToomas Soome  * f i c l . c
3afc2ba1dSToomas Soome  * Forth Inspired Command Language - external interface
4afc2ba1dSToomas Soome  * Author: John Sadler (john_sadler@alum.mit.edu)
5afc2ba1dSToomas Soome  * Created: 19 July 1997
6afc2ba1dSToomas Soome  * $Id: system.c,v 1.2 2010/09/10 10:35:54 asau Exp $
7afc2ba1dSToomas Soome  */
8afc2ba1dSToomas Soome /*
9afc2ba1dSToomas Soome  * This is an ANS Forth interpreter written in C.
10afc2ba1dSToomas Soome  * Ficl uses Forth syntax for its commands, but turns the Forth
11afc2ba1dSToomas Soome  * model on its head in other respects.
12afc2ba1dSToomas Soome  * Ficl provides facilities for interoperating
13afc2ba1dSToomas Soome  * with programs written in C: C functions can be exported to Ficl,
14afc2ba1dSToomas Soome  * and Ficl commands can be executed via a C calling interface. The
15afc2ba1dSToomas Soome  * interpreter is re-entrant, so it can be used in multiple instances
16afc2ba1dSToomas Soome  * in a multitasking system. Unlike Forth, Ficl's outer interpreter
17afc2ba1dSToomas Soome  * expects a text block as input, and returns to the caller after each
18afc2ba1dSToomas Soome  * text block, so the data pump is somewhere in external code in the
19afc2ba1dSToomas Soome  * style of TCL.
20afc2ba1dSToomas Soome  *
21afc2ba1dSToomas Soome  * Code is written in ANSI C for portability.
22afc2ba1dSToomas Soome  */
23afc2ba1dSToomas Soome /*
24afc2ba1dSToomas Soome  * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
25afc2ba1dSToomas Soome  * All rights reserved.
26afc2ba1dSToomas Soome  *
27afc2ba1dSToomas Soome  * Get the latest Ficl release at http://ficl.sourceforge.net
28afc2ba1dSToomas Soome  *
29afc2ba1dSToomas Soome  * I am interested in hearing from anyone who uses Ficl. If you have
30afc2ba1dSToomas Soome  * a problem, a success story, a defect, an enhancement request, or
31afc2ba1dSToomas Soome  * if you would like to contribute to the Ficl release, please
32afc2ba1dSToomas Soome  * contact me by email at the address above.
33afc2ba1dSToomas Soome  *
34afc2ba1dSToomas Soome  * L I C E N S E  and  D I S C L A I M E R
35afc2ba1dSToomas Soome  *
36afc2ba1dSToomas Soome  * Redistribution and use in source and binary forms, with or without
37afc2ba1dSToomas Soome  * modification, are permitted provided that the following conditions
38afc2ba1dSToomas Soome  * are met:
39afc2ba1dSToomas Soome  * 1. Redistributions of source code must retain the above copyright
40afc2ba1dSToomas Soome  *    notice, this list of conditions and the following disclaimer.
41afc2ba1dSToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
42afc2ba1dSToomas Soome  *    notice, this list of conditions and the following disclaimer in the
43afc2ba1dSToomas Soome  *    documentation and/or other materials provided with the distribution.
44afc2ba1dSToomas Soome  *
45afc2ba1dSToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
46afc2ba1dSToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
47afc2ba1dSToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
48afc2ba1dSToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
49afc2ba1dSToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
50afc2ba1dSToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
51afc2ba1dSToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
52afc2ba1dSToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
53afc2ba1dSToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
54afc2ba1dSToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55afc2ba1dSToomas Soome  * SUCH DAMAGE.
56afc2ba1dSToomas Soome  */
57afc2ba1dSToomas Soome 
58afc2ba1dSToomas Soome #include "ficl.h"
59afc2ba1dSToomas Soome 
60afc2ba1dSToomas Soome /*
61afc2ba1dSToomas Soome  * System statics
62afc2ba1dSToomas Soome  * Each ficlSystem builds a global dictionary during its start
63afc2ba1dSToomas Soome  * sequence. This is shared by all virtual machines of that system.
64afc2ba1dSToomas Soome  * Therefore only one VM can update the dictionary
65afc2ba1dSToomas Soome  * at a time. The system imports a locking function that
66afc2ba1dSToomas Soome  * you can override in order to control update access to
67afc2ba1dSToomas Soome  * the dictionary. The function is stubbed out by default,
68afc2ba1dSToomas Soome  * but you can insert one: #define FICL_WANT_MULTITHREADED 1
69afc2ba1dSToomas Soome  * and supply your own version of ficlDictionaryLock.
70afc2ba1dSToomas Soome  */
71afc2ba1dSToomas Soome 
72afc2ba1dSToomas Soome ficlSystem *ficlSystemGlobal = NULL;
73afc2ba1dSToomas Soome 
74afc2ba1dSToomas Soome /*
75afc2ba1dSToomas Soome  * f i c l S e t V e r s i o n E n v
76afc2ba1dSToomas Soome  * Create a double ficlCell environment constant for the version ID
77afc2ba1dSToomas Soome  */
78afc2ba1dSToomas Soome static void
ficlSystemSetVersion(ficlSystem * system)79afc2ba1dSToomas Soome ficlSystemSetVersion(ficlSystem *system)
80afc2ba1dSToomas Soome {
81afc2ba1dSToomas Soome 	int major = FICL_VERSION_MAJOR;
82afc2ba1dSToomas Soome 	int minor = FICL_VERSION_MINOR;
83afc2ba1dSToomas Soome 	ficl2Integer combined;
84afc2ba1dSToomas Soome 	ficlDictionary *environment = ficlSystemGetEnvironment(system);
85afc2ba1dSToomas Soome 	FICL_2INTEGER_SET(major, minor, combined);
86*c0bb4f73SToomas Soome 	(void) ficlDictionarySet2Constant(environment, "ficl-version",
87*c0bb4f73SToomas Soome 	    combined);
88*c0bb4f73SToomas Soome 	(void) ficlDictionarySetConstant(environment, "ficl-robust",
89*c0bb4f73SToomas Soome 	    FICL_ROBUST);
90afc2ba1dSToomas Soome }
91afc2ba1dSToomas Soome 
92afc2ba1dSToomas Soome /*
93afc2ba1dSToomas Soome  * f i c l I n i t S y s t e m
94afc2ba1dSToomas Soome  * Binds a global dictionary to the interpreter system.
95afc2ba1dSToomas Soome  * You specify the address and size of the allocated area.
96afc2ba1dSToomas Soome  * After that, Ficl manages it.
97afc2ba1dSToomas Soome  * First step is to set up the static pointers to the area.
98afc2ba1dSToomas Soome  * Then write the "precompiled" portion of the dictionary in.
99afc2ba1dSToomas Soome  * The dictionary needs to be at least large enough to hold the
100afc2ba1dSToomas Soome  * precompiled part. Try 1K cells minimum. Use "words" to find
101afc2ba1dSToomas Soome  * out how much of the dictionary is used at any time.
102afc2ba1dSToomas Soome  */
103afc2ba1dSToomas Soome ficlSystem *
ficlSystemCreate(ficlSystemInformation * fsi)104afc2ba1dSToomas Soome ficlSystemCreate(ficlSystemInformation *fsi)
105afc2ba1dSToomas Soome {
106afc2ba1dSToomas Soome 	ficlInteger dictionarySize;
107afc2ba1dSToomas Soome 	ficlInteger environmentSize;
108afc2ba1dSToomas Soome 	ficlInteger stackSize;
109afc2ba1dSToomas Soome 	ficlSystem *system;
110afc2ba1dSToomas Soome 	ficlCallback callback;
111afc2ba1dSToomas Soome 	ficlSystemInformation fauxInfo;
112afc2ba1dSToomas Soome 	ficlDictionary *environment;
113afc2ba1dSToomas Soome 
114afc2ba1dSToomas Soome 	if (fsi == NULL) {
115afc2ba1dSToomas Soome 		fsi = &fauxInfo;
116afc2ba1dSToomas Soome 		ficlSystemInformationInitialize(fsi);
117afc2ba1dSToomas Soome 	}
118afc2ba1dSToomas Soome 
119afc2ba1dSToomas Soome 	callback.context = fsi->context;
120afc2ba1dSToomas Soome 	callback.textOut = fsi->textOut;
121afc2ba1dSToomas Soome 	callback.errorOut = fsi->errorOut;
122afc2ba1dSToomas Soome 	callback.system = NULL;
123afc2ba1dSToomas Soome 	callback.vm = NULL;
124afc2ba1dSToomas Soome 
125afc2ba1dSToomas Soome 	FICL_ASSERT(&callback, sizeof (ficlInteger) >= sizeof (void *));
126afc2ba1dSToomas Soome 	FICL_ASSERT(&callback, sizeof (ficlUnsigned) >= sizeof (void *));
127afc2ba1dSToomas Soome #if (FICL_WANT_FLOAT)
128afc2ba1dSToomas Soome 	FICL_ASSERT(&callback, sizeof (ficlFloat) <= sizeof (ficlInteger));
129afc2ba1dSToomas Soome #endif
130afc2ba1dSToomas Soome 
131afc2ba1dSToomas Soome 	system = ficlMalloc(sizeof (ficlSystem));
132afc2ba1dSToomas Soome 
133afc2ba1dSToomas Soome 	FICL_ASSERT(&callback, system);
134afc2ba1dSToomas Soome 
135afc2ba1dSToomas Soome 	memset(system, 0, sizeof (ficlSystem));
136afc2ba1dSToomas Soome 
137afc2ba1dSToomas Soome 	dictionarySize = fsi->dictionarySize;
138afc2ba1dSToomas Soome 	if (dictionarySize <= 0)
139afc2ba1dSToomas Soome 		dictionarySize = FICL_DEFAULT_DICTIONARY_SIZE;
140afc2ba1dSToomas Soome 
141afc2ba1dSToomas Soome 	environmentSize = fsi->environmentSize;
142afc2ba1dSToomas Soome 	if (environmentSize <= 0)
143afc2ba1dSToomas Soome 		environmentSize = FICL_DEFAULT_ENVIRONMENT_SIZE;
144afc2ba1dSToomas Soome 
145afc2ba1dSToomas Soome 	stackSize = fsi->stackSize;
146afc2ba1dSToomas Soome 	if (stackSize < FICL_DEFAULT_STACK_SIZE)
147afc2ba1dSToomas Soome 		stackSize = FICL_DEFAULT_STACK_SIZE;
148afc2ba1dSToomas Soome 
149afc2ba1dSToomas Soome 	system->dictionary = ficlDictionaryCreateHashed(system,
150afc2ba1dSToomas Soome 	    (unsigned)dictionarySize, FICL_HASH_SIZE);
151afc2ba1dSToomas Soome 	system->dictionary->forthWordlist->name = "forth-wordlist";
152afc2ba1dSToomas Soome 
153afc2ba1dSToomas Soome 	environment = ficlDictionaryCreate(system, (unsigned)environmentSize);
154afc2ba1dSToomas Soome 	system->environment = environment;
155afc2ba1dSToomas Soome 	system->environment->forthWordlist->name = "environment";
156afc2ba1dSToomas Soome 
157afc2ba1dSToomas Soome 	system->callback.textOut = fsi->textOut;
158afc2ba1dSToomas Soome 	system->callback.errorOut = fsi->errorOut;
159afc2ba1dSToomas Soome 	system->callback.context = fsi->context;
160afc2ba1dSToomas Soome 	system->callback.system = system;
161afc2ba1dSToomas Soome 	system->callback.vm = NULL;
162afc2ba1dSToomas Soome 	system->stackSize = stackSize;
163afc2ba1dSToomas Soome 
164afc2ba1dSToomas Soome #if FICL_WANT_LOCALS
165afc2ba1dSToomas Soome 	/*
166afc2ba1dSToomas Soome 	 * The locals dictionary is only searched while compiling,
167afc2ba1dSToomas Soome 	 * but this is where speed is most important. On the other
168afc2ba1dSToomas Soome 	 * hand, the dictionary gets emptied after each use of locals
169afc2ba1dSToomas Soome 	 * The need to balance search speed with the cost of the 'empty'
170afc2ba1dSToomas Soome 	 * operation led me to select a single-threaded list...
171afc2ba1dSToomas Soome 	 */
172afc2ba1dSToomas Soome 	system->locals = ficlDictionaryCreate(system,
173afc2ba1dSToomas Soome 	    (unsigned)FICL_MAX_LOCALS * FICL_CELLS_PER_WORD);
174afc2ba1dSToomas Soome #endif /* FICL_WANT_LOCALS */
175afc2ba1dSToomas Soome 
176afc2ba1dSToomas Soome 	/*
177afc2ba1dSToomas Soome 	 * Build the precompiled dictionary and load softwords. We need
178afc2ba1dSToomas Soome 	 * a temporary VM to do this - ficlNewVM links one to the head of
179afc2ba1dSToomas Soome 	 * the system VM list. ficlCompilePlatform (defined in win32.c,
180afc2ba1dSToomas Soome 	 * for example) adds platform specific words.
181afc2ba1dSToomas Soome 	 */
182afc2ba1dSToomas Soome 	ficlSystemCompileCore(system);
183afc2ba1dSToomas Soome 	ficlSystemCompilePrefix(system);
184afc2ba1dSToomas Soome 
185afc2ba1dSToomas Soome #if FICL_WANT_FLOAT
186afc2ba1dSToomas Soome 	ficlSystemCompileFloat(system);
187afc2ba1dSToomas Soome #endif /* FICL_WANT_FLOAT */
188afc2ba1dSToomas Soome 
189afc2ba1dSToomas Soome #if FICL_WANT_PLATFORM
190afc2ba1dSToomas Soome 	ficlSystemCompilePlatform(system);
191afc2ba1dSToomas Soome #endif /* FICL_WANT_PLATFORM */
192afc2ba1dSToomas Soome 
193afc2ba1dSToomas Soome 	ficlSystemSetVersion(system);
194afc2ba1dSToomas Soome 
195afc2ba1dSToomas Soome 	/*
196afc2ba1dSToomas Soome 	 * Establish the parse order. Note that prefixes precede numbers -
197afc2ba1dSToomas Soome 	 * this allows constructs like "0b101010" which might parse as a
198afc2ba1dSToomas Soome 	 * hex value otherwise.
199afc2ba1dSToomas Soome 	 */
200afc2ba1dSToomas Soome 	ficlSystemAddPrimitiveParseStep(system, "?word", ficlVmParseWord);
201afc2ba1dSToomas Soome 	ficlSystemAddPrimitiveParseStep(system, "?prefix", ficlVmParsePrefix);
202afc2ba1dSToomas Soome 	ficlSystemAddPrimitiveParseStep(system, "?number", ficlVmParseNumber);
203afc2ba1dSToomas Soome #if FICL_WANT_FLOAT
204afc2ba1dSToomas Soome 	ficlSystemAddPrimitiveParseStep(system, "?float",
205afc2ba1dSToomas Soome 	    ficlVmParseFloatNumber);
206afc2ba1dSToomas Soome #endif
207afc2ba1dSToomas Soome 
208afc2ba1dSToomas Soome 	/*
209afc2ba1dSToomas Soome 	 * Now create a temporary VM to compile the softwords. Since all VMs
210afc2ba1dSToomas Soome 	 * are linked into the vmList of ficlSystem, we don't have to pass
211afc2ba1dSToomas Soome 	 * the VM to ficlCompileSoftCore -- it just hijacks whatever it finds
212afc2ba1dSToomas Soome 	 * in the VM list. Ficl 2.05: vmCreate no longer depends on the
213afc2ba1dSToomas Soome 	 * presence of INTERPRET in the dictionary, so a VM can be created
214afc2ba1dSToomas Soome 	 * before the dictionary is built. It just can't do much...
215afc2ba1dSToomas Soome 	 */
216*c0bb4f73SToomas Soome 	(void) ficlSystemCreateVm(system);
217afc2ba1dSToomas Soome #define	ADD_COMPILE_FLAG(name)	\
218*c0bb4f73SToomas Soome 	(void) ficlDictionarySetConstant(environment, #name, name)
219afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_LZ4_SOFTCORE);
220afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_FILE);
221afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_FLOAT);
222afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_DEBUGGER);
223afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_EXTENDED_PREFIX);
224afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_USER);
225afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_LOCALS);
226afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_OOP);
227afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_SOFTWORDS);
228afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_MULTITHREADED);
229afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_OPTIMIZE);
230afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_WANT_VCALL);
231afc2ba1dSToomas Soome 
232afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_PLATFORM_ALIGNMENT);
233afc2ba1dSToomas Soome 
234afc2ba1dSToomas Soome 	ADD_COMPILE_FLAG(FICL_ROBUST);
235afc2ba1dSToomas Soome 
236afc2ba1dSToomas Soome #define	ADD_COMPILE_STRING(name)	\
237*c0bb4f73SToomas Soome 	(void) ficlDictionarySetConstantString(environment, #name, name)
238afc2ba1dSToomas Soome 	ADD_COMPILE_STRING(FICL_PLATFORM_ARCHITECTURE);
239afc2ba1dSToomas Soome 	ADD_COMPILE_STRING(FICL_PLATFORM_OS);
240afc2ba1dSToomas Soome 
241afc2ba1dSToomas Soome 	ficlSystemCompileSoftCore(system);
242afc2ba1dSToomas Soome 	ficlSystemDestroyVm(system->vmList);
243afc2ba1dSToomas Soome 
244afc2ba1dSToomas Soome 	if (ficlSystemGlobal == NULL)
245afc2ba1dSToomas Soome 		ficlSystemGlobal = system;
246afc2ba1dSToomas Soome 
247afc2ba1dSToomas Soome 	return (system);
248afc2ba1dSToomas Soome }
249afc2ba1dSToomas Soome 
250afc2ba1dSToomas Soome /*
251afc2ba1dSToomas Soome  * f i c l T e r m S y s t e m
252afc2ba1dSToomas Soome  * Tear the system down by deleting the dictionaries and all VMs.
253afc2ba1dSToomas Soome  * This saves you from having to keep track of all that stuff.
254afc2ba1dSToomas Soome  */
255afc2ba1dSToomas Soome void
ficlSystemDestroy(ficlSystem * system)256afc2ba1dSToomas Soome ficlSystemDestroy(ficlSystem *system)
257afc2ba1dSToomas Soome {
258afc2ba1dSToomas Soome 	if (system->dictionary)
259afc2ba1dSToomas Soome 		ficlDictionaryDestroy(system->dictionary);
260afc2ba1dSToomas Soome 	system->dictionary = NULL;
261afc2ba1dSToomas Soome 
262afc2ba1dSToomas Soome 	if (system->environment)
263afc2ba1dSToomas Soome 		ficlDictionaryDestroy(system->environment);
264afc2ba1dSToomas Soome 	system->environment = NULL;
265afc2ba1dSToomas Soome 
266afc2ba1dSToomas Soome #if FICL_WANT_LOCALS
267afc2ba1dSToomas Soome 	if (system->locals)
268afc2ba1dSToomas Soome 		ficlDictionaryDestroy(system->locals);
269afc2ba1dSToomas Soome 	system->locals = NULL;
270afc2ba1dSToomas Soome #endif
271afc2ba1dSToomas Soome 
272afc2ba1dSToomas Soome 	while (system->vmList != NULL) {
273afc2ba1dSToomas Soome 		ficlVm *vm = system->vmList;
274afc2ba1dSToomas Soome 		system->vmList = system->vmList->link;
275afc2ba1dSToomas Soome 		ficlVmDestroy(vm);
276afc2ba1dSToomas Soome 	}
277afc2ba1dSToomas Soome 
278afc2ba1dSToomas Soome 	if (ficlSystemGlobal == system)
279afc2ba1dSToomas Soome 		ficlSystemGlobal = NULL;
280afc2ba1dSToomas Soome 
281afc2ba1dSToomas Soome 	ficlFree(system);
282afc2ba1dSToomas Soome 	system = NULL;
283afc2ba1dSToomas Soome }
284afc2ba1dSToomas Soome 
285afc2ba1dSToomas Soome /*
286afc2ba1dSToomas Soome  * f i c l A d d P a r s e S t e p
287afc2ba1dSToomas Soome  * Appends a parse step function to the end of the parse list (see
288afc2ba1dSToomas Soome  * ficlParseStep notes in ficl.h for details). Returns 0 if successful,
289afc2ba1dSToomas Soome  * nonzero if there's no more room in the list.
290afc2ba1dSToomas Soome  */
291afc2ba1dSToomas Soome int
ficlSystemAddParseStep(ficlSystem * system,ficlWord * word)292afc2ba1dSToomas Soome ficlSystemAddParseStep(ficlSystem *system, ficlWord *word)
293afc2ba1dSToomas Soome {
294afc2ba1dSToomas Soome 	int i;
295afc2ba1dSToomas Soome 	for (i = 0; i < FICL_MAX_PARSE_STEPS; i++) {
296afc2ba1dSToomas Soome 		if (system->parseList[i] == NULL) {
297afc2ba1dSToomas Soome 			system->parseList[i] = word;
298afc2ba1dSToomas Soome 			return (0);
299afc2ba1dSToomas Soome 		}
300afc2ba1dSToomas Soome 	}
301afc2ba1dSToomas Soome 
302afc2ba1dSToomas Soome 	return (1);
303afc2ba1dSToomas Soome }
304afc2ba1dSToomas Soome 
305afc2ba1dSToomas Soome /*
306afc2ba1dSToomas Soome  * Compile a word into the dictionary that invokes the specified ficlParseStep
307afc2ba1dSToomas Soome  * function. It is up to the user (as usual in Forth) to make sure the stack
308afc2ba1dSToomas Soome  * preconditions are valid (there needs to be a counted string on top of the
309afc2ba1dSToomas Soome  * stack) before using the resulting word.
310afc2ba1dSToomas Soome  */
311afc2ba1dSToomas Soome void
ficlSystemAddPrimitiveParseStep(ficlSystem * system,char * name,ficlParseStep pStep)312afc2ba1dSToomas Soome ficlSystemAddPrimitiveParseStep(ficlSystem *system, char *name,
313afc2ba1dSToomas Soome     ficlParseStep pStep)
314afc2ba1dSToomas Soome {
315afc2ba1dSToomas Soome 	ficlDictionary *dictionary = system->dictionary;
316afc2ba1dSToomas Soome 	ficlWord *word;
317afc2ba1dSToomas Soome 	ficlCell c;
318afc2ba1dSToomas Soome 
319afc2ba1dSToomas Soome 	word = ficlDictionaryAppendPrimitive(dictionary, name,
320afc2ba1dSToomas Soome 	    ficlPrimitiveParseStepParen, FICL_WORD_DEFAULT);
321afc2ba1dSToomas Soome 
322afc2ba1dSToomas Soome 	c.fn = (void (*)(void))pStep;
323afc2ba1dSToomas Soome 	ficlDictionaryAppendCell(dictionary, c);
324*c0bb4f73SToomas Soome 	(void) ficlSystemAddParseStep(system, word);
325afc2ba1dSToomas Soome }
326afc2ba1dSToomas Soome 
327afc2ba1dSToomas Soome /*
328afc2ba1dSToomas Soome  * f i c l N e w V M
329afc2ba1dSToomas Soome  * Create a new virtual machine and link it into the system list
330afc2ba1dSToomas Soome  * of VMs for later cleanup by ficlTermSystem.
331afc2ba1dSToomas Soome  */
332afc2ba1dSToomas Soome ficlVm *
ficlSystemCreateVm(ficlSystem * system)333afc2ba1dSToomas Soome ficlSystemCreateVm(ficlSystem *system)
334afc2ba1dSToomas Soome {
335afc2ba1dSToomas Soome 	ficlVm *vm = ficlVmCreate(NULL, system->stackSize, system->stackSize);
336afc2ba1dSToomas Soome 	vm->link = system->vmList;
337afc2ba1dSToomas Soome 
338afc2ba1dSToomas Soome 	memcpy(&(vm->callback), &(system->callback), sizeof (system->callback));
339afc2ba1dSToomas Soome 	vm->callback.vm = vm;
340afc2ba1dSToomas Soome 	vm->callback.system = system;
341afc2ba1dSToomas Soome 
342afc2ba1dSToomas Soome 	system->vmList = vm;
343afc2ba1dSToomas Soome 	return (vm);
344afc2ba1dSToomas Soome }
345afc2ba1dSToomas Soome 
346afc2ba1dSToomas Soome /*
347afc2ba1dSToomas Soome  * f i c l F r e e V M
348afc2ba1dSToomas Soome  * Removes the VM in question from the system VM list and deletes the
349afc2ba1dSToomas Soome  * memory allocated to it. This is an optional call, since ficlTermSystem
350afc2ba1dSToomas Soome  * will do this cleanup for you. This function is handy if you're going to
351afc2ba1dSToomas Soome  * do a lot of dynamic creation of VMs.
352afc2ba1dSToomas Soome  */
353afc2ba1dSToomas Soome void
ficlSystemDestroyVm(ficlVm * vm)354afc2ba1dSToomas Soome ficlSystemDestroyVm(ficlVm *vm)
355afc2ba1dSToomas Soome {
356afc2ba1dSToomas Soome 	ficlSystem *system = vm->callback.system;
357afc2ba1dSToomas Soome 	ficlVm *pList = system->vmList;
358afc2ba1dSToomas Soome 
359afc2ba1dSToomas Soome 	FICL_VM_ASSERT(vm, vm != NULL);
360afc2ba1dSToomas Soome 
361afc2ba1dSToomas Soome 	if (system->vmList == vm) {
362afc2ba1dSToomas Soome 		system->vmList = system->vmList->link;
363afc2ba1dSToomas Soome 	} else
364afc2ba1dSToomas Soome 		for (; pList != NULL; pList = pList->link) {
365afc2ba1dSToomas Soome 			if (pList->link == vm) {
366afc2ba1dSToomas Soome 				pList->link = vm->link;
367afc2ba1dSToomas Soome 				break;
368afc2ba1dSToomas Soome 			}
369afc2ba1dSToomas Soome 		}
370afc2ba1dSToomas Soome 
371afc2ba1dSToomas Soome 	if (pList)
372afc2ba1dSToomas Soome 		ficlVmDestroy(vm);
373afc2ba1dSToomas Soome }
374afc2ba1dSToomas Soome 
375afc2ba1dSToomas Soome /*
376afc2ba1dSToomas Soome  * f i c l L o o k u p
377afc2ba1dSToomas Soome  * Look in the system dictionary for a match to the given name. If
378afc2ba1dSToomas Soome  * found, return the address of the corresponding ficlWord. Otherwise
379afc2ba1dSToomas Soome  * return NULL.
380afc2ba1dSToomas Soome  */
381afc2ba1dSToomas Soome ficlWord *
ficlSystemLookup(ficlSystem * system,char * name)382afc2ba1dSToomas Soome ficlSystemLookup(ficlSystem *system, char *name)
383afc2ba1dSToomas Soome {
384afc2ba1dSToomas Soome 	ficlString s;
385afc2ba1dSToomas Soome 	FICL_STRING_SET_FROM_CSTRING(s, name);
386afc2ba1dSToomas Soome 	return (ficlDictionaryLookup(system->dictionary, s));
387afc2ba1dSToomas Soome }
388afc2ba1dSToomas Soome 
389afc2ba1dSToomas Soome /*
390afc2ba1dSToomas Soome  * f i c l G e t D i c t
391afc2ba1dSToomas Soome  * Returns the address of the system dictionary
392afc2ba1dSToomas Soome  */
393afc2ba1dSToomas Soome ficlDictionary *
ficlSystemGetDictionary(ficlSystem * system)394afc2ba1dSToomas Soome ficlSystemGetDictionary(ficlSystem *system)
395afc2ba1dSToomas Soome {
396afc2ba1dSToomas Soome 	return (system->dictionary);
397afc2ba1dSToomas Soome }
398afc2ba1dSToomas Soome 
399afc2ba1dSToomas Soome /*
400afc2ba1dSToomas Soome  * f i c l G e t E n v
401afc2ba1dSToomas Soome  * Returns the address of the system environment space
402afc2ba1dSToomas Soome  */
403afc2ba1dSToomas Soome ficlDictionary *
ficlSystemGetEnvironment(ficlSystem * system)404afc2ba1dSToomas Soome ficlSystemGetEnvironment(ficlSystem *system)
405afc2ba1dSToomas Soome {
406afc2ba1dSToomas Soome 	return (system->environment);
407afc2ba1dSToomas Soome }
408afc2ba1dSToomas Soome 
409afc2ba1dSToomas Soome /*
410afc2ba1dSToomas Soome  * f i c l G e t L o c
411afc2ba1dSToomas Soome  * Returns the address of the system locals dictionary. This dictionary is
412afc2ba1dSToomas Soome  * only used during compilation, and is shared by all VMs.
413afc2ba1dSToomas Soome  */
414afc2ba1dSToomas Soome #if FICL_WANT_LOCALS
415afc2ba1dSToomas Soome ficlDictionary *
ficlSystemGetLocals(ficlSystem * system)416afc2ba1dSToomas Soome ficlSystemGetLocals(ficlSystem *system)
417afc2ba1dSToomas Soome {
418afc2ba1dSToomas Soome 	return (system->locals);
419afc2ba1dSToomas Soome }
420afc2ba1dSToomas Soome #endif
421afc2ba1dSToomas Soome 
422afc2ba1dSToomas Soome /*
423afc2ba1dSToomas Soome  * f i c l L o o k u p L o c
424afc2ba1dSToomas Soome  * Same as dictLookup, but looks in system locals dictionary first...
425afc2ba1dSToomas Soome  * Assumes locals dictionary has only one wordlist...
426afc2ba1dSToomas Soome  */
427afc2ba1dSToomas Soome #if FICL_WANT_LOCALS
428afc2ba1dSToomas Soome ficlWord *
ficlSystemLookupLocal(ficlSystem * system,ficlString name)429afc2ba1dSToomas Soome ficlSystemLookupLocal(ficlSystem *system, ficlString name)
430afc2ba1dSToomas Soome {
431afc2ba1dSToomas Soome 	ficlWord *word = NULL;
432afc2ba1dSToomas Soome 	ficlDictionary *dictionary = system->dictionary;
433afc2ba1dSToomas Soome 	ficlHash *hash = ficlSystemGetLocals(system)->forthWordlist;
434afc2ba1dSToomas Soome 	int i;
435afc2ba1dSToomas Soome 	ficlUnsigned16 hashCode = ficlHashCode(name);
436afc2ba1dSToomas Soome 
437afc2ba1dSToomas Soome 	FICL_SYSTEM_ASSERT(system, hash);
438afc2ba1dSToomas Soome 	FICL_SYSTEM_ASSERT(system, dictionary);
439afc2ba1dSToomas Soome 
440afc2ba1dSToomas Soome 	ficlDictionaryLock(dictionary, FICL_TRUE);
441afc2ba1dSToomas Soome 	/*
442afc2ba1dSToomas Soome 	 * check the locals dictionary first...
443afc2ba1dSToomas Soome 	 */
444afc2ba1dSToomas Soome 	word = ficlHashLookup(hash, name, hashCode);
445afc2ba1dSToomas Soome 
446afc2ba1dSToomas Soome 	/*
447afc2ba1dSToomas Soome 	 * If no joy, (!word) ------------------------------v
448afc2ba1dSToomas Soome 	 * iterate over the search list in the main dictionary
449afc2ba1dSToomas Soome 	 */
450afc2ba1dSToomas Soome 	for (i = (int)dictionary->wordlistCount - 1; (i >= 0) && (!word); --i) {
451afc2ba1dSToomas Soome 		hash = dictionary->wordlists[i];
452afc2ba1dSToomas Soome 		word = ficlHashLookup(hash, name, hashCode);
453afc2ba1dSToomas Soome 	}
454afc2ba1dSToomas Soome 
455afc2ba1dSToomas Soome 	ficlDictionaryLock(dictionary, FICL_FALSE);
456afc2ba1dSToomas Soome 	return (word);
457afc2ba1dSToomas Soome }
458afc2ba1dSToomas Soome #endif
459