1cdf0e10cSrcweir /* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */
2cdf0e10cSrcweir /*
3cdf0e10cSrcweir
4cdf0e10cSrcweir Copyright (c) 1993, 1994 X Consortium
5cdf0e10cSrcweir
6cdf0e10cSrcweir Permission is hereby granted, free of charge, to any person obtaining a copy
7cdf0e10cSrcweir of this software and associated documentation files (the "Software"), to deal
8cdf0e10cSrcweir in the Software without restriction, including without limitation the rights
9cdf0e10cSrcweir to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10cdf0e10cSrcweir copies of the Software, and to permit persons to whom the Software is
11cdf0e10cSrcweir furnished to do so, subject to the following conditions:
12cdf0e10cSrcweir
13cdf0e10cSrcweir The above copyright notice and this permission notice shall be included in
14cdf0e10cSrcweir all copies or substantial portions of the Software.
15cdf0e10cSrcweir
16cdf0e10cSrcweir THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17cdf0e10cSrcweir IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18cdf0e10cSrcweir FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19cdf0e10cSrcweir X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20cdf0e10cSrcweir AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21cdf0e10cSrcweir CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22cdf0e10cSrcweir
23cdf0e10cSrcweir Except as contained in this notice, the name of the X Consortium shall not be
24cdf0e10cSrcweir used in advertising or otherwise to promote the sale, use or other dealings
25cdf0e10cSrcweir in this Software without prior written authorization from the X Consortium.
26cdf0e10cSrcweir
27cdf0e10cSrcweir */
28cdf0e10cSrcweir
29cdf0e10cSrcweir #include "def.h"
30cdf0e10cSrcweir char *hash_lookup( char *symbol, struct symhash *symbols );
31cdf0e10cSrcweir void hash_undefine( char *symbol, struct symhash *symbols );
32cdf0e10cSrcweir int gobble( register struct filepointer *filep, struct inclist *file,
33cdf0e10cSrcweir struct inclist *file_red, struct symhash *symbols );
34cdf0e10cSrcweir int deftype ( register char *line, register struct filepointer *filep,
35cdf0e10cSrcweir register struct inclist *file_red, register struct inclist *file,
36cdf0e10cSrcweir int parse_it, struct symhash *symbols);
37cdf0e10cSrcweir int zero_value(register char *exp, register struct filepointer *filep,
38cdf0e10cSrcweir register struct inclist *file_red, register struct symhash *symbols);
39cdf0e10cSrcweir
40cdf0e10cSrcweir extern char *directives[];
41cdf0e10cSrcweir extern struct symhash *maininclist;
42cdf0e10cSrcweir
find_includes(filep,file,file_red,recursion,failOK,incCollection,symbols)43cdf0e10cSrcweir int find_includes(filep, file, file_red, recursion, failOK, incCollection, symbols)
44cdf0e10cSrcweir struct filepointer *filep;
45cdf0e10cSrcweir struct inclist *file, *file_red;
46cdf0e10cSrcweir int recursion;
47cdf0e10cSrcweir boolean failOK;
48cdf0e10cSrcweir struct IncludesCollection* incCollection;
49cdf0e10cSrcweir struct symhash *symbols;
50cdf0e10cSrcweir {
51cdf0e10cSrcweir register char *line;
52cdf0e10cSrcweir register int type;
53cdf0e10cSrcweir boolean recfailOK;
54cdf0e10cSrcweir
55cdf0e10cSrcweir while ((line = get_line(filep))) {
56cdf0e10cSrcweir switch(type = deftype(line, filep, file_red, file, TRUE, symbols)) {
57cdf0e10cSrcweir case IF:
58cdf0e10cSrcweir doif:
59cdf0e10cSrcweir type = find_includes(filep, file,
60cdf0e10cSrcweir file_red, recursion+1, failOK, incCollection, symbols);
61cdf0e10cSrcweir while ((type == ELIF) || (type == ELIFFALSE) ||
62cdf0e10cSrcweir (type == ELIFGUESSFALSE))
63cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols);
64cdf0e10cSrcweir if (type == ELSE)
65cdf0e10cSrcweir gobble(filep, file, file_red, symbols);
66cdf0e10cSrcweir break;
67cdf0e10cSrcweir case IFFALSE:
68cdf0e10cSrcweir case IFGUESSFALSE:
69cdf0e10cSrcweir doiffalse:
70cdf0e10cSrcweir if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
71cdf0e10cSrcweir recfailOK = TRUE;
72cdf0e10cSrcweir else
73cdf0e10cSrcweir recfailOK = failOK;
74cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols);
75cdf0e10cSrcweir if (type == ELSE)
76cdf0e10cSrcweir find_includes(filep, file,
77cdf0e10cSrcweir file_red, recursion+1, recfailOK, incCollection, symbols);
78cdf0e10cSrcweir else
79cdf0e10cSrcweir if (type == ELIF)
80cdf0e10cSrcweir goto doif;
81cdf0e10cSrcweir else
82cdf0e10cSrcweir if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
83cdf0e10cSrcweir goto doiffalse;
84cdf0e10cSrcweir break;
85cdf0e10cSrcweir case IFDEF:
86cdf0e10cSrcweir case IFNDEF:
87cdf0e10cSrcweir if ((type == IFDEF && hash_lookup(line, symbols))
88cdf0e10cSrcweir || (type == IFNDEF && !hash_lookup(line, symbols))) {
89cdf0e10cSrcweir debug(1,(type == IFNDEF ?
90cdf0e10cSrcweir "line %d: %s !def'd in %s via %s%s\n" : "",
91cdf0e10cSrcweir filep->f_line, line,
92cdf0e10cSrcweir file->i_file, file_red->i_file, ": doit"));
93cdf0e10cSrcweir type = find_includes(filep, file,
94cdf0e10cSrcweir file_red, recursion+1, failOK, incCollection, symbols);
95cdf0e10cSrcweir while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
96cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols);
97cdf0e10cSrcweir if (type == ELSE)
98cdf0e10cSrcweir gobble(filep, file, file_red, symbols);
99cdf0e10cSrcweir }
100cdf0e10cSrcweir else {
101cdf0e10cSrcweir debug(1,(type == IFDEF ?
102cdf0e10cSrcweir "line %d: %s !def'd in %s via %s%s\n" : "",
103cdf0e10cSrcweir filep->f_line, line,
104cdf0e10cSrcweir file->i_file, file_red->i_file, ": gobble"));
105cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols);
106cdf0e10cSrcweir if (type == ELSE)
107cdf0e10cSrcweir find_includes(filep, file,
108cdf0e10cSrcweir file_red, recursion + 1, failOK, incCollection, symbols);
109cdf0e10cSrcweir else if (type == ELIF)
110cdf0e10cSrcweir goto doif;
111cdf0e10cSrcweir else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
112cdf0e10cSrcweir goto doiffalse;
113cdf0e10cSrcweir }
114cdf0e10cSrcweir break;
115cdf0e10cSrcweir case ELSE:
116cdf0e10cSrcweir case ELIFFALSE:
117cdf0e10cSrcweir case ELIFGUESSFALSE:
118cdf0e10cSrcweir case ELIF:
119cdf0e10cSrcweir if (!recursion)
120cdf0e10cSrcweir gobble(filep, file, file_red, symbols);
121cdf0e10cSrcweir case ENDIF:
122cdf0e10cSrcweir if (recursion)
123cdf0e10cSrcweir return(type);
124cdf0e10cSrcweir case DEFINE:
125cdf0e10cSrcweir define(line, &symbols);
126cdf0e10cSrcweir break;
127cdf0e10cSrcweir case UNDEF:
128cdf0e10cSrcweir if (!*line) {
129cdf0e10cSrcweir warning("%s, line %d: incomplete undef == \"%s\"\n",
130cdf0e10cSrcweir file_red->i_file, filep->f_line, line);
131cdf0e10cSrcweir break;
132cdf0e10cSrcweir }
133cdf0e10cSrcweir hash_undefine(line, symbols);
134cdf0e10cSrcweir break;
135cdf0e10cSrcweir case INCLUDE:
136cdf0e10cSrcweir add_include(filep, file, file_red, line, FALSE, failOK, incCollection, symbols);
137cdf0e10cSrcweir break;
138cdf0e10cSrcweir case INCLUDEDOT:
139cdf0e10cSrcweir add_include(filep, file, file_red, line, TRUE, failOK, incCollection, symbols);
140cdf0e10cSrcweir break;
141cdf0e10cSrcweir case ERROR:
142cdf0e10cSrcweir warning("%s: %d: %s\n", file_red->i_file,
143cdf0e10cSrcweir filep->f_line, line);
144cdf0e10cSrcweir break;
145cdf0e10cSrcweir
146cdf0e10cSrcweir case PRAGMA:
147cdf0e10cSrcweir case IDENT:
148cdf0e10cSrcweir case SCCS:
149cdf0e10cSrcweir case EJECT:
150cdf0e10cSrcweir break;
151cdf0e10cSrcweir case -1:
152cdf0e10cSrcweir warning("%s", file_red->i_file);
153cdf0e10cSrcweir if (file_red != file)
154cdf0e10cSrcweir warning1(" (reading %s)", file->i_file);
155cdf0e10cSrcweir warning1(", line %d: unknown directive == \"%s\"\n",
156cdf0e10cSrcweir filep->f_line, line);
157cdf0e10cSrcweir break;
158cdf0e10cSrcweir case -2:
159cdf0e10cSrcweir warning("%s", file_red->i_file);
160cdf0e10cSrcweir if (file_red != file)
161cdf0e10cSrcweir warning1(" (reading %s)", file->i_file);
162cdf0e10cSrcweir warning1(", line %d: incomplete include == \"%s\"\n",
163cdf0e10cSrcweir filep->f_line, line);
164cdf0e10cSrcweir break;
165cdf0e10cSrcweir }
166cdf0e10cSrcweir }
167cdf0e10cSrcweir return(-1);
168cdf0e10cSrcweir }
169cdf0e10cSrcweir
gobble(filep,file,file_red,symbols)170cdf0e10cSrcweir int gobble(filep, file, file_red, symbols)
171cdf0e10cSrcweir register struct filepointer *filep;
172cdf0e10cSrcweir struct inclist *file, *file_red;
173cdf0e10cSrcweir struct symhash *symbols;
174cdf0e10cSrcweir {
175cdf0e10cSrcweir register char *line;
176cdf0e10cSrcweir register int type;
177cdf0e10cSrcweir
178cdf0e10cSrcweir while ((line = get_line(filep))) {
179cdf0e10cSrcweir switch(type = deftype(line, filep, file_red, file, FALSE, symbols)) {
180cdf0e10cSrcweir case IF:
181cdf0e10cSrcweir case IFFALSE:
182cdf0e10cSrcweir case IFGUESSFALSE:
183cdf0e10cSrcweir case IFDEF:
184cdf0e10cSrcweir case IFNDEF:
185cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols);
186cdf0e10cSrcweir while ((type == ELIF) || (type == ELIFFALSE) ||
187cdf0e10cSrcweir (type == ELIFGUESSFALSE))
188cdf0e10cSrcweir type = gobble(filep, file, file_red, symbols);
189cdf0e10cSrcweir if (type == ELSE)
190cdf0e10cSrcweir (void)gobble(filep, file, file_red, symbols);
191cdf0e10cSrcweir break;
192cdf0e10cSrcweir case ELSE:
193cdf0e10cSrcweir case ENDIF:
194cdf0e10cSrcweir debug(0,("%s, line %d: #%s\n",
195cdf0e10cSrcweir file->i_file, filep->f_line,
196cdf0e10cSrcweir directives[type]));
197cdf0e10cSrcweir return(type);
198cdf0e10cSrcweir case DEFINE:
199cdf0e10cSrcweir case UNDEF:
200cdf0e10cSrcweir case INCLUDE:
201cdf0e10cSrcweir case INCLUDEDOT:
202cdf0e10cSrcweir case PRAGMA:
203cdf0e10cSrcweir case ERROR:
204cdf0e10cSrcweir case IDENT:
205cdf0e10cSrcweir case SCCS:
206cdf0e10cSrcweir case EJECT:
207cdf0e10cSrcweir break;
208cdf0e10cSrcweir case ELIF:
209cdf0e10cSrcweir case ELIFFALSE:
210cdf0e10cSrcweir case ELIFGUESSFALSE:
211cdf0e10cSrcweir return(type);
212cdf0e10cSrcweir case -1:
213cdf0e10cSrcweir warning("%s, line %d: unknown directive == \"%s\"\n",
214cdf0e10cSrcweir file_red->i_file, filep->f_line, line);
215cdf0e10cSrcweir break;
216cdf0e10cSrcweir }
217cdf0e10cSrcweir }
218cdf0e10cSrcweir return(-1);
219cdf0e10cSrcweir }
220cdf0e10cSrcweir
221cdf0e10cSrcweir /*
222cdf0e10cSrcweir * Decide what type of # directive this line is.
223cdf0e10cSrcweir */
deftype(line,filep,file_red,file,parse_it,symbols)224cdf0e10cSrcweir int deftype (line, filep, file_red, file, parse_it, symbols)
225cdf0e10cSrcweir register char *line;
226cdf0e10cSrcweir register struct filepointer *filep;
227cdf0e10cSrcweir register struct inclist *file_red, *file;
228cdf0e10cSrcweir int parse_it;
229cdf0e10cSrcweir struct symhash *symbols;
230cdf0e10cSrcweir {
231cdf0e10cSrcweir register char *p;
232cdf0e10cSrcweir char *directive, savechar;
233cdf0e10cSrcweir register int ret;
234cdf0e10cSrcweir
235cdf0e10cSrcweir /*
236cdf0e10cSrcweir * Parse the directive...
237cdf0e10cSrcweir */
238cdf0e10cSrcweir directive=line+1;
239cdf0e10cSrcweir while (*directive == ' ' || *directive == '\t')
240cdf0e10cSrcweir directive++;
241cdf0e10cSrcweir
242cdf0e10cSrcweir p = directive;
243cdf0e10cSrcweir while (*p >= 'a' && *p <= 'z')
244cdf0e10cSrcweir p++;
245cdf0e10cSrcweir savechar = *p;
246cdf0e10cSrcweir *p = '\0';
247cdf0e10cSrcweir ret = match(directive, directives);
248cdf0e10cSrcweir *p = savechar;
249cdf0e10cSrcweir
250cdf0e10cSrcweir /* If we don't recognize this compiler directive or we happen to just
251cdf0e10cSrcweir * be gobbling up text while waiting for an #endif or #elif or #else
252cdf0e10cSrcweir * in the case of an #elif we must check the zero_value and return an
253cdf0e10cSrcweir * ELIF or an ELIFFALSE.
254cdf0e10cSrcweir */
255cdf0e10cSrcweir
256cdf0e10cSrcweir if (ret == ELIF && !parse_it)
257cdf0e10cSrcweir {
258cdf0e10cSrcweir while (*p == ' ' || *p == '\t')
259cdf0e10cSrcweir p++;
260cdf0e10cSrcweir /*
261cdf0e10cSrcweir * parse an expression.
262cdf0e10cSrcweir */
263cdf0e10cSrcweir debug(0,("%s, line %d: #elif %s ",
264cdf0e10cSrcweir file->i_file, filep->f_line, p));
265cdf0e10cSrcweir ret = zero_value(p, filep, file_red, symbols);
266cdf0e10cSrcweir if (ret != IF)
267cdf0e10cSrcweir {
268cdf0e10cSrcweir debug(0,("false...\n"));
269cdf0e10cSrcweir if (ret == IFFALSE)
270cdf0e10cSrcweir return(ELIFFALSE);
271cdf0e10cSrcweir else
272cdf0e10cSrcweir return(ELIFGUESSFALSE);
273cdf0e10cSrcweir }
274cdf0e10cSrcweir else
275cdf0e10cSrcweir {
276cdf0e10cSrcweir debug(0,("true...\n"));
277cdf0e10cSrcweir return(ELIF);
278cdf0e10cSrcweir }
279cdf0e10cSrcweir }
280cdf0e10cSrcweir
281cdf0e10cSrcweir if (ret < 0 || ! parse_it)
282cdf0e10cSrcweir return(ret);
283cdf0e10cSrcweir
284cdf0e10cSrcweir /*
285cdf0e10cSrcweir * now decide how to parse the directive, and do it.
286cdf0e10cSrcweir */
287cdf0e10cSrcweir while (*p == ' ' || *p == '\t')
288cdf0e10cSrcweir p++;
289cdf0e10cSrcweir switch (ret) {
290cdf0e10cSrcweir case IF:
291cdf0e10cSrcweir /*
292cdf0e10cSrcweir * parse an expression.
293cdf0e10cSrcweir */
294cdf0e10cSrcweir ret = zero_value(p, filep, file_red, symbols);
295cdf0e10cSrcweir debug(0,("%s, line %d: %s #if %s\n",
296cdf0e10cSrcweir file->i_file, filep->f_line, ret?"false":"true", p));
297cdf0e10cSrcweir break;
298cdf0e10cSrcweir case IFDEF:
299cdf0e10cSrcweir case IFNDEF:
300cdf0e10cSrcweir debug(0,("%s, line %d: #%s %s\n",
301cdf0e10cSrcweir file->i_file, filep->f_line, directives[ret], p));
302cdf0e10cSrcweir case UNDEF:
303cdf0e10cSrcweir /*
304cdf0e10cSrcweir * separate the name of a single symbol.
305cdf0e10cSrcweir */
306cdf0e10cSrcweir while (isalnum(*p) || *p == '_')
307cdf0e10cSrcweir *line++ = *p++;
308cdf0e10cSrcweir *line = '\0';
309cdf0e10cSrcweir break;
310cdf0e10cSrcweir case INCLUDE:
311cdf0e10cSrcweir debug(2,("%s, line %d: #include %s\n",
312cdf0e10cSrcweir file->i_file, filep->f_line, p));
313cdf0e10cSrcweir
314cdf0e10cSrcweir /* Support ANSI macro substitution */
315cdf0e10cSrcweir {
316cdf0e10cSrcweir char *sym = hash_lookup(p, symbols);
317cdf0e10cSrcweir while (sym)
318cdf0e10cSrcweir {
319cdf0e10cSrcweir p = sym;
320cdf0e10cSrcweir debug(3,("%s : #includes SYMBOL %s\n",
321cdf0e10cSrcweir file->i_incstring,
322cdf0e10cSrcweir sym));
323cdf0e10cSrcweir /* mark file as having included a 'soft include' */
324cdf0e10cSrcweir file->i_included_sym = TRUE;
325cdf0e10cSrcweir sym = hash_lookup(p, symbols);
326cdf0e10cSrcweir }
327cdf0e10cSrcweir }
328cdf0e10cSrcweir
329cdf0e10cSrcweir /*
330cdf0e10cSrcweir * Separate the name of the include file.
331cdf0e10cSrcweir */
332cdf0e10cSrcweir while (*p && *p != '"' && *p != '<')
333cdf0e10cSrcweir p++;
334cdf0e10cSrcweir if (! *p)
335cdf0e10cSrcweir return(-2);
336cdf0e10cSrcweir if (*p++ == '"') {
337cdf0e10cSrcweir ret = INCLUDEDOT;
338cdf0e10cSrcweir while (*p && *p != '"')
339cdf0e10cSrcweir *line++ = *p++;
340cdf0e10cSrcweir } else
341cdf0e10cSrcweir while (*p && *p != '>')
342cdf0e10cSrcweir *line++ = *p++;
343cdf0e10cSrcweir *line = '\0';
344cdf0e10cSrcweir break;
345cdf0e10cSrcweir case DEFINE:
346cdf0e10cSrcweir /*
347cdf0e10cSrcweir * copy the definition back to the beginning of the line.
348cdf0e10cSrcweir */
349e932034bSJim Jagielski {
350*da891659SJim Jagielski int lenl = strlen(line);
351*da891659SJim Jagielski int lenp = strlen(p);
352*da891659SJim Jagielski memmove ( line, p, (lenl < lenp) ? lenl : lenp );
353*da891659SJim Jagielski line[ (lenl < lenp) ? lenl : lenp ] = '\0'; /* belts and braces */
354e932034bSJim Jagielski }
355cdf0e10cSrcweir break;
356cdf0e10cSrcweir case ELSE:
357cdf0e10cSrcweir case ENDIF:
358cdf0e10cSrcweir case ELIF:
359cdf0e10cSrcweir case PRAGMA:
360cdf0e10cSrcweir case ERROR:
361cdf0e10cSrcweir case IDENT:
362cdf0e10cSrcweir case SCCS:
363cdf0e10cSrcweir case EJECT:
364cdf0e10cSrcweir debug(0,("%s, line %d: #%s\n",
365cdf0e10cSrcweir file->i_file, filep->f_line, directives[ret]));
366cdf0e10cSrcweir /*
367cdf0e10cSrcweir * nothing to do.
368cdf0e10cSrcweir */
369cdf0e10cSrcweir break;
370cdf0e10cSrcweir }
371cdf0e10cSrcweir return(ret);
372cdf0e10cSrcweir }
373cdf0e10cSrcweir
374cdf0e10cSrcweir /*
375cdf0e10cSrcweir * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
376cdf0e10cSrcweir * function... It's safe, functions from cppsetup.c don't return here.
377cdf0e10cSrcweir */
378cdf0e10cSrcweir struct symhash *global_symbols = NULL;
379cdf0e10cSrcweir
isdefined(symbol)380cdf0e10cSrcweir char * isdefined( symbol )
381cdf0e10cSrcweir register char *symbol;
382cdf0e10cSrcweir {
383cdf0e10cSrcweir return hash_lookup( symbol, global_symbols );
384cdf0e10cSrcweir }
385cdf0e10cSrcweir
386cdf0e10cSrcweir /*
387cdf0e10cSrcweir * Return type based on if the #if expression evaluates to 0
388cdf0e10cSrcweir */
zero_value(exp,filep,file_red,symbols)389cdf0e10cSrcweir int zero_value(exp, filep, file_red, symbols)
390cdf0e10cSrcweir register char *exp;
391cdf0e10cSrcweir register struct filepointer *filep;
392cdf0e10cSrcweir register struct inclist *file_red;
393cdf0e10cSrcweir register struct symhash *symbols;
394cdf0e10cSrcweir {
395cdf0e10cSrcweir global_symbols = symbols; /* HACK! see above */
396cdf0e10cSrcweir if (cppsetup(exp, filep, file_red))
397cdf0e10cSrcweir return(IFFALSE);
398cdf0e10cSrcweir else
399cdf0e10cSrcweir return(IF);
400cdf0e10cSrcweir }
401cdf0e10cSrcweir
define(def,symbols)402cdf0e10cSrcweir void define( def, symbols )
403cdf0e10cSrcweir char *def;
404cdf0e10cSrcweir struct symhash **symbols;
405cdf0e10cSrcweir {
406cdf0e10cSrcweir char *val;
407cdf0e10cSrcweir
408cdf0e10cSrcweir /* Separate symbol name and its value */
409cdf0e10cSrcweir val = def;
410cdf0e10cSrcweir while (isalnum(*val) || *val == '_')
411cdf0e10cSrcweir val++;
412cdf0e10cSrcweir if (*val)
413cdf0e10cSrcweir *val++ = '\0';
414cdf0e10cSrcweir while (*val == ' ' || *val == '\t')
415cdf0e10cSrcweir val++;
416cdf0e10cSrcweir
417cdf0e10cSrcweir if (!*val)
418cdf0e10cSrcweir val = "1";
419cdf0e10cSrcweir hash_define( def, val, symbols );
420cdf0e10cSrcweir }
421cdf0e10cSrcweir
hash(str)422cdf0e10cSrcweir static int hash( str )
423cdf0e10cSrcweir register char *str;
424cdf0e10cSrcweir {
425cdf0e10cSrcweir /* Hash (Kernighan and Ritchie) */
426cdf0e10cSrcweir register unsigned int hashval = 0;
427cdf0e10cSrcweir //char *s = str;
428cdf0e10cSrcweir
429cdf0e10cSrcweir for ( ; *str; str++ )
430cdf0e10cSrcweir {
431cdf0e10cSrcweir hashval = ( hashval * SYMHASHSEED ) + ( *str );
432cdf0e10cSrcweir }
433cdf0e10cSrcweir
434cdf0e10cSrcweir //fprintf( stderr, "hash: %s, %d\n", s, hashval & ( SYMHASHMEMBERS - 1 ) );
435cdf0e10cSrcweir return hashval & ( SYMHASHMEMBERS - 1 );
436cdf0e10cSrcweir }
437cdf0e10cSrcweir
hash_copy(symbols)438cdf0e10cSrcweir struct symhash *hash_copy( symbols )
439cdf0e10cSrcweir struct symhash *symbols;
440cdf0e10cSrcweir {
441cdf0e10cSrcweir int i;
442cdf0e10cSrcweir struct symhash *newsym;
443cdf0e10cSrcweir if ( !symbols )
444cdf0e10cSrcweir return NULL;
445cdf0e10cSrcweir
446cdf0e10cSrcweir newsym = (struct symhash *) malloc( sizeof( struct symhash ) );
447cdf0e10cSrcweir
448cdf0e10cSrcweir for ( i = 0; i < SYMHASHMEMBERS; ++i )
449cdf0e10cSrcweir {
450cdf0e10cSrcweir if ( !symbols->s_pairs[ i ] )
451cdf0e10cSrcweir newsym->s_pairs[ i ] = NULL;
452cdf0e10cSrcweir else
453cdf0e10cSrcweir {
454cdf0e10cSrcweir struct pair *it = symbols->s_pairs[ i ];
455cdf0e10cSrcweir struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) );
456cdf0e10cSrcweir nw->p_name = it->p_name;
457cdf0e10cSrcweir nw->p_value = it->p_value;
458cdf0e10cSrcweir nw->p_next = NULL;
459cdf0e10cSrcweir
460cdf0e10cSrcweir while ( it->p_next )
461cdf0e10cSrcweir {
462cdf0e10cSrcweir nw->p_next = (struct pair*) malloc( sizeof( struct pair ) );
463cdf0e10cSrcweir it = it->p_next;
464cdf0e10cSrcweir nw = nw->p_next;
465cdf0e10cSrcweir nw->p_name = it->p_name;
466cdf0e10cSrcweir nw->p_value = it->p_value;
467cdf0e10cSrcweir nw->p_next = NULL;
468cdf0e10cSrcweir }
469cdf0e10cSrcweir }
470cdf0e10cSrcweir }
471cdf0e10cSrcweir return newsym;
472cdf0e10cSrcweir }
473cdf0e10cSrcweir
hash_free(symbols)474cdf0e10cSrcweir void hash_free( symbols )
475cdf0e10cSrcweir struct symhash *symbols;
476cdf0e10cSrcweir {
477cdf0e10cSrcweir int i;
478cdf0e10cSrcweir
479cdf0e10cSrcweir if ( !symbols )
480cdf0e10cSrcweir return;
481cdf0e10cSrcweir
482cdf0e10cSrcweir for ( i = 0; i < SYMHASHMEMBERS; ++i )
483cdf0e10cSrcweir {
484cdf0e10cSrcweir struct pair *it = symbols->s_pairs[ i ];
485cdf0e10cSrcweir struct pair *next;
486cdf0e10cSrcweir while ( it )
487cdf0e10cSrcweir {
488cdf0e10cSrcweir next = it->p_next;
489cdf0e10cSrcweir free( it );
490cdf0e10cSrcweir it = next;
491cdf0e10cSrcweir }
492cdf0e10cSrcweir }
493cdf0e10cSrcweir free( symbols->s_pairs );
494cdf0e10cSrcweir }
495cdf0e10cSrcweir
hash_define(name,val,symbols)496cdf0e10cSrcweir void hash_define( name, val, symbols )
497cdf0e10cSrcweir char *name, *val;
498cdf0e10cSrcweir struct symhash **symbols;
499cdf0e10cSrcweir {
500cdf0e10cSrcweir int hashval;
501cdf0e10cSrcweir struct pair *it;
502cdf0e10cSrcweir
503cdf0e10cSrcweir if ( !symbols )
504cdf0e10cSrcweir return;
505cdf0e10cSrcweir
506cdf0e10cSrcweir /* Make space if it's needed */
507cdf0e10cSrcweir if ( *symbols == NULL )
508cdf0e10cSrcweir {
509cdf0e10cSrcweir int i;
510cdf0e10cSrcweir
511cdf0e10cSrcweir *symbols = (struct symhash *) malloc( sizeof( struct symhash ) );
512cdf0e10cSrcweir if ( *symbols == NULL )
513cdf0e10cSrcweir fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
514cdf0e10cSrcweir
515cdf0e10cSrcweir for ( i = 0; i < SYMHASHMEMBERS; ++i )
516cdf0e10cSrcweir (*symbols)->s_pairs[i] = NULL;
517cdf0e10cSrcweir }
518cdf0e10cSrcweir
519cdf0e10cSrcweir hashval = hash( name );
520cdf0e10cSrcweir it = (*symbols)->s_pairs[ hashval ];
521cdf0e10cSrcweir
522cdf0e10cSrcweir /* Replace/insert the symbol */
523cdf0e10cSrcweir if ( it == NULL )
524cdf0e10cSrcweir {
525cdf0e10cSrcweir it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) );
526cdf0e10cSrcweir it->p_name = copy( name );
527cdf0e10cSrcweir it->p_value = copy( val );
528cdf0e10cSrcweir it->p_next = NULL;
529cdf0e10cSrcweir }
530cdf0e10cSrcweir else if ( strcmp( it->p_name, name ) == 0 )
531cdf0e10cSrcweir {
532cdf0e10cSrcweir it->p_value = copy( val );
533cdf0e10cSrcweir }
534cdf0e10cSrcweir else
535cdf0e10cSrcweir {
536cdf0e10cSrcweir while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) )
537cdf0e10cSrcweir {
538cdf0e10cSrcweir it = it->p_next;
539cdf0e10cSrcweir }
540cdf0e10cSrcweir if ( it->p_next )
541cdf0e10cSrcweir it->p_next->p_name = copy( name );
542cdf0e10cSrcweir else
543cdf0e10cSrcweir {
544cdf0e10cSrcweir it->p_next = (struct pair*) malloc( sizeof( struct pair ) );
545cdf0e10cSrcweir it->p_next->p_name = copy( name );
546cdf0e10cSrcweir it->p_next->p_value = copy( val );
547cdf0e10cSrcweir it->p_next->p_next = NULL;
548cdf0e10cSrcweir }
549cdf0e10cSrcweir }
550cdf0e10cSrcweir }
551cdf0e10cSrcweir
hash_lookup(symbol,symbols)552cdf0e10cSrcweir char *hash_lookup( symbol, symbols )
553cdf0e10cSrcweir char *symbol;
554cdf0e10cSrcweir struct symhash *symbols;
555cdf0e10cSrcweir {
556cdf0e10cSrcweir struct pair *it;
557cdf0e10cSrcweir
558cdf0e10cSrcweir if ( !symbols )
559cdf0e10cSrcweir return NULL;
560cdf0e10cSrcweir
561cdf0e10cSrcweir it = symbols->s_pairs[ hash( symbol ) ];
562cdf0e10cSrcweir
563cdf0e10cSrcweir while ( it && ( strcmp( it->p_name, symbol ) != 0 ) )
564cdf0e10cSrcweir {
565cdf0e10cSrcweir it = it->p_next;
566cdf0e10cSrcweir }
567cdf0e10cSrcweir if ( it )
568cdf0e10cSrcweir return it->p_value;
569cdf0e10cSrcweir
570cdf0e10cSrcweir return NULL;
571cdf0e10cSrcweir }
572cdf0e10cSrcweir
hash_undefine(symbol,symbols)573cdf0e10cSrcweir void hash_undefine( symbol, symbols )
574cdf0e10cSrcweir char *symbol;
575cdf0e10cSrcweir struct symhash *symbols;
576cdf0e10cSrcweir {
577cdf0e10cSrcweir int hashval;
578cdf0e10cSrcweir struct pair *it;
579cdf0e10cSrcweir
580cdf0e10cSrcweir if ( !symbols )
581cdf0e10cSrcweir return;
582cdf0e10cSrcweir
583cdf0e10cSrcweir hashval = hash( symbol );
584cdf0e10cSrcweir it = symbols->s_pairs[ hashval ];
585cdf0e10cSrcweir
586cdf0e10cSrcweir /* Replace/insert the symbol */
587cdf0e10cSrcweir if ( it == NULL )
588cdf0e10cSrcweir return;
589cdf0e10cSrcweir else if ( strcmp( it->p_name, symbol ) == 0 )
590cdf0e10cSrcweir {
591cdf0e10cSrcweir if ( it->p_next )
592cdf0e10cSrcweir {
593cdf0e10cSrcweir struct pair *tmp;
594cdf0e10cSrcweir it->p_name = it->p_next->p_name;
595cdf0e10cSrcweir it->p_value = it->p_next->p_value;
596cdf0e10cSrcweir tmp = it->p_next->p_next;
597cdf0e10cSrcweir free( it->p_next );
598cdf0e10cSrcweir it->p_next = tmp;
599cdf0e10cSrcweir }
600cdf0e10cSrcweir else
601cdf0e10cSrcweir {
602cdf0e10cSrcweir free( it );
603cdf0e10cSrcweir symbols->s_pairs[ hashval ] = NULL;
604cdf0e10cSrcweir }
605cdf0e10cSrcweir }
606cdf0e10cSrcweir else
607cdf0e10cSrcweir {
608cdf0e10cSrcweir while ( it->p_next && ( strcmp( it->p_next->p_name, symbol ) != 0 ) )
609cdf0e10cSrcweir {
610cdf0e10cSrcweir it = it->p_next;
611cdf0e10cSrcweir }
612cdf0e10cSrcweir if ( it->p_next )
613cdf0e10cSrcweir {
614cdf0e10cSrcweir struct pair *tmp = it->p_next;
615cdf0e10cSrcweir it->p_next = it->p_next->p_next;
616cdf0e10cSrcweir free( tmp );
617cdf0e10cSrcweir }
618cdf0e10cSrcweir }
619cdf0e10cSrcweir }
620