xref: /trunk/main/soltools/mkdepend/parse.c (revision e932034bf45507ae970bfd7165fb7b2a983ba40d)
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 
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 
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  */
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          */
349*e932034bSJim Jagielski         {
350*e932034bSJim Jagielski             int len = strlen(line);
351*e932034bSJim Jagielski             memmove (line, p, len);
352*e932034bSJim Jagielski             line[len] = '\0';
353*e932034bSJim Jagielski         }
354cdf0e10cSrcweir         break;
355cdf0e10cSrcweir     case ELSE:
356cdf0e10cSrcweir     case ENDIF:
357cdf0e10cSrcweir     case ELIF:
358cdf0e10cSrcweir     case PRAGMA:
359cdf0e10cSrcweir     case ERROR:
360cdf0e10cSrcweir     case IDENT:
361cdf0e10cSrcweir     case SCCS:
362cdf0e10cSrcweir     case EJECT:
363cdf0e10cSrcweir         debug(0,("%s, line %d: #%s\n",
364cdf0e10cSrcweir             file->i_file, filep->f_line, directives[ret]));
365cdf0e10cSrcweir         /*
366cdf0e10cSrcweir          * nothing to do.
367cdf0e10cSrcweir          */
368cdf0e10cSrcweir         break;
369cdf0e10cSrcweir     }
370cdf0e10cSrcweir     return(ret);
371cdf0e10cSrcweir }
372cdf0e10cSrcweir 
373cdf0e10cSrcweir /*
374cdf0e10cSrcweir  * HACK! - so that we do not have to introduce 'symbols' in each cppsetup.c
375cdf0e10cSrcweir  * function...  It's safe, functions from cppsetup.c don't return here.
376cdf0e10cSrcweir  */
377cdf0e10cSrcweir struct symhash *global_symbols = NULL;
378cdf0e10cSrcweir 
379cdf0e10cSrcweir char * isdefined( symbol )
380cdf0e10cSrcweir     register char *symbol;
381cdf0e10cSrcweir {
382cdf0e10cSrcweir     return hash_lookup( symbol, global_symbols );
383cdf0e10cSrcweir }
384cdf0e10cSrcweir 
385cdf0e10cSrcweir /*
386cdf0e10cSrcweir  * Return type based on if the #if expression evaluates to 0
387cdf0e10cSrcweir  */
388cdf0e10cSrcweir int zero_value(exp, filep, file_red, symbols)
389cdf0e10cSrcweir     register char   *exp;
390cdf0e10cSrcweir     register struct filepointer *filep;
391cdf0e10cSrcweir     register struct inclist *file_red;
392cdf0e10cSrcweir     register struct symhash *symbols;
393cdf0e10cSrcweir {
394cdf0e10cSrcweir     global_symbols = symbols; /* HACK! see above */
395cdf0e10cSrcweir     if (cppsetup(exp, filep, file_red))
396cdf0e10cSrcweir         return(IFFALSE);
397cdf0e10cSrcweir     else
398cdf0e10cSrcweir         return(IF);
399cdf0e10cSrcweir }
400cdf0e10cSrcweir 
401cdf0e10cSrcweir void define( def, symbols )
402cdf0e10cSrcweir     char            *def;
403cdf0e10cSrcweir     struct symhash **symbols;
404cdf0e10cSrcweir {
405cdf0e10cSrcweir     char *val;
406cdf0e10cSrcweir 
407cdf0e10cSrcweir     /* Separate symbol name and its value */
408cdf0e10cSrcweir     val = def;
409cdf0e10cSrcweir     while (isalnum(*val) || *val == '_')
410cdf0e10cSrcweir     val++;
411cdf0e10cSrcweir     if (*val)
412cdf0e10cSrcweir     *val++ = '\0';
413cdf0e10cSrcweir     while (*val == ' ' || *val == '\t')
414cdf0e10cSrcweir     val++;
415cdf0e10cSrcweir 
416cdf0e10cSrcweir     if (!*val)
417cdf0e10cSrcweir     val = "1";
418cdf0e10cSrcweir     hash_define( def, val, symbols );
419cdf0e10cSrcweir }
420cdf0e10cSrcweir 
421cdf0e10cSrcweir static int hash( str )
422cdf0e10cSrcweir     register char *str;
423cdf0e10cSrcweir {
424cdf0e10cSrcweir     /* Hash (Kernighan and Ritchie) */
425cdf0e10cSrcweir     register unsigned int hashval = 0;
426cdf0e10cSrcweir     //char *s = str;
427cdf0e10cSrcweir 
428cdf0e10cSrcweir     for ( ; *str; str++ )
429cdf0e10cSrcweir     {
430cdf0e10cSrcweir         hashval = ( hashval * SYMHASHSEED ) + ( *str );
431cdf0e10cSrcweir     }
432cdf0e10cSrcweir 
433cdf0e10cSrcweir     //fprintf( stderr, "hash: %s, %d\n", s, hashval & ( SYMHASHMEMBERS - 1 ) );
434cdf0e10cSrcweir     return hashval & ( SYMHASHMEMBERS - 1 );
435cdf0e10cSrcweir }
436cdf0e10cSrcweir 
437cdf0e10cSrcweir struct symhash *hash_copy( symbols )
438cdf0e10cSrcweir     struct symhash *symbols;
439cdf0e10cSrcweir {
440cdf0e10cSrcweir     int i;
441cdf0e10cSrcweir     struct symhash *newsym;
442cdf0e10cSrcweir     if ( !symbols )
443cdf0e10cSrcweir         return NULL;
444cdf0e10cSrcweir 
445cdf0e10cSrcweir     newsym = (struct symhash *) malloc( sizeof( struct symhash ) );
446cdf0e10cSrcweir 
447cdf0e10cSrcweir     for ( i = 0; i < SYMHASHMEMBERS; ++i )
448cdf0e10cSrcweir     {
449cdf0e10cSrcweir         if ( !symbols->s_pairs[ i ] )
450cdf0e10cSrcweir             newsym->s_pairs[ i ] = NULL;
451cdf0e10cSrcweir         else
452cdf0e10cSrcweir         {
453cdf0e10cSrcweir             struct pair *it = symbols->s_pairs[ i ];
454cdf0e10cSrcweir             struct pair *nw = newsym->s_pairs[ i ] = (struct pair*) malloc( sizeof( struct pair ) );
455cdf0e10cSrcweir             nw->p_name = it->p_name;
456cdf0e10cSrcweir             nw->p_value = it->p_value;
457cdf0e10cSrcweir             nw->p_next = NULL;
458cdf0e10cSrcweir 
459cdf0e10cSrcweir             while ( it->p_next )
460cdf0e10cSrcweir             {
461cdf0e10cSrcweir                 nw->p_next = (struct pair*) malloc( sizeof( struct pair ) );
462cdf0e10cSrcweir                 it = it->p_next;
463cdf0e10cSrcweir                 nw = nw->p_next;
464cdf0e10cSrcweir                 nw->p_name = it->p_name;
465cdf0e10cSrcweir                 nw->p_value = it->p_value;
466cdf0e10cSrcweir                 nw->p_next = NULL;
467cdf0e10cSrcweir             }
468cdf0e10cSrcweir         }
469cdf0e10cSrcweir     }
470cdf0e10cSrcweir     return newsym;
471cdf0e10cSrcweir }
472cdf0e10cSrcweir 
473cdf0e10cSrcweir void hash_free( symbols )
474cdf0e10cSrcweir     struct symhash *symbols;
475cdf0e10cSrcweir {
476cdf0e10cSrcweir     int i;
477cdf0e10cSrcweir 
478cdf0e10cSrcweir     if ( !symbols )
479cdf0e10cSrcweir         return;
480cdf0e10cSrcweir 
481cdf0e10cSrcweir     for ( i = 0; i < SYMHASHMEMBERS; ++i )
482cdf0e10cSrcweir     {
483cdf0e10cSrcweir         struct pair *it = symbols->s_pairs[ i ];
484cdf0e10cSrcweir         struct pair *next;
485cdf0e10cSrcweir         while ( it )
486cdf0e10cSrcweir         {
487cdf0e10cSrcweir             next = it->p_next;
488cdf0e10cSrcweir             free( it );
489cdf0e10cSrcweir             it = next;
490cdf0e10cSrcweir         }
491cdf0e10cSrcweir     }
492cdf0e10cSrcweir     free( symbols->s_pairs );
493cdf0e10cSrcweir }
494cdf0e10cSrcweir 
495cdf0e10cSrcweir void hash_define( name, val, symbols )
496cdf0e10cSrcweir     char            *name, *val;
497cdf0e10cSrcweir     struct symhash **symbols;
498cdf0e10cSrcweir {
499cdf0e10cSrcweir     int hashval;
500cdf0e10cSrcweir     struct pair *it;
501cdf0e10cSrcweir 
502cdf0e10cSrcweir     if ( !symbols )
503cdf0e10cSrcweir         return;
504cdf0e10cSrcweir 
505cdf0e10cSrcweir     /* Make space if it's needed */
506cdf0e10cSrcweir     if ( *symbols == NULL )
507cdf0e10cSrcweir     {
508cdf0e10cSrcweir         int i;
509cdf0e10cSrcweir 
510cdf0e10cSrcweir         *symbols = (struct symhash *) malloc( sizeof( struct symhash ) );
511cdf0e10cSrcweir         if ( *symbols == NULL )
512cdf0e10cSrcweir             fatalerr( "malloc()/realloc() failure in insert_defn()\n" );
513cdf0e10cSrcweir 
514cdf0e10cSrcweir         for ( i = 0; i < SYMHASHMEMBERS; ++i )
515cdf0e10cSrcweir             (*symbols)->s_pairs[i] = NULL;
516cdf0e10cSrcweir     }
517cdf0e10cSrcweir 
518cdf0e10cSrcweir     hashval = hash( name );
519cdf0e10cSrcweir     it = (*symbols)->s_pairs[ hashval ];
520cdf0e10cSrcweir 
521cdf0e10cSrcweir     /* Replace/insert the symbol */
522cdf0e10cSrcweir     if ( it == NULL )
523cdf0e10cSrcweir     {
524cdf0e10cSrcweir         it = (*symbols)->s_pairs[ hashval ] = (struct pair*) malloc( sizeof( struct pair ) );
525cdf0e10cSrcweir         it->p_name = copy( name );
526cdf0e10cSrcweir         it->p_value = copy( val );
527cdf0e10cSrcweir         it->p_next = NULL;
528cdf0e10cSrcweir     }
529cdf0e10cSrcweir     else if ( strcmp( it->p_name, name ) == 0 )
530cdf0e10cSrcweir     {
531cdf0e10cSrcweir         it->p_value = copy( val );
532cdf0e10cSrcweir     }
533cdf0e10cSrcweir     else
534cdf0e10cSrcweir     {
535cdf0e10cSrcweir         while ( it->p_next && ( strcmp( it->p_next->p_name, name ) != 0 ) )
536cdf0e10cSrcweir         {
537cdf0e10cSrcweir             it = it->p_next;
538cdf0e10cSrcweir         }
539cdf0e10cSrcweir         if ( it->p_next )
540cdf0e10cSrcweir             it->p_next->p_name = copy( name );
541cdf0e10cSrcweir         else
542cdf0e10cSrcweir         {
543cdf0e10cSrcweir             it->p_next = (struct pair*) malloc( sizeof( struct pair ) );
544cdf0e10cSrcweir             it->p_next->p_name = copy( name );
545cdf0e10cSrcweir             it->p_next->p_value = copy( val );
546cdf0e10cSrcweir             it->p_next->p_next = NULL;
547cdf0e10cSrcweir         }
548cdf0e10cSrcweir     }
549cdf0e10cSrcweir }
550cdf0e10cSrcweir 
551cdf0e10cSrcweir char *hash_lookup( symbol, symbols )
552cdf0e10cSrcweir     char           *symbol;
553cdf0e10cSrcweir     struct symhash *symbols;
554cdf0e10cSrcweir {
555cdf0e10cSrcweir     struct pair *it;
556cdf0e10cSrcweir 
557cdf0e10cSrcweir     if ( !symbols )
558cdf0e10cSrcweir         return NULL;
559cdf0e10cSrcweir 
560cdf0e10cSrcweir     it = symbols->s_pairs[ hash( symbol ) ];
561cdf0e10cSrcweir 
562cdf0e10cSrcweir     while ( it && ( strcmp( it->p_name, symbol ) != 0 ) )
563cdf0e10cSrcweir     {
564cdf0e10cSrcweir         it = it->p_next;
565cdf0e10cSrcweir     }
566cdf0e10cSrcweir     if ( it )
567cdf0e10cSrcweir         return it->p_value;
568cdf0e10cSrcweir 
569cdf0e10cSrcweir     return NULL;
570cdf0e10cSrcweir }
571cdf0e10cSrcweir 
572cdf0e10cSrcweir void hash_undefine( symbol, symbols )
573cdf0e10cSrcweir     char           *symbol;
574cdf0e10cSrcweir     struct symhash *symbols;
575cdf0e10cSrcweir {
576cdf0e10cSrcweir     int hashval;
577cdf0e10cSrcweir     struct pair *it;
578cdf0e10cSrcweir 
579cdf0e10cSrcweir     if ( !symbols )
580cdf0e10cSrcweir         return;
581cdf0e10cSrcweir 
582cdf0e10cSrcweir     hashval = hash( symbol );
583cdf0e10cSrcweir     it = symbols->s_pairs[ hashval ];
584cdf0e10cSrcweir 
585cdf0e10cSrcweir     /* Replace/insert the symbol */
586cdf0e10cSrcweir     if ( it == NULL )
587cdf0e10cSrcweir         return;
588cdf0e10cSrcweir     else if ( strcmp( it->p_name, symbol ) == 0 )
589cdf0e10cSrcweir     {
590cdf0e10cSrcweir         if ( it->p_next )
591cdf0e10cSrcweir         {
592cdf0e10cSrcweir             struct pair *tmp;
593cdf0e10cSrcweir             it->p_name = it->p_next->p_name;
594cdf0e10cSrcweir             it->p_value = it->p_next->p_value;
595cdf0e10cSrcweir             tmp = it->p_next->p_next;
596cdf0e10cSrcweir             free( it->p_next );
597cdf0e10cSrcweir             it->p_next = tmp;
598cdf0e10cSrcweir         }
599cdf0e10cSrcweir         else
600cdf0e10cSrcweir         {
601cdf0e10cSrcweir             free( it );
602cdf0e10cSrcweir             symbols->s_pairs[ hashval ] = NULL;
603cdf0e10cSrcweir         }
604cdf0e10cSrcweir     }
605cdf0e10cSrcweir     else
606cdf0e10cSrcweir     {
607cdf0e10cSrcweir         while ( it->p_next && ( strcmp( it->p_next->p_name, symbol ) != 0 ) )
608cdf0e10cSrcweir         {
609cdf0e10cSrcweir             it = it->p_next;
610cdf0e10cSrcweir         }
611cdf0e10cSrcweir         if ( it->p_next )
612cdf0e10cSrcweir         {
613cdf0e10cSrcweir             struct pair *tmp = it->p_next;
614cdf0e10cSrcweir             it->p_next = it->p_next->p_next;
615cdf0e10cSrcweir             free( tmp );
616cdf0e10cSrcweir         }
617cdf0e10cSrcweir     }
618cdf0e10cSrcweir }
619