VirtualBox

source: kBuild/trunk/src/makedep/parse.c@ 199

Last change on this file since 199 was 164, checked in by bird, 20 years ago

Initial revision

  • Property svn:eol-style set to native
File size: 16.4 KB
Line 
1/* $Xorg: parse.c,v 1.6 2001/02/09 02:03:16 xorgcvs Exp $ */
2/*
3
4Copyright (c) 1993, 1994, 1998 The Open Group
5
6Permission to use, copy, modify, distribute, and sell this software and its
7documentation for any purpose is hereby granted without fee, provided that
8the above copyright notice appear in all copies and that both that
9copyright notice and this permission notice appear in supporting
10documentation.
11
12The above copyright notice and this permission notice shall be included in
13all copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall not be
23used in advertising or otherwise to promote the sale, use or other dealings
24in this Software without prior written authorization from The Open Group.
25
26*/
27/* $XFree86: xc/config/makedepend/parse.c,v 1.11 2001/12/17 20:52:22 dawes Exp $ */
28
29#include "def.h"
30
31extern char *directives[];
32extern struct inclist inclist[ MAXFILES ],
33 *inclistnext,
34 maininclist;
35extern char *includedirs[ ],
36 **includedirsnext;
37
38static int deftype (char *line, struct filepointer *filep,
39 struct inclist *file_red, struct inclist *file,
40 int parse_it);
41static int zero_value(char *filename, char *exp, struct filepointer *filep,
42 struct inclist *file_red);
43static int merge2defines(struct inclist *file1, struct inclist *file2);
44
45static int
46gobble(struct filepointer *filep, struct inclist *file,
47 struct inclist *file_red)
48{
49 char *line;
50 int type;
51
52 while ((line = getnextline(filep))) {
53 switch(type = deftype(line, filep, file_red, file, FALSE)) {
54 case IF:
55 case IFFALSE:
56 case IFGUESSFALSE:
57 case IFDEF:
58 case IFNDEF:
59 type = gobble(filep, file, file_red);
60 while ((type == ELIF) || (type == ELIFFALSE) ||
61 (type == ELIFGUESSFALSE))
62 type = gobble(filep, file, file_red);
63 if (type == ELSE)
64 (void)gobble(filep, file, file_red);
65 break;
66 case ELSE:
67 case ENDIF:
68 debug(0,("%s, line %d: #%s\n",
69 file->i_file, filep->f_line,
70 directives[type]));
71 return(type);
72 case DEFINE:
73 case UNDEF:
74 case INCLUDE:
75 case INCLUDEDOT:
76 case PRAGMA:
77 case ERROR:
78 case IDENT:
79 case SCCS:
80 case EJECT:
81 case WARNING:
82 case INCLUDENEXT:
83 case INCLUDENEXTDOT:
84 break;
85 case ELIF:
86 case ELIFFALSE:
87 case ELIFGUESSFALSE:
88 return(type);
89 case -1:
90 warning("%s", file_red->i_file);
91 if (file_red != file)
92 warning1(" (reading %s)", file->i_file);
93 warning1(", line %d: unknown directive == \"%s\"\n",
94 filep->f_line, line);
95 break;
96 }
97 }
98 return(-1);
99}
100
101/*
102 * Decide what type of # directive this line is.
103 */
104static int
105deftype (char *line, struct filepointer *filep,
106 struct inclist *file_red, struct inclist *file, int parse_it)
107{
108 register char *p;
109 char *directive, savechar, *q;
110 register int ret;
111
112 /*
113 * Parse the directive...
114 */
115 directive=line+1;
116 while (*directive == ' ' || *directive == '\t')
117 directive++;
118
119 p = directive;
120 while ((*p == '_') || (*p >= 'a' && *p <= 'z'))
121 p++;
122 savechar = *p;
123 *p = '\0';
124 ret = match(directive, directives);
125 *p = savechar;
126
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.
131 */
132
133 if (ret == ELIF && !parse_it)
134 {
135 while (*p == ' ' || *p == '\t')
136 p++;
137 /*
138 * parse an expression.
139 */
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);
143 if (ret != IF)
144 {
145 debug(0,("false...\n"));
146 if (ret == IFFALSE)
147 return(ELIFFALSE);
148 else
149 return(ELIFGUESSFALSE);
150 }
151 else
152 {
153 debug(0,("true...\n"));
154 return(ELIF);
155 }
156 }
157
158 if (ret < 0 || ! parse_it)
159 return(ret);
160
161 /*
162 * now decide how to parse the directive, and do it.
163 */
164 while (*p == ' ' || *p == '\t')
165 p++;
166 q = p + strlen(p);
167 do {
168 q--;
169 } while (*q == ' ' || *q == '\t');
170 q[1] = '\0';
171 switch (ret) {
172 case IF:
173 /*
174 * parse an expression.
175 */
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));
179 break;
180 case IFDEF:
181 case IFNDEF:
182 debug(0,("%s, line %d: #%s %s\n",
183 file->i_file, filep->f_line, directives[ret], p));
184 case UNDEF:
185 /*
186 * separate the name of a single symbol.
187 */
188 while (isalnum(*p) || *p == '_')
189 *line++ = *p++;
190 *line = '\0';
191 break;
192 case INCLUDE:
193 case INCLUDENEXT:
194 debug(2,("%s, line %d: #include%s %s\n",
195 file->i_file, filep->f_line,
196 (ret == INCLUDE) ? "" : "_next", p));
197
198 /* Support ANSI macro substitution */
199 while (1) {
200 struct symtab **sym;
201
202 if (!*p || *p == '"' || *p == '<')
203 break;
204
205 sym = isdefined(p, file_red, NULL);
206 if (!sym)
207 break;
208
209 p = (*sym)->s_value;
210 debug(3,("%s : #includes SYMBOL %s = %s\n",
211 file->i_incstring,
212 (*sym) -> s_name,
213 (*sym) -> s_value));
214 /* mark file as having included a 'soft include' */
215 file->i_flags |= INCLUDED_SYM;
216 }
217
218 /*
219 * Separate the name of the include file.
220 */
221 while (*p && *p != '"' && *p != '<')
222 p++;
223 if (! *p)
224 return(-2);
225 if (*p++ == '"') {
226 if (ret == INCLUDE)
227 ret = INCLUDEDOT;
228 else
229 ret = INCLUDENEXTDOT;
230 while (*p && *p != '"')
231 *line++ = *p++;
232 } else
233 while (*p && *p != '>')
234 *line++ = *p++;
235 *line = '\0';
236 break;
237 case DEFINE:
238 /*
239 * copy the definition back to the beginning of the line.
240 */
241 strcpy (line, p);
242 break;
243 case ELSE:
244 case ENDIF:
245 case ELIF:
246 case PRAGMA:
247 case ERROR:
248 case IDENT:
249 case SCCS:
250 case EJECT:
251 case WARNING:
252 debug(0,("%s, line %d: #%s\n",
253 file->i_file, filep->f_line, directives[ret]));
254 /*
255 * nothing to do.
256 */
257 break;
258 }
259 return(ret);
260}
261
262struct symtab **
263fdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
264{
265 struct inclist **ip;
266 struct symtab **val;
267 int i;
268 static int recurse_lvl = 0;
269
270 if (file->i_flags & DEFCHECKED)
271 return(NULL);
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)
278 {
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;
284 }
285 }
286 else if (val != NULL && srcfile != NULL) *srcfile = file;
287 recurse_lvl--;
288 file->i_flags &= ~DEFCHECKED;
289
290 return(val);
291}
292
293struct symtab **
294isdefined(char *symbol, struct inclist *file, struct inclist **srcfile)
295{
296 struct symtab **val;
297
298 if ((val = slookup(symbol, &maininclist))) {
299 debug(1,("%s defined on command line\n", symbol));
300 if (srcfile != NULL) *srcfile = &maininclist;
301 return(val);
302 }
303 if ((val = fdefined(symbol, file, srcfile)))
304 return(val);
305 debug(1,("%s not defined in %s\n", symbol, file->i_file));
306 return(NULL);
307}
308
309/*
310 * Return type based on if the #if expression evaluates to 0
311 */
312static int
313zero_value(char *filename,
314 char *exp,
315 struct filepointer *filep,
316 struct inclist *file_red)
317{
318 if (cppsetup(filename, exp, filep, file_red))
319 return(IFFALSE);
320 else
321 return(IF);
322}
323
324void
325define2(char *name, char *val, struct inclist *file)
326{
327 int first, last, below;
328 register struct symtab **sp = NULL, **dest;
329 struct symtab *stab;
330
331 /* Make space if it's needed */
332 if (file->i_defs == NULL)
333 {
334 file->i_defs = (struct symtab **)
335 malloc(sizeof (struct symtab*) * SYMTABINC);
336 file->i_ndefs = 0;
337 }
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));
342
343 if (file->i_defs == NULL)
344 fatalerr("malloc()/realloc() failure in insert_defn()\n");
345
346 below = first = 0;
347 last = file->i_ndefs - 1;
348 while (last >= first)
349 {
350 /* Fast inline binary search */
351 register char *s1;
352 register char *s2;
353 register int middle = (first + last) / 2;
354
355 /* Fast inline strchr() */
356 s1 = name;
357 s2 = file->i_defs[middle]->s_name;
358 while (*s1++ == *s2++)
359 if (s2[-1] == '\0') break;
360
361 /* If exact match, set sp and break */
362 if (*--s1 == *--s2)
363 {
364 sp = file->i_defs + middle;
365 break;
366 }
367
368 /* If name > i_defs[middle] ... */
369 if (*s1 > *s2)
370 {
371 below = first;
372 first = middle + 1;
373 }
374 /* else ... */
375 else
376 {
377 below = last = middle - 1;
378 }
379 }
380
381 /* Search is done. If we found an exact match to the symbol name,
382 just replace its s_value */
383 if (sp != NULL)
384 {
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);
389 return;
390 }
391
392 sp = file->i_defs + file->i_ndefs++;
393 dest = file->i_defs + below + 1;
394 while (sp > dest)
395 {
396 *sp = sp[-1];
397 sp--;
398 }
399 stab = (struct symtab *) malloc(sizeof (struct symtab));
400 if (stab == NULL)
401 fatalerr("malloc()/realloc() failure in insert_defn()\n");
402
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);
406 *sp = stab;
407}
408
409void
410define(char *def, struct inclist *file)
411{
412 char *val;
413
414 /* Separate symbol name and its value */
415 val = def;
416 while (isalnum(*val) || *val == '_')
417 val++;
418 if (*val)
419 *val++ = '\0';
420 while (*val == ' ' || *val == '\t')
421 val++;
422
423 if (!*val)
424 val = "1";
425 define2(def, val, file);
426}
427
428struct symtab **
429slookup(char *symbol, struct inclist *file)
430{
431 register int first = 0;
432 register int last = file->i_ndefs - 1;
433
434 if (file) while (last >= first)
435 {
436 /* Fast inline binary search */
437 register char *s1;
438 register char *s2;
439 register int middle = (first + last) / 2;
440
441 /* Fast inline strchr() */
442 s1 = symbol;
443 s2 = file->i_defs[middle]->s_name;
444 while (*s1++ == *s2++)
445 if (s2[-1] == '\0') break;
446
447 /* If exact match, we're done */
448 if (*--s1 == *--s2)
449 {
450 return file->i_defs + middle;
451 }
452
453 /* If symbol > i_defs[middle] ... */
454 if (*s1 > *s2)
455 {
456 first = middle + 1;
457 }
458 /* else ... */
459 else
460 {
461 last = middle - 1;
462 }
463 }
464 return(NULL);
465}
466
467static int
468merge2defines(struct inclist *file1, struct inclist *file2)
469{
470 int i;
471
472 if ((file1==NULL) || (file2==NULL) ||
473 !(file2->i_flags & FINISHED))
474 return 0;
475
476 for (i=0; i < file2->i_listlen; i++)
477 if (file2->i_merged[i]==FALSE)
478 return 0;
479
480 {
481 int first1 = 0;
482 int last1 = file1->i_ndefs - 1;
483
484 int first2 = 0;
485 int last2 = file2->i_ndefs - 1;
486
487 int first=0;
488 struct symtab** i_defs = NULL;
489 int deflen=file1->i_ndefs+file2->i_ndefs;
490
491 debug(2,("merging %s into %s\n",
492 file2->i_file, file1->i_file));
493
494 if (deflen>0)
495 {
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;
501 }
502
503 while ((last1 >= first1) && (last2 >= first2))
504 {
505 char *s1=file1->i_defs[first1]->s_name;
506 char *s2=file2->i_defs[first2]->s_name;
507
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++];
512 else /* equal */
513 {
514 i_defs[first++]=file2->i_defs[first2++];
515 first1++;
516 }
517 }
518 while (last1 >= first1)
519 {
520 i_defs[first++]=file1->i_defs[first1++];
521 }
522 while (last2 >= first2)
523 {
524 i_defs[first++]=file2->i_defs[first2++];
525 }
526
527 if (file1->i_defs) free(file1->i_defs);
528 file1->i_defs=i_defs;
529 file1->i_ndefs=first;
530
531 return 1;
532 }
533}
534
535void
536undefine(char *symbol, struct inclist *file)
537{
538 register struct symtab **ptr;
539 struct inclist *srcfile;
540 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
541 {
542 srcfile->i_ndefs--;
543 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
544 *ptr = ptr[1];
545 }
546}
547
548int
549find_includes(struct filepointer *filep, struct inclist *file,
550 struct inclist *file_red, int recursion, boolean failOK)
551{
552 struct inclist *inclistp;
553 char **includedirsp;
554 register char *line;
555 register int type;
556 boolean recfailOK;
557
558 while ((line = getnextline(filep))) {
559 switch(type = deftype(line, filep, file_red, file, TRUE)) {
560 case IF:
561 doif:
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);
567 if (type == ELSE)
568 gobble(filep, file, file_red);
569 break;
570 case IFFALSE:
571 case IFGUESSFALSE:
572 doiffalse:
573 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
574 recfailOK = TRUE;
575 else
576 recfailOK = failOK;
577 type = gobble(filep, file, file_red);
578 if (type == ELSE)
579 find_includes(filep, file,
580 file_red, recursion+1, recfailOK);
581 else
582 if (type == ELIF)
583 goto doif;
584 else
585 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
586 goto doiffalse;
587 break;
588 case IFDEF:
589 case IFNDEF:
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" : "",
594 filep->f_line, line,
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);
600 if (type == ELSE)
601 gobble(filep, file, file_red);
602 }
603 else {
604 debug(1,(type == IFDEF ?
605 "line %d: %s !def'd in %s via %s%s\n" : "",
606 filep->f_line, line,
607 file->i_file, file_red->i_file, ": gobble"));
608 type = gobble(filep, file, file_red);
609 if (type == ELSE)
610 find_includes(filep, file,
611 file_red, recursion+1, failOK);
612 else if (type == ELIF)
613 goto doif;
614 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
615 goto doiffalse;
616 }
617 break;
618 case ELSE:
619 case ELIFFALSE:
620 case ELIFGUESSFALSE:
621 case ELIF:
622 if (!recursion)
623 gobble(filep, file, file_red);
624 case ENDIF:
625 if (recursion)
626 return(type);
627 case DEFINE:
628 define(line, file);
629 break;
630 case UNDEF:
631 if (!*line) {
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);
637 break;
638 }
639 undefine(line, file_red);
640 break;
641 case INCLUDE:
642 case INCLUDEDOT:
643 case INCLUDENEXT:
644 case INCLUDENEXTDOT:
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;
652 break;
653 case ERROR:
654 case WARNING:
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);
660 break;
661
662 case PRAGMA:
663 case IDENT:
664 case SCCS:
665 case EJECT:
666 break;
667 case -1:
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);
673 break;
674 case -2:
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);
680 break;
681 }
682 }
683 file->i_flags |= FINISHED;
684 debug(2,("finished with %s\n", file->i_file));
685 return(-1);
686}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette