1 /* $XConsortium: parse.c,v 1.30 94/04/17 20:10:38 gildea Exp $ */
4 Copyright (c) 1993, 1994 X Consortium
6 Permission is hereby granted, free of charge, to any person obtaining a copy
7 of this software and associated documentation files (the "Software"), to deal
8 in the Software without restriction, including without limitation the rights
9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 copies of the Software, and to permit persons to whom the Software is
11 furnished to do so, subject to the following conditions:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 Except as contained in this notice, the name of the X Consortium shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from the X Consortium.
30 #pragma warning(disable : 4996)
37 extern const char *directives[];
38 extern inclist maininclist;
40 int find_includes(struct filepointer *filep, inclist *file, inclist *file_red, int recursion, bool failOK)
46 while ((line = getline(filep))) {
47 switch(type = deftype(line, filep, file_red, file, true)) {
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);
56 gobble(filep, file, file_red);
61 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
65 type = gobble(filep, file, file_red);
67 find_includes(filep, file,
68 file_red, recursion+1, recfailOK);
73 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
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" : "",
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);
89 gobble(filep, file, file_red);
92 debug(1,(type == IFDEF ?
93 "line %d: %s !def'd in %s via %s%s\n" : "",
95 file->i_file, file_red->i_file, ": gobble"));
96 type = gobble(filep, file, file_red);
98 find_includes(filep, file,
99 file_red, recursion+1, failOK);
100 else if (type == ELIF)
102 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
111 gobble(filep, file, file_red);
120 warning("%s, line %d: incomplete undef == \"%s\"\n",
121 file_red->i_file, filep->f_line, line);
124 undefine(line, file_red);
127 add_include(filep, file, file_red, line, false, failOK);
130 add_include(filep, file, file_red, line, true, failOK);
133 warning("%s: %d: %s\n", file_red->i_file,
134 filep->f_line, line);
144 warning("%s", file_red->i_file);
145 if (file_red != file)
146 warning1(" (reading %s)", file->i_file);
147 warning1(", line %d: unknown directive == \"%s\"\n",
148 filep->f_line, line);
151 warning("%s", file_red->i_file);
152 if (file_red != file)
153 warning1(" (reading %s)", file->i_file);
154 warning1(", line %d: incomplete include == \"%s\"\n",
155 filep->f_line, line);
162 int gobble(register struct filepointer *filep, inclist *file,
168 while ((line = getline(filep))) {
169 switch(type = deftype(line, filep, file_red, file, false)) {
175 type = gobble(filep, file, file_red);
176 while ((type == ELIF) || (type == ELIFFALSE) ||
177 (type == ELIFGUESSFALSE))
178 type = gobble(filep, file, file_red);
180 (void)gobble(filep, file, file_red);
184 debug(0,("%s, line %d: #%s\n",
185 file->i_file, filep->f_line,
204 warning("%s, line %d: unknown directive == \"%s\"\n",
205 file_red->i_file, filep->f_line, line);
213 * Decide what type of # directive this line is.
215 int deftype(register char *line, register struct filepointer *filep,
216 register inclist *file_red, register inclist *file,
220 char *directive, savechar;
224 * Parse the directive...
227 while (*directive == ' ' || *directive == '\t')
231 while (*p >= 'a' && *p <= 'z')
235 ret = match(directive, directives);
238 /* If we don't recognize this compiler directive or we happen to just
239 * be gobbling up text while waiting for an #endif or #elif or #else
240 * in the case of an #elif we must check the zero_value and return an
241 * ELIF or an ELIFFALSE.
244 if (ret == ELIF && !parse_it)
246 while (*p == ' ' || *p == '\t')
249 * parse an expression.
251 debug(0,("%s, line %d: #elif %s ",
252 file->i_file, filep->f_line, p));
253 ret = zero_value(p, filep, file_red);
256 debug(0,("false...\n"));
260 return(ELIFGUESSFALSE);
264 debug(0,("true...\n"));
269 if (ret < 0 || ! parse_it)
273 * now decide how to parse the directive, and do it.
275 while (*p == ' ' || *p == '\t')
280 * parse an expression.
282 ret = zero_value(p, filep, file_red);
283 debug(0,("%s, line %d: %s #if %s\n",
284 file->i_file, filep->f_line, ret?"false":"true", p));
288 debug(0,("%s, line %d: #%s %s\n",
289 file->i_file, filep->f_line, directives[ret], p));
292 * separate the name of a single symbol.
294 while (isalnum(*p) || *p == '_')
299 debug(2,("%s, line %d: #include %s\n",
300 file->i_file, filep->f_line, p));
302 /* Support ANSI macro substitution */
304 struct symtab *sym = isdefined(p, file_red, NULL);
307 debug(3,("%s : #includes SYMBOL %s = %s\n",
311 /* mark file as having included a 'soft include' */
312 file->i_included_sym = true;
313 sym = isdefined(p, file_red, NULL);
318 * Separate the name of the include file.
320 while (*p && *p != '"' && *p != '<')
326 while (*p && *p != '"')
329 while (*p && *p != '>')
335 * copy the definition back to the beginning of the line.
348 debug(0,("%s, line %d: #%s\n",
349 file->i_file, filep->f_line, directives[ret]));
358 symtab *isdefined(register char *symbol, inclist *file,
361 register struct symtab *val;
363 if ((val = slookup(symbol, &maininclist))) {
364 debug(1,("%s defined on command line\n", symbol));
365 if (srcfile != NULL) *srcfile = &maininclist;
368 if ((val = fdefined(symbol, file, srcfile)))
370 debug(1,("%s not defined in %s\n", symbol, file->i_file));
374 struct symtab *fdefined(register char *symbol, inclist *file, inclist **srcfile)
376 register inclist **ip;
377 register struct symtab *val;
379 static int recurse_lvl = 0;
381 if (file->i_defchecked)
383 file->i_defchecked = true;
384 if ((val = slookup(symbol, file)))
385 debug(1,("%s defined in %s as %s\n", symbol, file->i_file, val->s_value));
386 if (val == NULL && file->i_list)
388 for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
389 if ((val = fdefined(symbol, *ip, srcfile))) {
393 else if (val != NULL && srcfile != NULL) *srcfile = file;
395 file->i_defchecked = false;
401 * Return type based on if the #if expression evaluates to 0
403 int zero_value(register char *exp, register struct filepointer *filep,
404 register inclist *file_red)
406 if (cppsetup(exp, filep, file_red))
412 void define(char *def, inclist *file)
416 /* Separate symbol name and its value */
418 while (isalnum(*val) || *val == '_')
422 while (*val == ' ' || *val == '\t')
427 define2(def, val, file);
430 void define2(char *name, char *val, inclist *file)
432 int first, last, below;
433 register struct symtab *sp = NULL, *dest;
435 /* Make space if it's needed */
436 if (file->i_defs == NULL)
438 file->i_defs = (struct symtab *)
439 malloc(sizeof (struct symtab) * SYMTABINC);
440 file->i_deflen = SYMTABINC;
443 else if (file->i_ndefs == file->i_deflen)
444 file->i_defs = (struct symtab *)
445 realloc(file->i_defs,
446 sizeof(struct symtab)*(file->i_deflen+=SYMTABINC));
448 if (file->i_defs == NULL)
449 fatalerr("malloc()/realloc() failure in insert_defn()\n");
452 last = file->i_ndefs - 1;
453 while (last >= first)
455 /* Fast inline binary search */
458 register int middle = (first + last) / 2;
460 /* Fast inline strchr() */
462 s2 = file->i_defs[middle].s_name;
463 while (*s1++ == *s2++)
464 if (s2[-1] == '\0') break;
466 /* If exact match, set sp and break */
469 sp = file->i_defs + middle;
473 /* If name > i_defs[middle] ... */
482 below = last = middle - 1;
486 /* Search is done. If we found an exact match to the symbol name,
487 just replace its s_value */
491 sp->s_value = copy(val);
495 sp = file->i_defs + file->i_ndefs++;
496 dest = file->i_defs + below + 1;
502 sp->s_name = copy(name);
503 sp->s_value = copy(val);
506 struct symtab *slookup(register char *symbol, register inclist *file)
508 register int first = 0;
509 register int last = file->i_ndefs - 1;
511 if (file) while (last >= first)
513 /* Fast inline binary search */
516 register int middle = (first + last) / 2;
518 /* Fast inline strchr() */
520 s2 = file->i_defs[middle].s_name;
521 while (*s1++ == *s2++)
522 if (s2[-1] == '\0') break;
524 /* If exact match, we're done */
527 return file->i_defs + middle;
530 /* If symbol > i_defs[middle] ... */
544 void undefine(char *symbol, register inclist *file)
546 register struct symtab *ptr;
548 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
551 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)