1 /* $XConsortium: parse.c /main/33 1996/12/04 10:11:28 swick $ */
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.
28 /* $XFree86: xc/config/makedepend/parse.c,v 1.3 1997/01/12 10:39:45 dawes Exp $ */
32 extern char *directives[];
33 extern struct inclist maininclist;
36 gobble(filep, file, file_red)
37 register struct filepointer *filep;
38 struct inclist *file, *file_red;
43 while (line = x_getline(filep)) {
44 switch(type = deftype(line, filep, file_red, file, FALSE)) {
50 type = gobble(filep, file, file_red);
51 while ((type == ELIF) || (type == ELIFFALSE) ||
52 (type == ELIFGUESSFALSE))
53 type = gobble(filep, file, file_red);
55 (void)gobble(filep, file, file_red);
59 debug(0,("%s, line %d: #%s\n",
60 file->i_file, filep->f_line,
79 warning("%s, line %d: unknown directive == \"%s\"\n",
80 file_red->i_file, filep->f_line, line);
88 * Decide what type of # directive this line is.
90 int deftype (line, filep, file_red, file, parse_it)
92 register struct filepointer *filep;
93 register struct inclist *file_red, *file;
97 char *directive, savechar;
101 * Parse the directive...
104 while (*directive == ' ' || *directive == '\t')
108 while (*p >= 'a' && *p <= 'z')
112 ret = match(directive, directives);
115 /* If we don't recognize this compiler directive or we happen to just
116 * be gobbling up text while waiting for an #endif or #elif or #else
117 * in the case of an #elif we must check the zero_value and return an
118 * ELIF or an ELIFFALSE.
121 if (ret == ELIF && !parse_it)
123 while (*p == ' ' || *p == '\t')
126 * parse an expression.
128 debug(0,("%s, line %d: #elif %s ",
129 file->i_file, filep->f_line, p));
130 ret = zero_value(p, filep, file_red);
133 debug(0,("false...\n"));
137 return(ELIFGUESSFALSE);
141 debug(0,("true...\n"));
146 if (ret < 0 || ! parse_it)
150 * now decide how to parse the directive, and do it.
152 while (*p == ' ' || *p == '\t')
157 * parse an expression.
159 ret = zero_value(p, filep, file_red);
160 debug(0,("%s, line %d: %s #if %s\n",
161 file->i_file, filep->f_line, ret?"false":"true", p));
165 debug(0,("%s, line %d: #%s %s\n",
166 file->i_file, filep->f_line, directives[ret], p));
169 * separate the name of a single symbol.
171 while (isalnum(*p) || *p == '_')
176 debug(2,("%s, line %d: #include %s\n",
177 file->i_file, filep->f_line, p));
179 /* Support ANSI macro substitution */
181 struct symtab **sym = isdefined(p, file_red, NULL);
184 debug(3,("%s : #includes SYMBOL %s = %s\n",
188 /* mark file as having included a 'soft include' */
189 file->i_flags |= INCLUDED_SYM;
190 sym = isdefined(p, file_red, NULL);
195 * Separate the name of the include file.
197 while (*p && *p != '"' && *p != '<')
203 while (*p && *p != '"')
206 while (*p && *p != '>')
212 * copy the definition back to the beginning of the line.
225 debug(0,("%s, line %d: #%s\n",
226 file->i_file, filep->f_line, directives[ret]));
235 struct symtab **fdefined(symbol, file, srcfile)
236 register char *symbol;
237 struct inclist *file;
238 struct inclist **srcfile;
240 register struct inclist **ip;
241 register struct symtab **val;
243 static int recurse_lvl = 0;
245 if (file->i_flags & DEFCHECKED)
247 file->i_flags |= DEFCHECKED;
248 if (val = slookup(symbol, file))
249 debug(1,("%s defined in %s as %s\n",
250 symbol, file->i_file, (*val)->s_value));
251 if (val == NULL && file->i_list)
253 for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
254 if (file->i_merged[i]==FALSE) {
255 val = fdefined(symbol, *ip, srcfile);
256 if ((*ip)->i_flags & FINISHED) {
257 merge2defines(file,*ip);
258 file->i_merged[i]=TRUE;
260 if (val!=NULL) break;
263 else if (val != NULL && srcfile != NULL) *srcfile = file;
265 file->i_flags &= ~DEFCHECKED;
270 struct symtab **isdefined(symbol, file, srcfile)
271 register char *symbol;
272 struct inclist *file;
273 struct inclist **srcfile;
275 register struct symtab **val;
277 if (val = slookup(symbol, &maininclist)) {
278 debug(1,("%s defined on command line\n", symbol));
279 if (srcfile != NULL) *srcfile = &maininclist;
282 if (val = fdefined(symbol, file, srcfile))
284 debug(1,("%s not defined in %s\n", symbol, file->i_file));
289 * Return type based on if the #if expression evaluates to 0
292 zero_value(exp, filep, file_red)
294 register struct filepointer *filep;
295 register struct inclist *file_red;
297 if (cppsetup(exp, filep, file_red))
304 define2(name, val, file)
306 struct inclist *file;
308 int first, last, below;
309 register struct symtab **sp = NULL, **dest;
312 /* Make space if it's needed */
313 if (file->i_defs == NULL)
315 file->i_defs = (struct symtab **)
316 malloc(sizeof (struct symtab*) * SYMTABINC);
319 else if (!(file->i_ndefs % SYMTABINC))
320 file->i_defs = (struct symtab **)
321 realloc(file->i_defs,
322 sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
324 if (file->i_defs == NULL)
325 fatalerr("malloc()/realloc() failure in insert_defn()\n");
328 last = file->i_ndefs - 1;
329 while (last >= first)
331 /* Fast inline binary search */
334 register int middle = (first + last) / 2;
336 /* Fast inline strchr() */
338 s2 = file->i_defs[middle]->s_name;
339 while (*s1++ == *s2++)
340 if (s2[-1] == '\0') break;
342 /* If exact match, set sp and break */
345 sp = file->i_defs + middle;
349 /* If name > i_defs[middle] ... */
358 below = last = middle - 1;
362 /* Search is done. If we found an exact match to the symbol name,
363 just replace its s_value */
366 free((*sp)->s_value);
367 (*sp)->s_value = copy(val);
371 sp = file->i_defs + file->i_ndefs++;
372 dest = file->i_defs + below + 1;
378 stab = (struct symtab *) malloc(sizeof (struct symtab));
380 fatalerr("malloc()/realloc() failure in insert_defn()\n");
382 stab->s_name = copy(name);
383 stab->s_value = copy(val);
390 struct inclist *file;
394 /* Separate symbol name and its value */
396 while (isalnum(*val) || *val == '_')
400 while (*val == ' ' || *val == '\t')
405 define2(def, val, file);
408 struct symtab **slookup(symbol, file)
409 register char *symbol;
410 register struct inclist *file;
412 register int first = 0;
413 register int last = file->i_ndefs - 1;
415 if (file) while (last >= first)
417 /* Fast inline binary search */
420 register int middle = (first + last) / 2;
422 /* Fast inline strchr() */
424 s2 = file->i_defs[middle]->s_name;
425 while (*s1++ == *s2++)
426 if (s2[-1] == '\0') break;
428 /* If exact match, we're done */
431 return file->i_defs + middle;
434 /* If symbol > i_defs[middle] ... */
448 int merge2defines(file1, file2)
449 struct inclist *file1;
450 struct inclist *file2;
452 if ((file1!=NULL) && (file2!=NULL))
455 int last1 = file1->i_ndefs - 1;
458 int last2 = file2->i_ndefs - 1;
461 struct symtab** i_defs = NULL;
462 int deflen=file1->i_ndefs+file2->i_ndefs;
466 /* make sure deflen % SYMTABINC == 0 is still true */
467 deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
468 i_defs=(struct symtab**)
469 malloc(deflen*sizeof(struct symtab*));
470 if (i_defs==NULL) return 0;
473 while ((last1 >= first1) && (last2 >= first2))
475 char *s1=file1->i_defs[first1]->s_name;
476 char *s2=file2->i_defs[first2]->s_name;
478 if (strcmp(s1,s2) < 0)
479 i_defs[first++]=file1->i_defs[first1++];
480 else if (strcmp(s1,s2) > 0)
481 i_defs[first++]=file2->i_defs[first2++];
484 i_defs[first++]=file2->i_defs[first2++];
488 while (last1 >= first1)
490 i_defs[first++]=file1->i_defs[first1++];
492 while (last2 >= first2)
494 i_defs[first++]=file2->i_defs[first2++];
497 if (file1->i_defs) free(file1->i_defs);
498 file1->i_defs=i_defs;
499 file1->i_ndefs=first;
507 undefine(symbol, file)
509 register struct inclist *file;
511 register struct symtab **ptr;
512 struct inclist *srcfile;
513 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
516 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
522 find_includes(filep, file, file_red, recursion, failOK)
523 struct filepointer *filep;
524 struct inclist *file, *file_red;
532 while (line = x_getline(filep)) {
533 switch(type = deftype(line, filep, file_red, file, TRUE)) {
536 type = find_includes(filep, file,
537 file_red, recursion+1, failOK);
538 while ((type == ELIF) || (type == ELIFFALSE) ||
539 (type == ELIFGUESSFALSE))
540 type = gobble(filep, file, file_red);
542 gobble(filep, file, file_red);
547 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
551 type = gobble(filep, file, file_red);
553 find_includes(filep, file,
554 file_red, recursion+1, recfailOK);
559 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
564 if ((type == IFDEF && isdefined(line, file_red, NULL))
565 || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
566 debug(1,(type == IFNDEF ?
567 "line %d: %s !def'd in %s via %s%s\n" : "",
569 file->i_file, file_red->i_file, ": doit"));
570 type = find_includes(filep, file,
571 file_red, recursion+1, failOK);
572 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
573 type = gobble(filep, file, file_red);
575 gobble(filep, file, file_red);
578 debug(1,(type == IFDEF ?
579 "line %d: %s !def'd in %s via %s%s\n" : "",
581 file->i_file, file_red->i_file, ": gobble"));
582 type = gobble(filep, file, file_red);
584 find_includes(filep, file,
585 file_red, recursion+1, failOK);
586 else if (type == ELIF)
588 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
597 gobble(filep, file, file_red);
606 warning("%s, line %d: incomplete undef == \"%s\"\n",
607 file_red->i_file, filep->f_line, line);
610 undefine(line, file_red);
613 add_include(filep, file, file_red, line, FALSE, failOK);
616 add_include(filep, file, file_red, line, TRUE, failOK);
620 warning("%s: %d: %s\n", file_red->i_file,
621 filep->f_line, line);
630 warning("%s", file_red->i_file);
631 if (file_red != file)
632 warning1(" (reading %s)", file->i_file);
633 warning1(", line %d: unknown directive == \"%s\"\n",
634 filep->f_line, line);
637 warning("%s", file_red->i_file);
638 if (file_red != file)
639 warning1(" (reading %s)", file->i_file);
640 warning1(", line %d: incomplete include == \"%s\"\n",
641 filep->f_line, line);
645 file->i_flags |= FINISHED;