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