1 /* $Xorg: parse.c,v 1.6 2001/02/09 02:03:16 xorgcvs Exp $ */
4 Copyright (c) 1993, 1994, 1998 The Open Group
6 Permission to use, copy, modify, distribute, and sell this software and its
7 documentation for any purpose is hereby granted without fee, provided that
8 the above copyright notice appear in all copies and that both that
9 copyright notice and this permission notice appear in supporting
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall not be
23 used in advertising or otherwise to promote the sale, use or other dealings
24 in this Software without prior written authorization from The Open Group.
27 /* $XFree86: xc/config/makedepend/parse.c,v 1.12 2002/02/26 05:09:10 tsi Exp $ */
31 extern char *directives[];
32 extern struct inclist inclist[ MAXFILES ],
35 extern char *includedirs[ ],
38 static int deftype (char *line, struct filepointer *filep,
39 struct inclist *file_red, struct inclist *file,
41 static int zero_value(char *filename, char *exp, struct filepointer *filep,
42 struct inclist *file_red);
43 static int merge2defines(struct inclist *file1, struct inclist *file2);
46 gobble(struct filepointer *filep, struct inclist *file,
47 struct inclist *file_red)
52 while ((line = getnextline(filep))) {
53 switch(type = deftype(line, filep, file_red, file, FALSE)) {
59 type = gobble(filep, file, file_red);
60 while ((type == ELIF) || (type == ELIFFALSE) ||
61 (type == ELIFGUESSFALSE))
62 type = gobble(filep, file, file_red);
64 (void)gobble(filep, file, file_red);
68 debug(0,("%s, line %d: #%s\n",
69 file->i_file, filep->f_line,
90 warning("%s", file_red->i_file);
92 warning1(" (reading %s)", file->i_file);
93 warning1(", line %d: unknown directive == \"%s\"\n",
102 * Decide what type of # directive this line is.
105 deftype (char *line, struct filepointer *filep,
106 struct inclist *file_red, struct inclist *file, int parse_it)
109 char *directive, savechar, *q;
113 * Parse the directive...
116 while (*directive == ' ' || *directive == '\t')
120 while ((*p == '_') || (*p >= 'a' && *p <= 'z'))
124 ret = match(directive, directives);
127 /* If we don't recognize this compiler directive or we happen to just
128 * be gobbling up text while waiting for an #endif or #elif or #else
129 * in the case of an #elif we must check the zero_value and return an
130 * ELIF or an ELIFFALSE.
133 if (ret == ELIF && !parse_it)
135 while (*p == ' ' || *p == '\t')
138 * parse an expression.
140 debug(0,("%s, line %d: #elif %s ",
141 file->i_file, filep->f_line, p));
142 ret = zero_value(file->i_file, p, filep, file_red);
145 debug(0,("false...\n"));
149 return(ELIFGUESSFALSE);
153 debug(0,("true...\n"));
158 if (ret < 0 || ! parse_it)
162 * now decide how to parse the directive, and do it.
164 while (*p == ' ' || *p == '\t')
169 } while (*q == ' ' || *q == '\t');
174 * parse an expression.
176 ret = zero_value(file->i_file, p, filep, file_red);
177 debug(0,("%s, line %d: %s #if %s\n",
178 file->i_file, filep->f_line, ret?"false":"true", p));
182 debug(0,("%s, line %d: #%s %s\n",
183 file->i_file, filep->f_line, directives[ret], p));
186 * separate the name of a single symbol.
188 while (isalnum(*p) || *p == '_')
194 debug(2,("%s, line %d: #include%s %s\n",
195 file->i_file, filep->f_line,
196 (ret == INCLUDE) ? "" : "_next", p));
198 /* Support ANSI macro substitution */
202 if (!*p || *p == '"' || *p == '<')
205 sym = isdefined(p, file_red, NULL);
210 debug(3,("%s : #includes SYMBOL %s = %s\n",
214 /* mark file as having included a 'soft include' */
215 file->i_flags |= INCLUDED_SYM;
219 * Separate the name of the include file.
221 while (*p && *p != '"' && *p != '<')
229 ret = INCLUDENEXTDOT;
230 while (*p && *p != '"')
233 while (*p && *p != '>')
239 * copy the definition back to the beginning of the line.
252 debug(0,("%s, line %d: #%s\n",
253 file->i_file, filep->f_line, directives[ret]));
263 fdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
268 static int recurse_lvl = 0;
270 if (file->i_flags & DEFCHECKED)
272 debug(2,("Looking for %s in %s\n", symbol, file->i_file));
273 file->i_flags |= DEFCHECKED;
274 if ((val = slookup(symbol, file)))
275 debug(1,("%s defined in %s as %s\n",
276 symbol, file->i_file, (*val)->s_value));
277 if (val == NULL && file->i_list)
279 for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
280 if (file->i_merged[i]==FALSE) {
281 val = fdefined(symbol, *ip, srcfile);
282 file->i_merged[i]=merge2defines(file,*ip);
283 if (val!=NULL) break;
286 else if (val != NULL && srcfile != NULL) *srcfile = file;
288 file->i_flags &= ~DEFCHECKED;
294 isdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
298 if ((val = slookup(symbol, &maininclist))) {
299 debug(1,("%s defined on command line\n", symbol));
300 if (srcfile != NULL) *srcfile = &maininclist;
303 if ((val = fdefined(symbol, file, srcfile)))
305 debug(1,("%s not defined in %s\n", symbol, file->i_file));
310 * Return type based on if the #if expression evaluates to 0
313 zero_value(char *filename,
315 struct filepointer *filep,
316 struct inclist *file_red)
318 if (cppsetup(filename, exp, filep, file_red))
325 define2(char *name, char *val, struct inclist *file)
327 int first, last, below;
328 register struct symtab **sp = NULL, **dest;
331 /* Make space if it's needed */
332 if (file->i_defs == NULL)
334 file->i_defs = (struct symtab **)
335 malloc(sizeof (struct symtab*) * SYMTABINC);
338 else if (!(file->i_ndefs % SYMTABINC))
339 file->i_defs = (struct symtab **)
340 realloc(file->i_defs,
341 sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
343 if (file->i_defs == NULL)
344 fatalerr("malloc()/realloc() failure in insert_defn()\n");
347 last = file->i_ndefs - 1;
348 while (last >= first)
350 /* Fast inline binary search */
353 register int middle = (first + last) / 2;
355 /* Fast inline strchr() */
357 s2 = file->i_defs[middle]->s_name;
358 while (*s1++ == *s2++)
359 if (s2[-1] == '\0') break;
361 /* If exact match, set sp and break */
364 sp = file->i_defs + middle;
368 /* If name > i_defs[middle] ... */
377 below = last = middle - 1;
381 /* Search is done. If we found an exact match to the symbol name,
382 just replace its s_value */
385 debug(1,("redefining %s from %s to %s in file %s\n",
386 name, (*sp)->s_value, val, file->i_file));
387 free((*sp)->s_value);
388 (*sp)->s_value = copy(val);
392 sp = file->i_defs + file->i_ndefs++;
393 dest = file->i_defs + below + 1;
399 stab = (struct symtab *) malloc(sizeof (struct symtab));
401 fatalerr("malloc()/realloc() failure in insert_defn()\n");
403 debug(1,("defining %s to %s in file %s\n", name, val, file->i_file));
404 stab->s_name = copy(name);
405 stab->s_value = copy(val);
410 define(char *def, struct inclist *file)
414 /* Separate symbol name and its value */
416 while (isalnum(*val) || *val == '_')
420 while (*val == ' ' || *val == '\t')
425 define2(def, val, file);
429 slookup(char *symbol, struct inclist *file)
431 register int first = 0;
432 register int last = file->i_ndefs - 1;
434 if (file) while (last >= first)
436 /* Fast inline binary search */
439 register int middle = (first + last) / 2;
441 /* Fast inline strchr() */
443 s2 = file->i_defs[middle]->s_name;
444 while (*s1++ == *s2++)
445 if (s2[-1] == '\0') break;
447 /* If exact match, we're done */
450 return file->i_defs + middle;
453 /* If symbol > i_defs[middle] ... */
468 merge2defines(struct inclist *file1, struct inclist *file2)
472 if ((file1==NULL) || (file2==NULL) ||
473 !(file2->i_flags & FINISHED))
476 for (i=0; i < file2->i_listlen; i++)
477 if (file2->i_merged[i]==FALSE)
482 int last1 = file1->i_ndefs - 1;
485 int last2 = file2->i_ndefs - 1;
488 struct symtab** i_defs = NULL;
489 int deflen=file1->i_ndefs+file2->i_ndefs;
491 debug(2,("merging %s into %s\n",
492 file2->i_file, file1->i_file));
496 /* make sure deflen % SYMTABINC == 0 is still true */
497 deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
498 i_defs=(struct symtab**)
499 malloc(deflen*sizeof(struct symtab*));
500 if (i_defs==NULL) return 0;
503 while ((last1 >= first1) && (last2 >= first2))
505 char *s1=file1->i_defs[first1]->s_name;
506 char *s2=file2->i_defs[first2]->s_name;
508 if (strcmp(s1,s2) < 0)
509 i_defs[first++]=file1->i_defs[first1++];
510 else if (strcmp(s1,s2) > 0)
511 i_defs[first++]=file2->i_defs[first2++];
514 i_defs[first++]=file2->i_defs[first2++];
518 while (last1 >= first1)
520 i_defs[first++]=file1->i_defs[first1++];
522 while (last2 >= first2)
524 i_defs[first++]=file2->i_defs[first2++];
527 if (file1->i_defs) free(file1->i_defs);
528 file1->i_defs=i_defs;
529 file1->i_ndefs=first;
536 undefine(char *symbol, struct inclist *file)
538 register struct symtab **ptr;
539 struct inclist *srcfile;
540 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
543 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
549 find_includes(struct filepointer *filep, struct inclist *file,
550 struct inclist *file_red, int recursion, boolean failOK)
552 struct inclist *inclistp;
558 while ((line = getnextline(filep))) {
559 switch(type = deftype(line, filep, file_red, file, TRUE)) {
562 type = find_includes(filep, file,
563 file_red, recursion+1, failOK);
564 while ((type == ELIF) || (type == ELIFFALSE) ||
565 (type == ELIFGUESSFALSE))
566 type = gobble(filep, file, file_red);
568 gobble(filep, file, file_red);
573 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
577 type = gobble(filep, file, file_red);
579 find_includes(filep, file,
580 file_red, recursion+1, recfailOK);
585 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
590 if ((type == IFDEF && isdefined(line, file_red, NULL))
591 || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
592 debug(1,(type == IFNDEF ?
593 "line %d: %s !def'd in %s via %s%s\n" : "",
595 file->i_file, file_red->i_file, ": doit"));
596 type = find_includes(filep, file,
597 file_red, recursion+1, failOK);
598 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
599 type = gobble(filep, file, file_red);
601 gobble(filep, file, file_red);
604 debug(1,(type == IFDEF ?
605 "line %d: %s !def'd in %s via %s%s\n" : "",
607 file->i_file, file_red->i_file, ": gobble"));
608 type = gobble(filep, file, file_red);
610 find_includes(filep, file,
611 file_red, recursion+1, failOK);
612 else if (type == ELIF)
614 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
623 gobble(filep, file, file_red);
632 warning("%s", file_red->i_file);
633 if (file_red != file)
634 warning1(" (reading %s)", file->i_file);
635 warning1(", line %d: incomplete undef == \"%s\"\n",
636 filep->f_line, line);
639 undefine(line, file_red);
645 inclistp = inclistnext;
646 includedirsp = includedirsnext;
647 debug(2,("%s, reading %s, includes %s\n",
648 file_red->i_file, file->i_file, line));
649 add_include(filep, file, file_red, line, type, failOK);
650 inclistnext = inclistp;
651 includedirsnext = includedirsp;
655 warning("%s", file_red->i_file);
656 if (file_red != file)
657 warning1(" (reading %s)", file->i_file);
658 warning1(", line %d: %s\n",
659 filep->f_line, line);
668 warning("%s", file_red->i_file);
669 if (file_red != file)
670 warning1(" (reading %s)", file->i_file);
671 warning1(", line %d: unknown directive == \"%s\"\n",
672 filep->f_line, line);
675 warning("%s", file_red->i_file);
676 if (file_red != file)
677 warning1(" (reading %s)", file->i_file);
678 warning1(", line %d: incomplete include == \"%s\"\n",
679 filep->f_line, line);
683 file->i_flags |= FINISHED;
684 debug(2,("finished with %s\n", file->i_file));