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));