1 dawes 1.1.1.2 /* $XConsortium: parse.c /main/31 1995/12/08 18:26:41 gildea $ */
|
2 dawes 1.1 /*
3
4 Copyright (c) 1993, 1994 X Consortium
5
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:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
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.
22
23 dawes 1.1 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.
26
27 */
28
29 #include "def.h"
30
31 extern char *directives[];
32 extern struct inclist maininclist;
33
34 find_includes(filep, file, file_red, recursion, failOK)
35 struct filepointer *filep;
36 struct inclist *file, *file_red;
37 int recursion;
38 boolean failOK;
39 {
40 register char *line;
41 register int type;
42 boolean recfailOK;
43
44 dawes 1.1 while (line = getline(filep)) {
45 switch(type = deftype(line, filep, file_red, file, TRUE)) {
46 case IF:
47 doif:
48 type = find_includes(filep, file,
49 file_red, recursion+1, failOK);
50 while ((type == ELIF) || (type == ELIFFALSE) ||
51 (type == ELIFGUESSFALSE))
52 type = gobble(filep, file, file_red);
53 if (type == ELSE)
54 gobble(filep, file, file_red);
55 break;
56 case IFFALSE:
57 case IFGUESSFALSE:
58 doiffalse:
59 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
60 recfailOK = TRUE;
61 else
62 recfailOK = failOK;
63 type = gobble(filep, file, file_red);
64 if (type == ELSE)
65 dawes 1.1 find_includes(filep, file,
66 file_red, recursion+1, recfailOK);
67 else
68 if (type == ELIF)
69 goto doif;
70 else
71 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
72 goto doiffalse;
73 break;
74 case IFDEF:
75 case IFNDEF:
76 if ((type == IFDEF && isdefined(line, file_red, NULL))
77 || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
78 debug(1,(type == IFNDEF ?
79 "line %d: %s !def'd in %s via %s%s\n" : "",
80 filep->f_line, line,
81 file->i_file, file_red->i_file, ": doit"));
82 type = find_includes(filep, file,
83 file_red, recursion+1, failOK);
84 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
85 type = gobble(filep, file, file_red);
86 dawes 1.1 if (type == ELSE)
87 gobble(filep, file, file_red);
88 }
89 else {
90 debug(1,(type == IFDEF ?
91 "line %d: %s !def'd in %s via %s%s\n" : "",
92 filep->f_line, line,
93 file->i_file, file_red->i_file, ": gobble"));
94 type = gobble(filep, file, file_red);
95 if (type == ELSE)
96 find_includes(filep, file,
97 file_red, recursion+1, failOK);
98 else if (type == ELIF)
99 goto doif;
100 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
101 goto doiffalse;
102 }
103 break;
104 case ELSE:
105 case ELIFFALSE:
106 case ELIFGUESSFALSE:
107 dawes 1.1 case ELIF:
108 if (!recursion)
109 gobble(filep, file, file_red);
110 case ENDIF:
111 if (recursion)
112 return(type);
113 case DEFINE:
114 define(line, file);
115 break;
116 case UNDEF:
117 if (!*line) {
118 warning("%s, line %d: incomplete undef == \"%s\"\n",
119 file_red->i_file, filep->f_line, line);
120 break;
121 }
122 undefine(line, file_red);
123 break;
124 case INCLUDE:
125 add_include(filep, file, file_red, line, FALSE, failOK);
126 break;
127 case INCLUDEDOT:
128 dawes 1.1 add_include(filep, file, file_red, line, TRUE, failOK);
129 break;
130 case ERROR:
131 warning("%s: %d: %s\n", file_red->i_file,
132 filep->f_line, line);
133 break;
134
135 case PRAGMA:
136 case IDENT:
137 case SCCS:
138 case EJECT:
139 break;
140 case -1:
141 warning("%s", file_red->i_file);
142 if (file_red != file)
143 warning1(" (reading %s)", file->i_file);
144 warning1(", line %d: unknown directive == \"%s\"\n",
145 filep->f_line, line);
146 break;
147 case -2:
148 warning("%s", file_red->i_file);
149 dawes 1.1 if (file_red != file)
150 warning1(" (reading %s)", file->i_file);
151 warning1(", line %d: incomplete include == \"%s\"\n",
152 filep->f_line, line);
153 break;
154 }
155 }
|
156 dawes 1.1.1.2 file->i_flags |= FINISHED;
|
157 dawes 1.1 return(-1);
158 }
159
160 gobble(filep, file, file_red)
161 register struct filepointer *filep;
162 struct inclist *file, *file_red;
163 {
164 register char *line;
165 register int type;
166
167 while (line = getline(filep)) {
168 switch(type = deftype(line, filep, file_red, file, FALSE)) {
169 case IF:
170 case IFFALSE:
171 case IFGUESSFALSE:
172 case IFDEF:
173 case IFNDEF:
174 type = gobble(filep, file, file_red);
175 while ((type == ELIF) || (type == ELIFFALSE) ||
176 (type == ELIFGUESSFALSE))
177 type = gobble(filep, file, file_red);
178 dawes 1.1 if (type == ELSE)
179 (void)gobble(filep, file, file_red);
180 break;
181 case ELSE:
182 case ENDIF:
183 debug(0,("%s, line %d: #%s\n",
184 file->i_file, filep->f_line,
185 directives[type]));
186 return(type);
187 case DEFINE:
188 case UNDEF:
189 case INCLUDE:
190 case INCLUDEDOT:
191 case PRAGMA:
192 case ERROR:
193 case IDENT:
194 case SCCS:
195 case EJECT:
196 break;
197 case ELIF:
198 case ELIFFALSE:
199 dawes 1.1 case ELIFGUESSFALSE:
200 return(type);
201 case -1:
202 warning("%s, line %d: unknown directive == \"%s\"\n",
203 file_red->i_file, filep->f_line, line);
204 break;
205 }
206 }
207 return(-1);
208 }
209
210 /*
211 * Decide what type of # directive this line is.
212 */
213 int deftype (line, filep, file_red, file, parse_it)
214 register char *line;
215 register struct filepointer *filep;
216 register struct inclist *file_red, *file;
217 int parse_it;
218 {
219 register char *p;
220 dawes 1.1 char *directive, savechar;
221 register int ret;
222
223 /*
224 * Parse the directive...
225 */
226 directive=line+1;
227 while (*directive == ' ' || *directive == '\t')
228 directive++;
229
230 p = directive;
231 while (*p >= 'a' && *p <= 'z')
232 p++;
233 savechar = *p;
234 *p = '\0';
235 ret = match(directive, directives);
236 *p = savechar;
237
238 /* If we don't recognize this compiler directive or we happen to just
239 * be gobbling up text while waiting for an #endif or #elif or #else
240 * in the case of an #elif we must check the zero_value and return an
241 dawes 1.1 * ELIF or an ELIFFALSE.
242 */
243
244 if (ret == ELIF && !parse_it)
245 {
246 while (*p == ' ' || *p == '\t')
247 p++;
248 /*
249 * parse an expression.
250 */
251 debug(0,("%s, line %d: #elif %s ",
252 file->i_file, filep->f_line, p));
253 ret = zero_value(p, filep, file_red);
254 if (ret != IF)
255 {
256 debug(0,("false...\n"));
257 if (ret == IFFALSE)
258 return(ELIFFALSE);
259 else
260 return(ELIFGUESSFALSE);
261 }
262 dawes 1.1 else
263 {
264 debug(0,("true...\n"));
265 return(ELIF);
266 }
267 }
268
269 if (ret < 0 || ! parse_it)
270 return(ret);
271
272 /*
273 * now decide how to parse the directive, and do it.
274 */
275 while (*p == ' ' || *p == '\t')
276 p++;
277 switch (ret) {
278 case IF:
279 /*
280 * parse an expression.
281 */
282 ret = zero_value(p, filep, file_red);
283 dawes 1.1 debug(0,("%s, line %d: %s #if %s\n",
284 file->i_file, filep->f_line, ret?"false":"true", p));
285 break;
286 case IFDEF:
287 case IFNDEF:
288 debug(0,("%s, line %d: #%s %s\n",
289 file->i_file, filep->f_line, directives[ret], p));
290 case UNDEF:
291 /*
292 * separate the name of a single symbol.
293 */
294 while (isalnum(*p) || *p == '_')
295 *line++ = *p++;
296 *line = '\0';
297 break;
298 case INCLUDE:
299 debug(2,("%s, line %d: #include %s\n",
300 file->i_file, filep->f_line, p));
301
302 /* Support ANSI macro substitution */
303 {
|
304 dawes 1.1.1.2 struct symtab **sym = isdefined(p, file_red, NULL);
|
305 dawes 1.1 while (sym) {
|
306 dawes 1.1.1.2 p = (*sym)->s_value;
|
307 dawes 1.1 debug(3,("%s : #includes SYMBOL %s = %s\n",
308 file->i_incstring,
|
309 dawes 1.1.1.2 (*sym) -> s_name,
310 (*sym) -> s_value));
|
311 dawes 1.1 /* mark file as having included a 'soft include' */
|
312 dawes 1.1.1.2 file->i_flags |= INCLUDED_SYM;
|
313 dawes 1.1 sym = isdefined(p, file_red, NULL);
314 }
315 }
316
317 /*
318 * Separate the name of the include file.
319 */
320 while (*p && *p != '"' && *p != '<')
321 p++;
322 if (! *p)
323 return(-2);
324 if (*p++ == '"') {
325 ret = INCLUDEDOT;
326 while (*p && *p != '"')
327 *line++ = *p++;
328 } else
329 while (*p && *p != '>')
330 *line++ = *p++;
331 *line = '\0';
332 break;
333 case DEFINE:
334 dawes 1.1 /*
335 * copy the definition back to the beginning of the line.
336 */
337 strcpy (line, p);
338 break;
339 case ELSE:
340 case ENDIF:
341 case ELIF:
342 case PRAGMA:
343 case ERROR:
344 case IDENT:
345 case SCCS:
346 case EJECT:
347 debug(0,("%s, line %d: #%s\n",
348 file->i_file, filep->f_line, directives[ret]));
349 /*
350 * nothing to do.
351 */
352 break;
353 }
354 return(ret);
355 dawes 1.1 }
356
|
357 dawes 1.1.1.2 struct symtab **isdefined(symbol, file, srcfile)
|
358 dawes 1.1 register char *symbol;
359 struct inclist *file;
360 struct inclist **srcfile;
361 {
|
362 dawes 1.1.1.2 register struct symtab **val;
|
363 dawes 1.1
364 if (val = slookup(symbol, &maininclist)) {
365 debug(1,("%s defined on command line\n", symbol));
366 if (srcfile != NULL) *srcfile = &maininclist;
367 return(val);
368 }
369 if (val = fdefined(symbol, file, srcfile))
370 return(val);
371 debug(1,("%s not defined in %s\n", symbol, file->i_file));
372 return(NULL);
373 }
374
|
375 dawes 1.1.1.2 struct symtab **fdefined(symbol, file, srcfile)
|
376 dawes 1.1 register char *symbol;
377 struct inclist *file;
378 struct inclist **srcfile;
379 {
380 register struct inclist **ip;
|
381 dawes 1.1.1.2 register struct symtab **val;
|
382 dawes 1.1 register int i;
383 static int recurse_lvl = 0;
384
|
385 dawes 1.1.1.2 if (file->i_flags & DEFCHECKED)
|
386 dawes 1.1 return(NULL);
|
387 dawes 1.1.1.2 file->i_flags |= DEFCHECKED;
|
388 dawes 1.1 if (val = slookup(symbol, file))
|
389 dawes 1.1.1.2 debug(1,("%s defined in %s as %s\n",
390 symbol, file->i_file, (*val)->s_value));
|
391 dawes 1.1 if (val == NULL && file->i_list)
392 {
393 for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
|
394 dawes 1.1.1.2 if (file->i_merged[i]==FALSE) {
395 val = fdefined(symbol, *ip, srcfile);
396 if ((*ip)->i_flags & FINISHED) {
397 merge2defines(file,*ip);
398 file->i_merged[i]=TRUE;
399 }
400 if (val!=NULL) break;
|
401 dawes 1.1 }
402 }
403 else if (val != NULL && srcfile != NULL) *srcfile = file;
404 recurse_lvl--;
|
405 dawes 1.1.1.2 file->i_flags &= ~DEFCHECKED;
|
406 dawes 1.1
407 return(val);
408 }
409
410 /*
411 * Return type based on if the #if expression evaluates to 0
412 */
413 zero_value(exp, filep, file_red)
414 register char *exp;
415 register struct filepointer *filep;
416 register struct inclist *file_red;
417 {
418 if (cppsetup(exp, filep, file_red))
419 return(IFFALSE);
420 else
421 return(IF);
422 }
423
424 define(def, file)
425 char *def;
426 struct inclist *file;
427 dawes 1.1 {
428 char *val;
429
430 /* Separate symbol name and its value */
431 val = def;
432 while (isalnum(*val) || *val == '_')
433 val++;
434 if (*val)
435 *val++ = '\0';
436 while (*val == ' ' || *val == '\t')
437 val++;
438
439 if (!*val)
440 val = "1";
441 define2(def, val, file);
442 }
443
444 define2(name, val, file)
445 char *name, *val;
446 struct inclist *file;
447 {
448 dawes 1.1 int first, last, below;
|
449 dawes 1.1.1.2 register struct symtab **sp = NULL, **dest;
450 struct symtab *stab;
|
451 dawes 1.1
452 /* Make space if it's needed */
453 if (file->i_defs == NULL)
454 {
|
455 dawes 1.1.1.2 file->i_defs = (struct symtab **)
456 malloc(sizeof (struct symtab*) * SYMTABINC);
|
457 dawes 1.1 file->i_ndefs = 0;
458 }
|
459 dawes 1.1.1.2 else if (!(file->i_ndefs % SYMTABINC))
460 file->i_defs = (struct symtab **)
|
461 dawes 1.1 realloc(file->i_defs,
|
462 dawes 1.1.1.2 sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
|
463 dawes 1.1
464 if (file->i_defs == NULL)
465 fatalerr("malloc()/realloc() failure in insert_defn()\n");
466
467 below = first = 0;
468 last = file->i_ndefs - 1;
469 while (last >= first)
470 {
471 /* Fast inline binary search */
472 register char *s1;
473 register char *s2;
474 register int middle = (first + last) / 2;
475
476 /* Fast inline strchr() */
477 s1 = name;
|
478 dawes 1.1.1.2 s2 = file->i_defs[middle]->s_name;
|
479 dawes 1.1 while (*s1++ == *s2++)
480 if (s2[-1] == '\0') break;
481
482 /* If exact match, set sp and break */
483 if (*--s1 == *--s2)
484 {
485 sp = file->i_defs + middle;
486 break;
487 }
488
489 /* If name > i_defs[middle] ... */
490 if (*s1 > *s2)
491 {
492 below = first;
493 first = middle + 1;
494 }
495 /* else ... */
496 else
497 {
498 below = last = middle - 1;
499 }
500 dawes 1.1 }
501
502 /* Search is done. If we found an exact match to the symbol name,
503 just replace its s_value */
504 if (sp != NULL)
505 {
|
506 dawes 1.1.1.2 free((*sp)->s_value);
507 (*sp)->s_value = copy(val);
|
508 dawes 1.1 return;
509 }
510
511 sp = file->i_defs + file->i_ndefs++;
512 dest = file->i_defs + below + 1;
513 while (sp > dest)
514 {
515 *sp = sp[-1];
516 sp--;
517 }
|
518 dawes 1.1.1.2 stab = (struct symtab *) malloc(sizeof (struct symtab));
519 if (stab == NULL)
520 fatalerr("malloc()/realloc() failure in insert_defn()\n");
521
522 stab->s_name = copy(name);
523 stab->s_value = copy(val);
524 *sp = stab;
|
525 dawes 1.1 }
526
|
527 dawes 1.1.1.2 struct symtab **slookup(symbol, file)
|
528 dawes 1.1 register char *symbol;
529 register struct inclist *file;
530 {
531 register int first = 0;
532 register int last = file->i_ndefs - 1;
533
534 if (file) while (last >= first)
535 {
536 /* Fast inline binary search */
537 register char *s1;
538 register char *s2;
539 register int middle = (first + last) / 2;
540
541 /* Fast inline strchr() */
542 s1 = symbol;
|
543 dawes 1.1.1.2 s2 = file->i_defs[middle]->s_name;
|
544 dawes 1.1 while (*s1++ == *s2++)
545 if (s2[-1] == '\0') break;
546
547 /* If exact match, we're done */
548 if (*--s1 == *--s2)
549 {
550 return file->i_defs + middle;
551 }
552
553 /* If symbol > i_defs[middle] ... */
554 if (*s1 > *s2)
555 {
556 first = middle + 1;
557 }
558 /* else ... */
559 else
560 {
561 last = middle - 1;
562 }
563 }
564 return(NULL);
565 dawes 1.1 }
566
|
567 dawes 1.1.1.2 int merge2defines(file1, file2)
568 struct inclist *file1;
569 struct inclist *file2;
570 {
571 if ((file1!=NULL) && (file2!=NULL))
572 {
573 int first1 = 0;
574 int last1 = file1->i_ndefs - 1;
575
576 int first2 = 0;
577 int last2 = file2->i_ndefs - 1;
578
579 int first=0;
580 struct symtab** i_defs = NULL;
581 int deflen=file1->i_ndefs+file2->i_ndefs;
582
583 if (deflen>0)
584 {
585 /* make sure deflen % SYMTABINC == 0 is still true */
586 deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
587 i_defs=(struct symtab**)
588 dawes 1.1.1.2 malloc(deflen*sizeof(struct symtab*));
589 if (i_defs==NULL) return 0;
590 }
591
592 while ((last1 >= first1) && (last2 >= first2))
593 {
594 char *s1=file1->i_defs[first1]->s_name;
595 char *s2=file2->i_defs[first2]->s_name;
596
597 if (strcmp(s1,s2) < 0)
598 i_defs[first++]=file1->i_defs[first1++];
599 else if (strcmp(s1,s2) > 0)
600 i_defs[first++]=file2->i_defs[first2++];
601 else /* equal */
602 {
603 i_defs[first++]=file2->i_defs[first2++];
604 first1++;
605 }
606 }
607 while (last1 >= first1)
608 {
609 dawes 1.1.1.2 i_defs[first++]=file1->i_defs[first1++];
610 }
611 while (last2 >= first2)
612 {
613 i_defs[first++]=file2->i_defs[first2++];
614 }
615
616 if (file1->i_defs) free(file1->i_defs);
617 file1->i_defs=i_defs;
618 file1->i_ndefs=first;
619
620 return 1;
621 }
622 return 0;
623 }
624
|
625 dawes 1.1 undefine(symbol, file)
626 char *symbol;
627 register struct inclist *file;
628 {
|
629 dawes 1.1.1.2 register struct symtab **ptr;
|
630 dawes 1.1 struct inclist *srcfile;
631 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
632 {
633 srcfile->i_ndefs--;
634 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
635 *ptr = ptr[1];
636 }
637 }
|
638 dawes 1.1.1.2
|