parse.c revision 0eb10989
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; 433 434 if (file == NULL) 435 return NULL; 436 437 last = file->i_ndefs - 1; 438 439 while (last >= first) 440 { 441 /* Fast inline binary search */ 442 register char *s1; 443 register char *s2; 444 register int middle = (first + last) / 2; 445 446 /* Fast inline strchr() */ 447 s1 = symbol; 448 s2 = file->i_defs[middle]->s_name; 449 while (*s1++ == *s2++) 450 if (s2[-1] == '\0') break; 451 452 /* If exact match, we're done */ 453 if (*--s1 == *--s2) 454 { 455 return file->i_defs + middle; 456 } 457 458 /* If symbol > i_defs[middle] ... */ 459 if (*s1 > *s2) 460 { 461 first = middle + 1; 462 } 463 /* else ... */ 464 else 465 { 466 last = middle - 1; 467 } 468 } 469 return(NULL); 470} 471 472static int 473merge2defines(struct inclist *file1, struct inclist *file2) 474{ 475 int i; 476 477 if ((file1==NULL) || (file2==NULL) || 478 !(file2->i_flags & FINISHED)) 479 return 0; 480 481 for (i=0; i < file2->i_listlen; i++) 482 if (file2->i_merged[i]==FALSE) 483 return 0; 484 485 { 486 int first1 = 0; 487 int last1 = file1->i_ndefs - 1; 488 489 int first2 = 0; 490 int last2 = file2->i_ndefs - 1; 491 492 int first=0; 493 struct symtab** i_defs = NULL; 494 int deflen=file1->i_ndefs+file2->i_ndefs; 495 496 debug(2,("merging %s into %s\n", 497 file2->i_file, file1->i_file)); 498 499 if (deflen>0) 500 { 501 /* make sure deflen % SYMTABINC == 0 is still true */ 502 deflen += (SYMTABINC - deflen % SYMTABINC) % SYMTABINC; 503 i_defs=(struct symtab**) 504 malloc(deflen*sizeof(struct symtab*)); 505 if (i_defs==NULL) return 0; 506 } 507 508 while ((last1 >= first1) && (last2 >= first2)) 509 { 510 char *s1=file1->i_defs[first1]->s_name; 511 char *s2=file2->i_defs[first2]->s_name; 512 513 if (strcmp(s1,s2) < 0) 514 i_defs[first++]=file1->i_defs[first1++]; 515 else if (strcmp(s1,s2) > 0) 516 i_defs[first++]=file2->i_defs[first2++]; 517 else /* equal */ 518 { 519 i_defs[first++]=file2->i_defs[first2++]; 520 first1++; 521 } 522 } 523 while (last1 >= first1) 524 { 525 i_defs[first++]=file1->i_defs[first1++]; 526 } 527 while (last2 >= first2) 528 { 529 i_defs[first++]=file2->i_defs[first2++]; 530 } 531 532 if (file1->i_defs) free(file1->i_defs); 533 file1->i_defs=i_defs; 534 file1->i_ndefs=first; 535 536 return 1; 537 } 538} 539 540void 541undefine(char *symbol, struct inclist *file) 542{ 543 register struct symtab **ptr; 544 struct inclist *srcfile; 545 while ((ptr = isdefined(symbol, file, &srcfile)) != NULL) 546 { 547 srcfile->i_ndefs--; 548 for (; ptr < srcfile->i_defs + srcfile->i_ndefs; ptr++) 549 *ptr = ptr[1]; 550 } 551} 552 553int 554find_includes(struct filepointer *filep, struct inclist *file, 555 struct inclist *file_red, int recursion, boolean failOK) 556{ 557 struct inclist *inclistp; 558 char **includedirsp; 559 register char *line; 560 register int type; 561 boolean recfailOK; 562 563 while ((line = getnextline(filep))) { 564 switch(type = deftype(line, filep, file_red, file, TRUE)) { 565 case IF: 566 doif: 567 type = find_includes(filep, file, 568 file_red, recursion+1, failOK); 569 while ((type == ELIF) || (type == ELIFFALSE) || 570 (type == ELIFGUESSFALSE)) 571 type = gobble(filep, file, file_red); 572 if (type == ELSE) 573 gobble(filep, file, file_red); 574 break; 575 case IFFALSE: 576 case IFGUESSFALSE: 577 doiffalse: 578 if (type == IFGUESSFALSE || type == ELIFGUESSFALSE) 579 recfailOK = TRUE; 580 else 581 recfailOK = failOK; 582 type = gobble(filep, file, file_red); 583 if (type == ELSE) 584 find_includes(filep, file, 585 file_red, recursion+1, recfailOK); 586 else 587 if (type == ELIF) 588 goto doif; 589 else 590 if ((type == ELIFFALSE) || (type == ELIFGUESSFALSE)) 591 goto doiffalse; 592 break; 593 case IFDEF: 594 case IFNDEF: 595 if ((type == IFDEF && isdefined(line, file_red, NULL)) 596 || (type == IFNDEF && !isdefined(line, file_red, NULL))) { 597 debug(1,(type == IFNDEF ? 598 "line %d: %s !def'd in %s via %s%s\n" : "", 599 filep->f_line, line, 600 file->i_file, file_red->i_file, ": doit")); 601 type = find_includes(filep, file, 602 file_red, recursion+1, failOK); 603 while (type == ELIF || type == ELIFFALSE || type == ELIFGUESSFALSE) 604 type = gobble(filep, file, file_red); 605 if (type == ELSE) 606 gobble(filep, file, file_red); 607 } 608 else { 609 debug(1,(type == IFDEF ? 610 "line %d: %s !def'd in %s via %s%s\n" : "", 611 filep->f_line, line, 612 file->i_file, file_red->i_file, ": gobble")); 613 type = gobble(filep, file, file_red); 614 if (type == ELSE) 615 find_includes(filep, file, 616 file_red, recursion+1, failOK); 617 else if (type == ELIF) 618 goto doif; 619 else if (type == ELIFFALSE || type == ELIFGUESSFALSE) 620 goto doiffalse; 621 } 622 break; 623 case ELSE: 624 case ELIFFALSE: 625 case ELIFGUESSFALSE: 626 case ELIF: 627 if (!recursion) 628 gobble(filep, file, file_red); 629 case ENDIF: 630 if (recursion) 631 return(type); 632 case DEFINE: 633 define(line, file); 634 break; 635 case UNDEF: 636 if (!*line) { 637 warning("%s", file_red->i_file); 638 if (file_red != file) 639 warning1(" (reading %s)", file->i_file); 640 warning1(", line %d: incomplete undef == \"%s\"\n", 641 filep->f_line, line); 642 break; 643 } 644 undefine(line, file_red); 645 break; 646 case INCLUDE: 647 case INCLUDEDOT: 648 case INCLUDENEXT: 649 case INCLUDENEXTDOT: 650 inclistp = inclistnext; 651 includedirsp = includedirsnext; 652 debug(2,("%s, reading %s, includes %s\n", 653 file_red->i_file, file->i_file, line)); 654 add_include(filep, file, file_red, line, type, failOK); 655 inclistnext = inclistp; 656 includedirsnext = includedirsp; 657 break; 658 case ERROR: 659 case WARNING: 660 warning("%s", file_red->i_file); 661 if (file_red != file) 662 warning1(" (reading %s)", file->i_file); 663 warning1(", line %d: %s\n", 664 filep->f_line, line); 665 break; 666 667 case PRAGMA: 668 case IDENT: 669 case SCCS: 670 case EJECT: 671 break; 672 case -1: 673 warning("%s", file_red->i_file); 674 if (file_red != file) 675 warning1(" (reading %s)", file->i_file); 676 warning1(", line %d: unknown directive == \"%s\"\n", 677 filep->f_line, line); 678 break; 679 case -2: 680 warning("%s", file_red->i_file); 681 if (file_red != file) 682 warning1(" (reading %s)", file->i_file); 683 warning1(", line %d: incomplete include == \"%s\"\n", 684 filep->f_line, line); 685 break; 686 } 687 } 688 file->i_flags |= FINISHED; 689 debug(2,("finished with %s\n", file->i_file)); 690 return(-1); 691} 692