]> andersk Git - moira.git/blob - util/makedepend/parse.c
sync'ing files for RCS->CVS migration
[moira.git] / util / makedepend / parse.c
1 /*
2  * $XConsortium: parse.c,v 1.8 88/09/22 13:52:51 jim Exp $
3  */
4 #include "def.h"
5 #include        <sys/signal.h>
6
7 extern char     *directives[];
8 extern struct symtab    deflist[];
9
10 find_includes(filep, file, file_red, recursion)
11         struct filepointer      *filep;
12         struct inclist          *file, *file_red;
13         int                     recursion;
14 {
15         register char   *line;
16         register int    type;
17
18         while (line = getline(filep)) {
19                 switch(type = deftype(line, filep, file_red, file, TRUE)) {
20                 case IF:
21                 doif:
22                         type = find_includes(filep, file,
23                                 file_red, recursion+1);
24                         while ((type == ELIF) || (type == ELIFFALSE))
25                                 type = gobble(filep, file, file_red);
26                         if (type == ELSE)
27                                 gobble(filep, file, file_red);
28                         break;
29                 case IFFALSE:
30                     doiffalse:
31                         type = gobble(filep, file, file_red);
32                         if (type == ELSE)
33                             find_includes(filep, file,
34                                 file_red, recursion+1);
35                         else
36                         if (type == ELIF)
37                             goto doif;
38                         else
39                         if (type == ELIFFALSE)
40                             goto doiffalse;
41                         break;
42                 case IFDEF:
43                 case IFNDEF:
44                         if ((type == IFDEF && defined(line, file_red))
45                          || (type == IFNDEF && !defined(line, file_red))) {
46                                 debug1(type == IFNDEF ?
47                                     "line %d: %s !def'd in %s via %s%s\n" : "",
48                                     filep->f_line, line,
49                                     file->i_file, file_red->i_file, ": doit");
50                                 type = find_includes(filep, file,
51                                         file_red, recursion+1);
52                                 if (type == ELSE)
53                                         gobble(filep, file, file_red);
54                         }
55                         else {
56                                 debug1(type == IFDEF ?
57                                     "line %d: %s !def'd in %s via %s%s\n" : "",
58                                     filep->f_line, line,
59                                     file->i_file, file_red->i_file, ": gobble");
60                                 type = gobble(filep, file, file_red);
61                                 if (type == ELSE)
62                                         find_includes(filep, file,
63                                                 file_red, recursion+1);
64                         }
65                         break;
66                 case ELSE:
67                 case ELIFFALSE:
68                 case ELIF:
69                         if (!recursion)
70                                 gobble(filep, file, file_red);
71                 case ENDIF:
72                         if (recursion)
73                                 return(type);
74                 case DEFINE:
75                         define(line, file);
76                         break;
77                 case UNDEF:
78                         /*
79                          * undefine all occurances of line by killing s_name
80                          */
81                         if (!*line) {
82                             log("%s, line %d: incomplete undef == \"%s\"\n",
83                                 file_red->i_file, filep->f_line, line);
84                             break;
85                         }
86                     {
87                         struct symtab *val;
88                         for(val = defined(line, file_red);
89                             (val && val->s_name);
90                             val = defined(line, file_red))
91
92                             *(val->s_name) = '\0';
93                     }
94                         break;
95                 case INCLUDE:
96                         add_include(file, file_red, line, FALSE);
97                         break;
98                 case INCLUDEDOT:
99                         add_include(file, file_red, line, TRUE);
100                         break;
101                 case PRAGMA:
102                 case EJECT:
103                         break;
104                 case -1:
105                         log("%s", file_red->i_file);
106                         if (file_red != file)
107                             log(" (reading %s)", file->i_file);
108                         log(", line %d: unknown directive == \"%s\"\n",
109                             filep->f_line, line);
110                         break;
111                 case -2:
112                         log("%s", file_red->i_file);
113                         if (file_red != file)
114                             log(" (reading %s)", file->i_file);
115                         log(", line %d: incomplete include == \"%s\"\n",
116                             filep->f_line, line);
117                         break;
118                 }
119         }
120         return(-1);
121 }
122
123 gobble(filep, file, file_red)
124         register struct filepointer *filep;
125         struct inclist          *file, *file_red;
126 {
127         register char   *line;
128         register int    type;
129
130         while (line = getline(filep)) {
131                 switch(type = deftype(line, filep, file_red, file, FALSE)) {
132                 case IF:
133                 case IFFALSE:
134                 case IFDEF:
135                 case IFNDEF:
136                         type = gobble(filep, file, file_red);
137                         while ((type == ELIF) || (type == ELIFFALSE))
138                             type = gobble(filep, file, file_red);
139                         if (type == ELSE)
140                                 type = gobble(filep, file, file_red);
141                         break;
142                 case ELSE:
143                 case ENDIF:
144                         debug0("%s, line %d: #%s\n",
145                                 file->i_file, filep->f_line,
146                                 directives[type]);
147                         return(type);
148                 case DEFINE:
149                 case UNDEF:
150                 case INCLUDE:
151                 case INCLUDEDOT:
152                 case PRAGMA:
153                 case EJECT:
154                         break;
155                 case ELIF:
156                 case ELIFFALSE:
157                         return(type);
158                 case -1:
159                         log("%s, line %d: unknown directive == \"%s\"\n",
160                                 file_red->i_file, filep->f_line, line);
161                         break;
162                 }
163         }
164         return(-1);
165 }
166
167 /*
168  * Decide what type of # directive this line is.
169  */
170 deftype(line, filep, file_red, file, parse_it)
171         register char   *line;
172         register struct filepointer *filep;
173         register struct inclist *file_red, *file;
174         int     parse_it;
175 {
176         register char   *p;
177         char    *directive, savechar;
178         register int    ret;
179
180         /*
181          * Parse the directive...
182          */
183         directive=line+1;
184         while (*directive == ' ' || *directive == '\t')
185                 directive++;
186
187         p = directive;
188         while (*p >= 'a' && *p <= 'z')
189                 p++;
190         savechar = *p;
191         *p = '\0';
192         ret = match(directive, directives);
193         *p = savechar;
194
195         /* If we don't recognize this compiler directive or we happen to just
196          * be gobbling up text while waiting for an #endif or #elif or #else
197          * in the case of an #elif we must check the zero_value and return an
198          * ELIF or an ELIFFALSE.
199          */
200
201         if (ret == ELIF && !parse_it)
202         {
203             while (*p == ' ' || *p == '\t')
204                 p++;
205             /*
206              * parse an expression.
207              */
208             debug0("%s, line %d: #elif %s ",
209                    file->i_file, filep->f_line, p);
210             if (zero_value(p, filep, file_red))
211             {
212                 debug0("false...\n");
213                 return(ELIFFALSE);
214             }
215             else
216             {
217                 debug0("true...\n");
218                 return(ret);
219             }
220         }
221
222         if (ret < 0 || ! parse_it)
223                 return(ret);
224
225         /*
226          * now decide how to parse the directive, and do it.
227          */
228         while (*p == ' ' || *p == '\t')
229                 p++;
230         switch (ret) {
231         case IF:
232                 /*
233                  * parse an expression.
234                  */
235                 debug0("%s, line %d: #if %s\n",
236                         file->i_file, filep->f_line, p);
237                 if (zero_value(p, filep, file_red))
238                         ret = IFFALSE;
239                 break;
240         case IFDEF:
241         case IFNDEF:
242                 debug0("%s, line %d: #%s %s\n",
243                         file->i_file, filep->f_line, directives[ret], p);
244         case UNDEF:
245                 /*
246                  * separate the name of a single symbol.
247                  */
248                 while (isalnum(*p) || *p == '_')
249                         *line++ = *p++;
250                 *line = '\0';
251                 break;
252         case INCLUDE:
253                 debug2("%s, line %d: #include %s\n",
254                         file->i_file, filep->f_line, p);
255
256                 /* Support ANSI macro substitution */
257                 {
258                     struct symtab *sym = defined(p, file_red);
259                     while (sym) {
260                         p = sym->s_value;
261                         debug3("%s : #includes SYMBOL %s = %s\n",
262                                file->i_incstring,
263                                sym -> s_name,
264                                sym -> s_value);
265                         /* mark file as having included a 'soft include' */
266                         file->i_included_sym = TRUE; 
267                         sym = defined(p, file_red);
268                     }
269                 }
270
271                 /*
272                  * Separate the name of the include file.
273                  */
274                 while (*p && *p != '"' && *p != '<')
275                         p++;
276                 if (! *p)
277                         return(-2);
278                 if (*p++ == '"') {
279                         ret = INCLUDEDOT;
280                         while (*p && *p != '"')
281                                 *line++ = *p++;
282                 } else
283                         while (*p && *p != '>')
284                                 *line++ = *p++;
285                 *line = '\0';
286                 break;
287         case DEFINE:
288                 /*
289                  * copy the definition back to the beginning of the line.
290                  */
291                 strcpy (line, p);
292                 break;
293         case ELSE:
294         case ENDIF:
295         case ELIF:
296         case PRAGMA:
297         case EJECT:
298                 debug0("%s, line %d: #%s\n",
299                         file->i_file, filep->f_line, directives[ret]);
300                 /*
301                  * nothing to do.
302                  */
303                 break;
304         }
305         return(ret);
306 }
307
308 struct symtab *defined(symbol, file)
309         register char   *symbol;
310         struct inclist  *file;
311 {
312         register struct symtab  *val;
313
314         if (val = slookup(symbol, deflist)) {
315                 debug1("%s defined on command line\n", symbol);
316                 return(val);
317         }
318         if (val = fdefined(symbol, file))
319                 return(val);
320         debug1("%s not defined in %s\n", symbol, file->i_file);
321         return(NULL);
322 }
323
324 struct symtab *fdefined(symbol, file)
325         register char   *symbol;
326         struct inclist  *file;
327 {
328         register struct inclist **ip;
329         register struct symtab  *val;
330         register int    i;
331         static int      recurse_lvl = 0;
332
333         if (file->i_defchecked)
334                 return(NULL);
335         file->i_defchecked = TRUE;
336         if (val = slookup(symbol, file->i_defs))
337                 debug1("%s defined in %s\n", symbol, file->i_file);
338         if (val == NULL && file->i_list)
339                 for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
340                         if (val = fdefined(symbol, *ip)) {
341                                 debug1("%s defined in %s\n",
342                                         symbol, (*ip)->i_file);
343                                 break;
344                         }
345         recurse_lvl--;
346         file->i_defchecked = FALSE;
347
348         return(val);
349 }
350
351 struct symtab *slookup(symbol, stab)
352         register char   *symbol;
353         register struct symtab  *stab;
354 {
355         if (stab)
356                 for (; stab->s_name; stab++)
357                         if (strcmp(symbol, stab->s_name) == 0)
358                                 return(stab);
359         return(NULL);
360 }
361
362 /*
363  * Return true if the #if expression evaluates to 0
364  */
365 zero_value(exp, filep, file_red)
366         register char   *exp;
367         register struct filepointer *filep;
368         register struct inclist *file_red;
369 {
370 #ifdef  CPP
371         return (cppsetup(exp, filep, file_red) == 0);
372 #else   CPP
373         return(TRUE);
374 #endif  CPP
375 }
376
377 define(def, file)
378         register char   *def;
379         register struct inclist *file;
380 {
381         register char   *p;
382         struct symtab   *sp = file->i_lastdef++;
383         register int    i;
384
385         /*
386          * If we are out of space, allocate some more.
387          */
388         if (file->i_defs == NULL
389         || file->i_lastdef == file->i_defs + file->i_deflen) {
390                 if (file->i_defs)
391                         file->i_defs = (struct symtab *) realloc(file->i_defs,
392                             sizeof(struct symtab)*(file->i_deflen+SYMTABINC));
393                 else
394                         file->i_defs = (struct symtab *)
395                                 malloc(sizeof (struct symtab) * SYMTABINC);
396                 i=file->i_deflen;
397                 file->i_deflen += SYMTABINC;
398                 while (i < file->i_deflen)
399                         file->i_defs[ i++ ].s_name = NULL;
400                 file->i_lastdef = file->i_defs + file->i_deflen - SYMTABINC;
401                 if (sp) /* be sure we use last cell in previous group */
402                         file->i_lastdef--;
403                 sp = file->i_lastdef++;
404         }
405         else if (file->i_lastdef > file->i_defs + file->i_deflen)
406                 log_fatal("define() botch\n");
407
408         /*
409          * copy the symbol being defined.
410          */
411         p = def;
412         while (isalnum(*p) || *p == '_')
413                 p++;
414         if (*p)
415                 *p++ = '\0';
416         sp->s_name = copy(def);
417
418         /*
419          * And copy its value.
420          */
421         while (*p == ' ' && *p == '\t')
422                 p++;
423         sp->s_value = copy(p);
424 }
This page took 1.479353 seconds and 5 git commands to generate.