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