xref: /titanic_52/usr/src/common/ficl/prefix.c (revision a1bf3f785ae05c419b339c3a2061f2b18c024f61)
1*a1bf3f78SToomas Soome /*
2*a1bf3f78SToomas Soome  * p r e f i x . c
3*a1bf3f78SToomas Soome  * Forth Inspired Command Language
4*a1bf3f78SToomas Soome  * Parser extensions for Ficl
5*a1bf3f78SToomas Soome  * Authors: Larry Hastings & John Sadler (john_sadler@alum.mit.edu)
6*a1bf3f78SToomas Soome  * Created: April 2001
7*a1bf3f78SToomas Soome  * $Id: prefix.c,v 1.8 2010/09/13 18:43:04 asau Exp $
8*a1bf3f78SToomas Soome  */
9*a1bf3f78SToomas Soome /*
10*a1bf3f78SToomas Soome  * Copyright (c) 1997-2001 John Sadler (john_sadler@alum.mit.edu)
11*a1bf3f78SToomas Soome  * All rights reserved.
12*a1bf3f78SToomas Soome  *
13*a1bf3f78SToomas Soome  * Get the latest Ficl release at http://ficl.sourceforge.net
14*a1bf3f78SToomas Soome  *
15*a1bf3f78SToomas Soome  * I am interested in hearing from anyone who uses Ficl. If you have
16*a1bf3f78SToomas Soome  * a problem, a success story, a defect, an enhancement request, or
17*a1bf3f78SToomas Soome  * if you would like to contribute to the Ficl release, please
18*a1bf3f78SToomas Soome  * contact me by email at the address above.
19*a1bf3f78SToomas Soome  *
20*a1bf3f78SToomas Soome  * L I C E N S E  and  D I S C L A I M E R
21*a1bf3f78SToomas Soome  *
22*a1bf3f78SToomas Soome  * Redistribution and use in source and binary forms, with or without
23*a1bf3f78SToomas Soome  * modification, are permitted provided that the following conditions
24*a1bf3f78SToomas Soome  * are met:
25*a1bf3f78SToomas Soome  * 1. Redistributions of source code must retain the above copyright
26*a1bf3f78SToomas Soome  *    notice, this list of conditions and the following disclaimer.
27*a1bf3f78SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
28*a1bf3f78SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
29*a1bf3f78SToomas Soome  *    documentation and/or other materials provided with the distribution.
30*a1bf3f78SToomas Soome  *
31*a1bf3f78SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
32*a1bf3f78SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33*a1bf3f78SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34*a1bf3f78SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
35*a1bf3f78SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*a1bf3f78SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*a1bf3f78SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*a1bf3f78SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39*a1bf3f78SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40*a1bf3f78SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41*a1bf3f78SToomas Soome  * SUCH DAMAGE.
42*a1bf3f78SToomas Soome  */
43*a1bf3f78SToomas Soome 
44*a1bf3f78SToomas Soome #include "ficl.h"
45*a1bf3f78SToomas Soome 
46*a1bf3f78SToomas Soome /*
47*a1bf3f78SToomas Soome  * (jws) revisions:
48*a1bf3f78SToomas Soome  * A prefix is a word in a dedicated wordlist (name stored in list_name below)
49*a1bf3f78SToomas Soome  * that is searched in a special way by the prefix parse step. When a prefix
50*a1bf3f78SToomas Soome  * matches the beginning of an incoming token, push the non-prefix part of the
51*a1bf3f78SToomas Soome  * token back onto the input stream and execute the prefix code.
52*a1bf3f78SToomas Soome  *
53*a1bf3f78SToomas Soome  * The parse step is called ficlParsePrefix.
54*a1bf3f78SToomas Soome  * Storing prefix entries in the dictionary greatly simplifies
55*a1bf3f78SToomas Soome  * the process of matching and dispatching prefixes, avoids the
56*a1bf3f78SToomas Soome  * need to clean up a dynamically allocated prefix list when the system
57*a1bf3f78SToomas Soome  * goes away, but still allows prefixes to be allocated at runtime.
58*a1bf3f78SToomas Soome  */
59*a1bf3f78SToomas Soome 
60*a1bf3f78SToomas Soome static char list_name[] = "<prefixes>";
61*a1bf3f78SToomas Soome 
62*a1bf3f78SToomas Soome /*
63*a1bf3f78SToomas Soome  * f i c l P a r s e P r e f i x
64*a1bf3f78SToomas Soome  * This is the parse step for prefixes - it checks an incoming word
65*a1bf3f78SToomas Soome  * to see if it starts with a prefix, and if so runs the corresponding
66*a1bf3f78SToomas Soome  * code against the remainder of the word and returns true.
67*a1bf3f78SToomas Soome  */
68*a1bf3f78SToomas Soome int
69*a1bf3f78SToomas Soome ficlVmParsePrefix(ficlVm *vm, ficlString s)
70*a1bf3f78SToomas Soome {
71*a1bf3f78SToomas Soome 	int i;
72*a1bf3f78SToomas Soome 	ficlHash *hash;
73*a1bf3f78SToomas Soome 	ficlWord *word = ficlSystemLookup(vm->callback.system, list_name);
74*a1bf3f78SToomas Soome 
75*a1bf3f78SToomas Soome 	/*
76*a1bf3f78SToomas Soome 	 * Make sure we found the prefix dictionary - otherwise silently fail
77*a1bf3f78SToomas Soome 	 * If forth-wordlist is not in the search order, we won't find the
78*a1bf3f78SToomas Soome 	 * prefixes.
79*a1bf3f78SToomas Soome 	 */
80*a1bf3f78SToomas Soome 	if (!word)
81*a1bf3f78SToomas Soome 		return (0); /* false */
82*a1bf3f78SToomas Soome 
83*a1bf3f78SToomas Soome 	hash = (ficlHash *)(word->param[0].p);
84*a1bf3f78SToomas Soome 	/*
85*a1bf3f78SToomas Soome 	 * Walk the list looking for a match with the beginning of the
86*a1bf3f78SToomas Soome 	 * incoming token
87*a1bf3f78SToomas Soome 	 */
88*a1bf3f78SToomas Soome 	for (i = 0; i < (int)hash->size; i++) {
89*a1bf3f78SToomas Soome 		word = hash->table[i];
90*a1bf3f78SToomas Soome 		while (word != NULL) {
91*a1bf3f78SToomas Soome 			int n;
92*a1bf3f78SToomas Soome 			n = word->length;
93*a1bf3f78SToomas Soome 			/*
94*a1bf3f78SToomas Soome 			 * If we find a match, adjust the TIB to give back
95*a1bf3f78SToomas Soome 			 * the non-prefix characters and execute the prefix
96*a1bf3f78SToomas Soome 			 * word.
97*a1bf3f78SToomas Soome 			 */
98*a1bf3f78SToomas Soome 			if (!ficlStrincmp(FICL_STRING_GET_POINTER(s),
99*a1bf3f78SToomas Soome 			    word->name, (ficlUnsigned)n)) {
100*a1bf3f78SToomas Soome 				/*
101*a1bf3f78SToomas Soome 				 * (sadler) fixed off-by-one error when the
102*a1bf3f78SToomas Soome 				 * token has no trailing space in the TIB
103*a1bf3f78SToomas Soome 				 */
104*a1bf3f78SToomas Soome 				ficlVmSetTibIndex(vm,
105*a1bf3f78SToomas Soome 				    s.text + n - vm->tib.text);
106*a1bf3f78SToomas Soome 				ficlVmExecuteWord(vm, word);
107*a1bf3f78SToomas Soome 
108*a1bf3f78SToomas Soome 				return (1); /* true */
109*a1bf3f78SToomas Soome 			}
110*a1bf3f78SToomas Soome 			word = word->link;
111*a1bf3f78SToomas Soome 		}
112*a1bf3f78SToomas Soome 	}
113*a1bf3f78SToomas Soome 
114*a1bf3f78SToomas Soome 	return (0); /* false */
115*a1bf3f78SToomas Soome }
116*a1bf3f78SToomas Soome 
117*a1bf3f78SToomas Soome static void
118*a1bf3f78SToomas Soome ficlPrimitiveTempBase(ficlVm *vm)
119*a1bf3f78SToomas Soome {
120*a1bf3f78SToomas Soome 	int oldbase = vm->base;
121*a1bf3f78SToomas Soome 	ficlString number = ficlVmGetWord0(vm);
122*a1bf3f78SToomas Soome 	int base = ficlStackPopInteger(vm->dataStack);
123*a1bf3f78SToomas Soome 
124*a1bf3f78SToomas Soome 	vm->base = base;
125*a1bf3f78SToomas Soome 	if (!ficlVmParseNumber(vm, number))
126*a1bf3f78SToomas Soome 		ficlVmThrowError(vm, "%.*s not recognized",
127*a1bf3f78SToomas Soome 		    FICL_STRING_GET_LENGTH(number),
128*a1bf3f78SToomas Soome 		    FICL_STRING_GET_POINTER(number));
129*a1bf3f78SToomas Soome 
130*a1bf3f78SToomas Soome 	vm->base = oldbase;
131*a1bf3f78SToomas Soome }
132*a1bf3f78SToomas Soome 
133*a1bf3f78SToomas Soome /*
134*a1bf3f78SToomas Soome  * f i c l C o m p i l e P r e f i x
135*a1bf3f78SToomas Soome  * Build prefix support into the dictionary and the parser
136*a1bf3f78SToomas Soome  * Note: since prefixes always execute, they are effectively IMMEDIATE.
137*a1bf3f78SToomas Soome  * If they need to generate code in compile state you must add
138*a1bf3f78SToomas Soome  * this code explicitly.
139*a1bf3f78SToomas Soome  */
140*a1bf3f78SToomas Soome void
141*a1bf3f78SToomas Soome ficlSystemCompilePrefix(ficlSystem *system)
142*a1bf3f78SToomas Soome {
143*a1bf3f78SToomas Soome 	ficlDictionary *dictionary = system->dictionary;
144*a1bf3f78SToomas Soome 	ficlHash *hash;
145*a1bf3f78SToomas Soome 
146*a1bf3f78SToomas Soome 	/*
147*a1bf3f78SToomas Soome 	 * Create a named wordlist for prefixes to reside in...
148*a1bf3f78SToomas Soome 	 * Since we're doing a special kind of search, make it
149*a1bf3f78SToomas Soome 	 * a single bucket hashtable - hashing does not help here.
150*a1bf3f78SToomas Soome 	 */
151*a1bf3f78SToomas Soome 	hash = ficlDictionaryCreateWordlist(dictionary, 1);
152*a1bf3f78SToomas Soome 	hash->name = list_name;
153*a1bf3f78SToomas Soome 	ficlDictionaryAppendConstantPointer(dictionary, list_name, hash);
154*a1bf3f78SToomas Soome 
155*a1bf3f78SToomas Soome 	/*
156*a1bf3f78SToomas Soome 	 * Put __tempbase in the forth-wordlist
157*a1bf3f78SToomas Soome 	 */
158*a1bf3f78SToomas Soome 	ficlDictionarySetPrimitive(dictionary, "__tempbase",
159*a1bf3f78SToomas Soome 	    ficlPrimitiveTempBase, FICL_WORD_DEFAULT);
160*a1bf3f78SToomas Soome 
161*a1bf3f78SToomas Soome 	/*
162*a1bf3f78SToomas Soome 	 * If you want to add some prefixes at compilation-time, copy this
163*a1bf3f78SToomas Soome 	 * line to the top of this function:
164*a1bf3f78SToomas Soome 	 *
165*a1bf3f78SToomas Soome 	 * ficlHash *oldCompilationWordlist;
166*a1bf3f78SToomas Soome 	 *
167*a1bf3f78SToomas Soome 	 * then copy this code to the bottom, just above the return:
168*a1bf3f78SToomas Soome 	 *
169*a1bf3f78SToomas Soome 	 *
170*a1bf3f78SToomas Soome 	 * oldCompilationWordlist = dictionary->compilationWordlist;
171*a1bf3f78SToomas Soome 	 * dictionary->compilationWordlist = hash;
172*a1bf3f78SToomas Soome 	 * ficlDictionarySetPrimitive(dictionary, YOUR WORD HERE,
173*a1bf3f78SToomas Soome 	 * FICL_WORD_DEFAULT);
174*a1bf3f78SToomas Soome 	 * dictionary->compilationWordlist = oldCompilationWordlist;
175*a1bf3f78SToomas Soome 	 *
176*a1bf3f78SToomas Soome 	 * and substitute in your own actual calls to
177*a1bf3f78SToomas Soome 	 * ficlDictionarySetPrimitive() as needed.
178*a1bf3f78SToomas Soome 	 *
179*a1bf3f78SToomas Soome 	 * Or--better yet--do it in your own code, so you don't have
180*a1bf3f78SToomas Soome 	 * to re-modify the Ficl source code every time we cut a new release!
181*a1bf3f78SToomas Soome 	 */
182*a1bf3f78SToomas Soome }
183