1 /* $TOG: parse.c /main/35 1998/03/25 08:17:55 kaleb $ */
4 Copyright (c) 1993, 1994, 1998 The Open Group
8 The above copyright notice and this permission notice shall be included in
9 all copies or substantial portions of the Software.
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
15 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
16 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 Except as contained in this notice, the name of The Open Group shall not be
19 used in advertising or otherwise to promote the sale, use or other dealings
20 in this Software without prior written authorization from The Open Group.
26 extern char *directives[];
27 extern struct inclist maininclist;
30 gobble(filep, file, file_red)
31 register struct filepointer *filep;
32 struct inclist *file, *file_red;
37 while (line = getline(filep)) {
38 switch(type = deftype(line, filep, file_red, file, FALSE)) {
44 type = gobble(filep, file, file_red);
45 while ((type == ELIF) || (type == ELIFFALSE) ||
46 (type == ELIFGUESSFALSE))
47 type = gobble(filep, file, file_red);
49 (void)gobble(filep, file, file_red);
53 debug(0,("%s, line %d: #%s\n",
54 file->i_file, filep->f_line,
73 warning("%s, line %d: unknown directive == \"%s\"\n",
74 file_red->i_file, filep->f_line, line);
82 * Decide what type of # directive this line is.
84 int deftype (line, filep, file_red, file, parse_it)
86 register struct filepointer *filep;
87 register struct inclist *file_red, *file;
91 char *directive, savechar;
95 * Parse the directive...
98 while (*directive == ' ' || *directive == '\t')
102 while (*p >= 'a' && *p <= 'z')
106 ret = match(directive, directives);
109 /* If we don't recognize this compiler directive or we happen to just
110 * be gobbling up text while waiting for an #endif or #elif or #else
111 * in the case of an #elif we must check the zero_value and return an
112 * ELIF or an ELIFFALSE.
115 if (ret == ELIF && !parse_it)
117 while (*p == ' ' || *p == '\t')
120 * parse an expression.
122 debug(0,("%s, line %d: #elif %s ",
123 file->i_file, filep->f_line, p));
124 ret = zero_value(p, filep, file_red);
127 debug(0,("false...\n"));
131 return(ELIFGUESSFALSE);
135 debug(0,("true...\n"));
140 if (ret < 0 || ! parse_it)
144 * now decide how to parse the directive, and do it.
146 while (*p == ' ' || *p == '\t')
151 * parse an expression.
153 ret = zero_value(p, filep, file_red);
154 debug(0,("%s, line %d: %s #if %s\n",
155 file->i_file, filep->f_line, ret?"false":"true", p));
159 debug(0,("%s, line %d: #%s %s\n",
160 file->i_file, filep->f_line, directives[ret], p));
163 * separate the name of a single symbol.
165 while (isalnum(*p) || *p == '_')
170 debug(2,("%s, line %d: #include %s\n",
171 file->i_file, filep->f_line, p));
173 /* Support ANSI macro substitution */
175 struct symtab **sym = isdefined(p, file_red, NULL);
178 debug(3,("%s : #includes SYMBOL %s = %s\n",
182 /* mark file as having included a 'soft include' */
183 file->i_flags |= INCLUDED_SYM;
184 sym = isdefined(p, file_red, NULL);
189 * Separate the name of the include file.
191 while (*p && *p != '"' && *p != '<')
197 while (*p && *p != '"')
200 while (*p && *p != '>')
206 * copy the definition back to the beginning of the line.
218 debug(0,("%s, line %d: #%s\n",
219 file->i_file, filep->f_line, directives[ret]));
228 struct symtab **fdefined(symbol, file, srcfile)
229 register char *symbol;
230 struct inclist *file;
231 struct inclist **srcfile;
233 register struct inclist **ip;
234 register struct symtab **val;
236 static int recurse_lvl = 0;
238 if (file->i_flags & DEFCHECKED)
240 file->i_flags |= DEFCHECKED;
241 if (val = slookup(symbol, file))
242 debug(1,("%s defined in %s as %s\n",
243 symbol, file->i_file, (*val)->s_value));
244 if (val == NULL && file->i_list)
246 for (ip = file->i_list, i=0; i < file->i_listlen; i++, ip++)
247 if (file->i_merged[i]==FALSE) {
248 val = fdefined(symbol, *ip, srcfile);
249 if ((*ip)->i_flags & FINISHED) {
250 merge2defines(file,*ip);
251 file->i_merged[i]=TRUE;
253 if (val!=NULL) break;
256 else if (val != NULL && srcfile != NULL) *srcfile = file;
258 file->i_flags &= ~DEFCHECKED;
263 struct symtab **isdefined(symbol, file, srcfile)
264 register char *symbol;
265 struct inclist *file;
266 struct inclist **srcfile;
268 register struct symtab **val;
270 if (val = slookup(symbol, &maininclist)) {
271 debug(1,("%s defined on command line\n", symbol));
272 if (srcfile != NULL) *srcfile = &maininclist;
275 if (val = fdefined(symbol, file, srcfile))
277 debug(1,("%s not defined in %s\n", symbol, file->i_file));
282 * Return type based on if the #if expression evaluates to 0
285 zero_value(exp, filep, file_red)
287 register struct filepointer *filep;
288 register struct inclist *file_red;
290 if (cppsetup(exp, filep, file_red))
297 define2(name, val, file)
299 struct inclist *file;
301 int first, last, below;
302 register struct symtab **sp = NULL, **dest;
305 /* Make space if it's needed */
306 if (file->i_defs == NULL)
308 file->i_defs = (struct symtab **)
309 malloc(sizeof (struct symtab*) * SYMTABINC);
312 else if (!(file->i_ndefs % SYMTABINC))
313 file->i_defs = (struct symtab **)
314 realloc(file->i_defs,
315 sizeof(struct symtab*)*(file->i_ndefs+SYMTABINC));
317 if (file->i_defs == NULL)
318 fatalerr("malloc()/realloc() failure in insert_defn()\n");
321 last = file->i_ndefs - 1;
322 while (last >= first)
324 /* Fast inline binary search */
327 register int middle = (first + last) / 2;
329 /* Fast inline strchr() */
331 s2 = file->i_defs[middle]->s_name;
332 while (*s1++ == *s2++)
333 if (s2[-1] == '\0') break;
335 /* If exact match, set sp and break */
338 sp = file->i_defs + middle;
342 /* If name > i_defs[middle] ... */
351 below = last = middle - 1;
355 /* Search is done. If we found an exact match to the symbol name,
356 just replace its s_value */
359 free((*sp)->s_value);
360 (*sp)->s_value = copy(val);
364 sp = file->i_defs + file->i_ndefs++;
365 dest = file->i_defs + below + 1;
371 stab = (struct symtab *) malloc(sizeof (struct symtab));
373 fatalerr("malloc()/realloc() failure in insert_defn()\n");
375 stab->s_name = copy(name);
376 stab->s_value = copy(val);
383 struct inclist *file;
387 /* Separate symbol name and its value */
389 while (isalnum(*val) || *val == '_')
393 while (*val == ' ' || *val == '\t')
398 define2(def, val, file);
401 struct symtab **slookup(symbol, file)
402 register char *symbol;
403 register struct inclist *file;
405 register int first = 0;
406 register int last = file->i_ndefs - 1;
408 if (file) while (last >= first)
410 /* Fast inline binary search */
413 register int middle = (first + last) / 2;
415 /* Fast inline strchr() */
417 s2 = file->i_defs[middle]->s_name;
418 while (*s1++ == *s2++)
419 if (s2[-1] == '\0') break;
421 /* If exact match, we're done */
424 return file->i_defs + middle;
427 /* If symbol > i_defs[middle] ... */
441 int merge2defines(file1, file2)
442 struct inclist *file1;
443 struct inclist *file2;
445 if ((file1!=NULL) && (file2!=NULL))
448 int last1 = file1->i_ndefs - 1;
451 int last2 = file2->i_ndefs - 1;
454 struct symtab** i_defs = NULL;
455 int deflen=file1->i_ndefs+file2->i_ndefs;
459 /* make sure deflen % SYMTABINC == 0 is still true */
460 deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC;
461 i_defs=(struct symtab**)
462 malloc(deflen*sizeof(struct symtab*));
463 if (i_defs==NULL) return 0;
466 while ((last1 >= first1) && (last2 >= first2))
468 char *s1=file1->i_defs[first1]->s_name;
469 char *s2=file2->i_defs[first2]->s_name;
471 if (strcmp(s1,s2) < 0)
472 i_defs[first++]=file1->i_defs[first1++];
473 else if (strcmp(s1,s2) > 0)
474 i_defs[first++]=file2->i_defs[first2++];
477 i_defs[first++]=file2->i_defs[first2++];
481 while (last1 >= first1)
483 i_defs[first++]=file1->i_defs[first1++];
485 while (last2 >= first2)
487 i_defs[first++]=file2->i_defs[first2++];
490 if (file1->i_defs) free(file1->i_defs);
491 file1->i_defs=i_defs;
492 file1->i_ndefs=first;
500 undefine(symbol, file)
502 register struct inclist *file;
504 register struct symtab **ptr;
505 struct inclist *srcfile;
506 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL)
509 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++)
515 find_includes(filep, file, file_red, recursion, failOK)
516 struct filepointer *filep;
517 struct inclist *file, *file_red;
525 while (line = getline(filep)) {
526 switch(type = deftype(line, filep, file_red, file, TRUE)) {
529 type = find_includes(filep, file,
530 file_red, recursion+1, failOK);
531 while ((type == ELIF) || (type == ELIFFALSE) ||
532 (type == ELIFGUESSFALSE))
533 type = gobble(filep, file, file_red);
535 gobble(filep, file, file_red);
540 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE)
544 type = gobble(filep, file, file_red);
546 find_includes(filep, file,
547 file_red, recursion+1, recfailOK);
552 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE))
557 if ((type == IFDEF && isdefined(line, file_red, NULL))
558 || (type == IFNDEF && !isdefined(line, file_red, NULL))) {
559 debug(1,(type == IFNDEF ?
560 "line %d: %s !def'd in %s via %s%s\n" : "",
562 file->i_file, file_red->i_file, ": doit"));
563 type = find_includes(filep, file,
564 file_red, recursion+1, failOK);
565 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE)
566 type = gobble(filep, file, file_red);
568 gobble(filep, file, file_red);
571 debug(1,(type == IFDEF ?
572 "line %d: %s !def'd in %s via %s%s\n" : "",
574 file->i_file, file_red->i_file, ": gobble"));
575 type = gobble(filep, file, file_red);
577 find_includes(filep, file,
578 file_red, recursion+1, failOK);
579 else if (type == ELIF)
581 else if (type == ELIFFALSE || type == ELIFGUESSFALSE)
590 gobble(filep, file, file_red);
599 warning("%s, line %d: incomplete undef == \"%s\"\n",
600 file_red->i_file, filep->f_line, line);
603 undefine(line, file_red);
606 add_include(filep, file, file_red, line, FALSE, failOK);
609 add_include(filep, file, file_red, line, TRUE, failOK);
612 warning("%s: %d: %s\n", file_red->i_file,
613 filep->f_line, line);
622 warning("%s", file_red->i_file);
623 if (file_red != file)
624 warning1(" (reading %s)", file->i_file);
625 warning1(", line %d: unknown directive == \"%s\"\n",
626 filep->f_line, line);
629 warning("%s", file_red->i_file);
630 if (file_red != file)
631 warning1(" (reading %s)", file->i_file);
632 warning1(", line %d: incomplete include == \"%s\"\n",
633 filep->f_line, line);
637 file->i_flags |= FINISHED;