xref: /trunk/main/soltools/mkdepend/parse.c (revision 534d93521fb9d960038706348aeef53f37423a94)
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