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);
112 //hmmm: is this right?
123 warning("%s, line %d: incomplete undef == \"%s\"\n",
124 file_red->i_file, filep->f_line, line);
127 undefine(line, file_red);
130 add_include(filep, file, file_red, line, false, failOK);
133 add_include(filep, file, file_red, line, true, failOK);
136 warning("%s: %d: %s\n", file_red->i_file,
137 filep->f_line, line);
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);
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);
165 int gobble(register struct filepointer *filep, inclist *file,
171 while ((line = getline(filep))) {
172 switch(type = deftype(line, filep, file_red, file, false)) {
178 type = gobble(filep, file, file_red);
179 while ((type == ELIF) || (type == ELIFFALSE) ||
180 (type == ELIFGUESSFALSE))
181 type = gobble(filep, file, file_red);
183 (void)gobble(filep, file, file_red);
187 debug(0,("%s, line %d: #%s\n",
188 file->i_file, filep->f_line,
207 warning("%s, line %d: unknown directive == \"%s\"\n",
208 file_red->i_file, filep->f_line, line);
216 * Decide what type of # directive this line is.
218 int deftype(register char *line, register struct filepointer *filep,
219 register inclist *file_red, register inclist *file,
223 char *directive, savechar;
227 * Parse the directive...
230 while (*directive == ' ' || *directive == '\t')
234 while (*p >= 'a' && *p <= 'z')
238 ret = match(directive, directives);
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.
247 if (ret == ELIF && !parse_it)
249 while (*p == ' ' || *p == '\t')
252 * parse an expression.
254 debug(0,("%s, line %d: #elif %s ",
255 file->i_file, filep->f_line, p));
256 ret = zero_value(p, filep, file_red);
259 debug(0,("false...\n"));
263 return(ELIFGUESSFALSE);
267 debug(0,("true...\n"));
272 if (ret < 0 || ! parse_it)
276 * now decide how to parse the directive, and do it.
278 while (*p == ' ' || *p == '\t')
283 * parse an expression.
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));
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?
296 * separate the name of a single symbol.
298 while (isalnum(*p) || *p == '_')
303 debug(2,("%s, line %d: #include %s\n",
304 file->i_file, filep->f_line, p));
306 /* Support ANSI macro substitution */
308 struct symtab *sym = isdefined(p, file_red, NULL);
311 debug(3,("%s : #includes SYMBOL %s = %s\n",
315 /* mark file as having included a 'soft include' */
316 file->i_included_sym = true;
317 sym = isdefined(p, file_red, NULL);
322 * Separate the name of the include file.
324 while (*p && *p != '"' && *p != '<')
330 while (*p && *p != '"')
333 while (*p && *p != '>')
339 * copy the definition back to the beginning of the line.
352 debug(0,("%s, line %d: #%s\n",
353 file->i_file, filep->f_line, directives[ret]));
362 symtab *isdefined(register char *symbol, inclist *file,
365 register struct symtab *val;
367 if ((val = slookup(symbol, &maininclist))) {
368 debug(1,("%s defined on command line\n", symbol));
369 if (srcfile != NULL) *srcfile = &maininclist;
372 if ((val = fdefined(symbol, file, srcfile)))
374 debug(1,("%s not defined in %s\n", symbol, file->i_file));
378 struct symtab *fdefined(register char *symbol, inclist *file, inclist **srcfile)
380 register inclist **ip;
381 register struct symtab *val;
383 static int recurse_lvl = 0;
385 if (file->i_defchecked)
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)
392 for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
393 if ((val = fdefined(symbol, *ip, srcfile))) {
397 else if (val != NULL && srcfile != NULL) *srcfile = file;
399 file->i_defchecked = false;
405 * Return type based on if the #if expression evaluates to 0
407 int zero_value(register char *exp, register struct filepointer *filep,
408 register inclist *file_red)
410 if (cppsetup(exp, filep, file_red))
416 void define(char *def, inclist *file)
420 /* Separate symbol name and its value */
422 while (isalnum(*val) || *val == '_')
426 while (*val == ' ' || *val == '\t')
431 define2(def, val, file);
434 void define2(char *name, char *val, inclist *file)
436 int first, last, below;
437 register struct symtab *sp = NULL, *dest;
439 /* Make space if it's needed */
440 if (file->i_defs == NULL)
442 file->i_defs = (struct symtab *)
443 malloc(sizeof (struct symtab) * SYMTABINC);
444 file->i_deflen = SYMTABINC;
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));
452 if (file->i_defs == NULL)
453 fatalerr("malloc()/realloc() failure in insert_defn()\n");
456 last = file->i_ndefs - 1;
457 while (last >= first)
459 /* Fast inline binary search */
462 register int middle = (first + last) / 2;
464 /* Fast inline strchr() */
466 s2 = file->i_defs[middle].s_name;
467 while (*s1++ == *s2++)
468 if (s2[-1] == '\0') break;
470 /* If exact match, set sp and break */
473 sp = file->i_defs + middle;
477 /* If name > i_defs[middle] ... */
486 below = last = middle - 1;
490 /* Search is done. If we found an exact match to the symbol name,
491 just replace its s_value */
495 sp->s_value = copy(val);
499 sp = file->i_defs + file->i_ndefs++;
500 dest = file->i_defs + below + 1;
506 sp->s_name = copy(name);
507 sp->s_value = copy(val);
510 struct symtab *slookup(register char *symbol, register inclist *file)
512 register int first = 0;
513 register int last = file->i_ndefs - 1;
515 if (file) while (last >= first)
517 /* Fast inline binary search */
520 register int middle = (first + last) / 2;
522 /* Fast inline strchr() */
524 s2 = file->i_defs[middle].s_name;
525 while (*s1++ == *s2++)
526 if (s2[-1] == '\0') break;
528 /* If exact match, we're done */
531 return file->i_defs + middle;
534 /* If symbol > i_defs[middle] ... */
548 void undefine(char *symbol, register inclist *file)
550 register struct symtab *ptr;
552 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
555 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)