1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1986-2008 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * Glenn Fowler <gsf@research.att.com> * 18 * * 19 ***********************************************************************/ 20 #pragma prototyped 21 /* 22 * Glenn Fowler 23 * AT&T Research 24 * 25 * preprocessor library control interface 26 */ 27 28 #include "pplib.h" 29 #include "pptab.h" 30 31 #include <ls.h> 32 33 #define REFONE (pp.truncate?(Hash_table_t*)0:pp.symtab) 34 #define REFALL (pp.truncate?pp.dirtab:pp.symtab) 35 36 #define ppiskey(t,v,p) (p=t,v>=p->value&&value<=(p+elementsof(t)-2)->value) 37 38 /* 39 * set option value 40 * initialization files have lowest precedence 41 */ 42 43 static void 44 set(register long* p, register long op, int val) 45 { 46 long* r; 47 48 r = p == &pp.state ? &pp.ro_state : p == &pp.mode ? &pp.ro_mode : &pp.ro_option; 49 if (!(pp.mode & INIT) || !(pp.in->type == IN_FILE) || !(*r & op)) 50 { 51 if (!pp.initialized && !(pp.mode & INIT)) 52 *r |= op; 53 if (val) 54 *p |= op; 55 else 56 *p &= ~op; 57 } 58 debug((-7, "set(%s)=%s", p == &pp.state ? "state" : p == &pp.mode ? "mode" : "option", p == &pp.state ? ppstatestr(*p) : p == &pp.mode ? ppmodestr(*p) : ppoptionstr(*p))); 59 } 60 61 /* 62 * initialize hash table with keywords from key 63 */ 64 65 static void 66 inithash(register Hash_table_t* tab, register struct ppkeyword* key) 67 { 68 register char* s; 69 70 for (; s = key->name; key++) 71 { 72 if (!ppisid(*s)) 73 s++; 74 hashput(tab, s, key->value); 75 } 76 } 77 78 /* 79 * return ppkeyword table name given value 80 */ 81 82 char* 83 ppkeyname(register int value, int dir) 84 { 85 register char* s; 86 register struct ppkeyword* p; 87 88 if (dir && ppiskey(directives, value, p) || !dir && (ppiskey(options, value, p) || ppiskey(predicates, value, p) || ppiskey(variables, value, p))) 89 { 90 s = (p + (value - p->value))->name; 91 return s + !ppisid(*s); 92 } 93 #if DEBUG 94 error(PANIC, "no keyword table name for value=%d", value); 95 #endif 96 return "UNKNOWN"; 97 } 98 99 /* 100 * add to the include maps 101 */ 102 103 void 104 ppmapinclude(char* file, register char* s) 105 { 106 register int c; 107 register struct ppdirs* dp; 108 int fd; 109 int flags; 110 int index; 111 int token; 112 char* t; 113 char* old_file; 114 long old_state; 115 struct ppfile* fp; 116 struct ppfile* mp; 117 118 old_file = error_info.file; 119 old_state = pp.state; 120 if (s) 121 PUSH_BUFFER("mapinclude", s, 1); 122 else if (file) 123 { 124 if (*file == '-') 125 { 126 if (!error_info.file) 127 { 128 error(1, "%s: input file name required for %s ignore", file, dirname(INCLUDE)); 129 return; 130 } 131 s = t = strcopy(pp.tmpbuf, error_info.file); 132 c = *++file; 133 for (;;) 134 { 135 if (s <= pp.tmpbuf || *s == '/') 136 { 137 s = t; 138 break; 139 } 140 else if (*s == c) 141 break; 142 s--; 143 } 144 strcpy(s, file); 145 file = pp.tmpbuf; 146 } 147 if ((fd = ppsearch(file, INC_LOCAL, SEARCH_INCLUDE)) < 0) 148 return; 149 PUSH_FILE(file, fd); 150 } 151 else 152 return; 153 #if CATSTRINGS 154 pp.state |= (COMPILE|FILEPOP|HEADER|JOINING|STRIP|NOSPACE|PASSEOF); 155 #else 156 pp.state |= (COMPILE|FILEPOP|HEADER|STRIP|NOSPACE|PASSEOF); 157 #endif 158 pp.level++; 159 flags = INC_MAPALL; 160 fp = mp = 0; 161 for (;;) 162 { 163 switch (token = pplex()) 164 { 165 case 0: 166 case T_STRING: 167 case T_HEADER: 168 if (fp) 169 { 170 fp->guard = INC_IGNORE; 171 for (dp = pp.firstdir->next; dp; dp = dp->next) 172 if (dp->name && (c = strlen(dp->name)) && !strncmp(dp->name, fp->name, c) && fp->name[c] == '/') 173 { 174 ppsetfile(fp->name + c + 1)->guard = INC_IGNORE; 175 break; 176 } 177 } 178 if (!token) 179 break; 180 pathcanon(pp.token, 0); 181 fp = ppsetfile(pp.token); 182 if (mp) 183 { 184 mp->flags |= flags; 185 if (streq(fp->name, ".")) 186 mp->flags |= INC_MAPNOLOCAL; 187 else 188 mp->bound[index] = fp; 189 190 fp = mp = 0; 191 } 192 else 193 index = token == T_HEADER ? INC_STANDARD : INC_LOCAL; 194 continue; 195 case '=': 196 if (!(mp = fp)) 197 error(3, "%s: \"name\" = \"binding\" expected"); 198 fp = 0; 199 continue; 200 case '\n': 201 continue; 202 case T_ID: 203 if (streq(pp.token, "all")) 204 { 205 flags = INC_MAPALL; 206 continue; 207 } 208 else if (streq(pp.token, "hosted")) 209 { 210 flags = INC_MAPHOSTED; 211 continue; 212 } 213 else if (streq(pp.token, "nohosted")) 214 { 215 flags = INC_MAPNOHOSTED; 216 continue; 217 } 218 /*FALLTHROUGH*/ 219 default: 220 error(3, "%s unexpected in %s map list", pptokstr(pp.token, 0), dirname(INCLUDE)); 221 break; 222 } 223 break; 224 } 225 pp.level--; 226 error_info.file = old_file; 227 pp.state = old_state; 228 } 229 230 /* 231 * return non-0 if file is identical to fd 232 */ 233 234 static int 235 identical(char* file, int fd) 236 { 237 struct stat a; 238 struct stat b; 239 240 return !stat(file, &a) && !fstat(fd, &b) && a.st_dev == b.st_dev && a.st_ino == b.st_ino; 241 } 242 243 /* 244 * compare up to pp.truncate chars 245 * 246 * NOTE: __STD* and symbols containing ' ' are not truncated 247 */ 248 249 static int 250 trunccomp(register char* a, register char* b) 251 { 252 return !strchr(b, ' ') && !strneq(b, "__STD", 5) ? strncmp(a, b, pp.truncate) : strcmp(a, b); 253 } 254 255 /* 256 * hash up to pp.truncate chars 257 * 258 * NOTE: __STD* and symbols containing ' ' are not truncated 259 */ 260 261 static unsigned int 262 trunchash(char* a) 263 { 264 int n; 265 266 return memhash(a, (n = strlen(a)) > pp.truncate && !strchr(a, ' ') && !strneq(a, "__STD", 5) ? pp.truncate : n); 267 } 268 269 #if DEBUG & TRACE_debug 270 /* 271 * append context to debug trace 272 */ 273 274 static int 275 context(Sfio_t* sp, int level, int flags) 276 { 277 static int state; 278 279 NoP(level); 280 NoP(flags); 281 if (error_info.trace <= -10 && pp.state != state) 282 { 283 state = pp.state; 284 sfprintf(sp, " %s", ppstatestr(pp.state)); 285 } 286 return 1; 287 } 288 #endif 289 290 /* 291 * reset include guard 292 */ 293 294 static int 295 unguard(const char* name, char* v, void* handle) 296 { 297 register struct ppfile* fp = (struct ppfile*)v; 298 299 fp->guard = 0; 300 return 0; 301 } 302 303 /* 304 * reset macro definition 305 */ 306 307 static void 308 undefine(void* p) 309 { 310 struct ppmacro* mac = ((struct ppsymbol*)p)->macro; 311 312 if (mac) 313 { 314 if (mac->formals) 315 free(mac->formals); 316 free(mac->value); 317 free(mac); 318 } 319 } 320 321 /* 322 * pp operations 323 * 324 * NOTE: PP_INIT must be done before the first pplex() call 325 * PP_DONE must be done after the last pplex() call 326 * PP_INIT-PP_DONE must be done for each new PP_INPUT 327 */ 328 329 void 330 ppop(int op, ...) 331 { 332 va_list ap; 333 register char* p; 334 register struct ppkeyword* kp; 335 register char* s; 336 int c; 337 long n; 338 char* t; 339 struct ppdirs* dp; 340 struct ppdirs* hp; 341 struct ppsymkey* key; 342 struct oplist* xp; 343 Sfio_t* sp; 344 struct stat st; 345 PPCOMMENT ppcomment; 346 PPLINESYNC pplinesync; 347 348 static int initialized; 349 350 va_start(ap, op); 351 switch (op) 352 { 353 case PP_ASSERT: 354 case PP_DEFINE: 355 case PP_DIRECTIVE: 356 case PP_OPTION: 357 case PP_READ: 358 case PP_UNDEF: 359 if (pp.initialized) 360 goto before; 361 if ((p = va_arg(ap, char*)) && *p) 362 { 363 if (pp.lastop) 364 pp.lastop = (pp.lastop->next = newof(0, struct oplist, 1, 0)); 365 else 366 pp.firstop = pp.lastop = newof(0, struct oplist, 1, 0); 367 pp.lastop->op = op; 368 pp.lastop->value = p; 369 } 370 break; 371 case PP_BUILTIN: 372 pp.builtin = va_arg(ap, PPBUILTIN); 373 break; 374 case PP_CDIR: 375 p = va_arg(ap, char*); 376 c = va_arg(ap, int); 377 pp.cdir.path = 0; 378 if (!p) 379 pp.c = c; 380 else if (streq(p, "-")) 381 { 382 pp.c = c; 383 for (dp = pp.firstdir; dp; dp = dp->next) 384 dp->c = c; 385 } 386 else if (!pp.c) 387 { 388 if (!*p || stat((pathcanon(p, 0), p), &st)) 389 pp.c = c; 390 else 391 { 392 for (dp = pp.firstdir; dp; dp = dp->next) 393 { 394 if (!pp.c && (dp->c || dp->name && SAMEID(&dp->id, &st))) 395 pp.c = 1; 396 dp->c = pp.c == 1; 397 } 398 if (!pp.c) 399 { 400 pp.cdir.path = p; 401 SAVEID(&pp.cdir.id, &st); 402 } 403 } 404 } 405 break; 406 case PP_CHOP: 407 if (p = va_arg(ap, char*)) 408 { 409 c = strlen(p); 410 xp = newof(0, struct oplist, 1, c + 1); 411 xp->value = ((char*)xp) + sizeof(struct oplist); 412 s = xp->value; 413 c = *p++; 414 while (*p && *p != c) 415 *s++ = *p++; 416 *s++ = '/'; 417 xp->op = s - xp->value; 418 *s++ = 0; 419 if (*p && *++p && *p != c) 420 { 421 while (*p && *p != c) 422 *s++ = *p++; 423 *s++ = '/'; 424 } 425 *s = 0; 426 xp->next = pp.chop; 427 pp.chop = xp; 428 } 429 break; 430 case PP_COMMENT: 431 if (pp.comment = va_arg(ap, PPCOMMENT)) 432 pp.flags |= PP_comment; 433 else 434 pp.flags &= ~PP_comment; 435 break; 436 case PP_COMPATIBILITY: 437 set(&pp.state, COMPATIBILITY, va_arg(ap, int)); 438 #if COMPATIBLE 439 if (pp.initialized) 440 ppfsm(FSM_COMPATIBILITY, NiL); 441 #else 442 if (pp.state & COMPATIBILITY) 443 error(3, "preprocessor not compiled with compatibility dialect enabled [COMPATIBLE]"); 444 #endif 445 if (pp.state & COMPATIBILITY) 446 pp.flags |= PP_compatibility; 447 else 448 pp.flags &= ~PP_compatibility; 449 break; 450 case PP_COMPILE: 451 if (pp.initialized) 452 goto before; 453 pp.state |= COMPILE; 454 if (!pp.symtab) 455 pp.symtab = hashalloc(NiL, HASH_name, "symbols", 0); 456 if (kp = va_arg(ap, struct ppkeyword*)) 457 for (; s = kp->name; kp++) 458 { 459 n = SYM_LEX; 460 switch (*s) 461 { 462 case '-': 463 s++; 464 break; 465 case '+': 466 s++; 467 if (!(pp.option & PLUSPLUS)) 468 break; 469 /*FALLTHROUGH*/ 470 default: 471 n |= SYM_KEYWORD; 472 break; 473 } 474 if (key = ppkeyset(pp.symtab, s)) 475 { 476 key->sym.flags = n; 477 key->lex = kp->value; 478 } 479 } 480 break; 481 case PP_DEBUG: 482 error_info.trace = va_arg(ap, int); 483 break; 484 case PP_DEFAULT: 485 if (p = va_arg(ap, char*)) 486 p = strdup(p); 487 if (pp.ppdefault) 488 free(pp.ppdefault); 489 pp.ppdefault = p; 490 break; 491 case PP_DONE: 492 #if CHECKPOINT 493 if (pp.mode & DUMP) 494 ppdump(); 495 #endif 496 if (pp.mode & FILEDEPS) 497 { 498 sfputc(pp.filedeps.sp, '\n'); 499 if (pp.filedeps.sp == sfstdout) 500 sfsync(pp.filedeps.sp); 501 else 502 sfclose(pp.filedeps.sp); 503 } 504 if (pp.state & STANDALONE) 505 { 506 if ((pp.state & (NOTEXT|HIDDEN)) == HIDDEN && pplastout() != '\n') 507 ppputchar('\n'); 508 ppflushout(); 509 } 510 error_info.file = 0; 511 break; 512 case PP_DUMP: 513 set(&pp.mode, DUMP, va_arg(ap, int)); 514 #if !CHECKPOINT 515 if (pp.mode & DUMP) 516 error(3, "preprocessor not compiled with checkpoint enabled [CHECKPOINT]"); 517 #endif 518 break; 519 case PP_FILEDEPS: 520 if (n = va_arg(ap, int)) 521 pp.filedeps.flags |= n; 522 else 523 pp.filedeps.flags = 0; 524 break; 525 case PP_FILENAME: 526 error_info.file = va_arg(ap, char*); 527 break; 528 case PP_HOSTDIR: 529 if (!(pp.mode & INIT)) 530 pp.ro_mode |= HOSTED; 531 else if (pp.ro_mode & HOSTED) 532 break; 533 pp.ro_mode |= INIT; 534 p = va_arg(ap, char*); 535 c = va_arg(ap, int); 536 pp.hostdir.path = 0; 537 if (!p) 538 pp.hosted = c; 539 else if (streq(p, "-")) 540 { 541 if (pp.initialized) 542 set(&pp.mode, HOSTED, c); 543 else 544 { 545 pp.hosted = c ? 1 : 2; 546 for (dp = pp.firstdir; dp; dp = dp->next) 547 if (pp.hosted == 1) 548 dp->type |= TYPE_HOSTED; 549 else 550 dp->type &= ~TYPE_HOSTED; 551 } 552 } 553 else if (!pp.hosted) 554 { 555 if (!*p || stat((pathcanon(p, 0), p), &st)) 556 pp.hosted = 1; 557 else 558 { 559 for (dp = pp.firstdir; dp; dp = dp->next) 560 { 561 if (!pp.hosted && ((dp->type & TYPE_HOSTED) || dp->name && SAMEID(&dp->id, &st))) 562 pp.hosted = 1; 563 if (pp.hosted == 1) 564 dp->type |= TYPE_HOSTED; 565 else 566 dp->type &= ~TYPE_HOSTED; 567 } 568 if (!pp.hosted) 569 { 570 pp.hostdir.path = p; 571 SAVEID(&pp.hostdir.id, &st); 572 } 573 } 574 } 575 break; 576 case PP_ID: 577 p = va_arg(ap, char*); 578 c = va_arg(ap, int); 579 if (p) 580 ppfsm(c ? FSM_IDADD : FSM_IDDEL, p); 581 break; 582 case PP_IGNORE: 583 if (p = va_arg(ap, char*)) 584 { 585 pathcanon(p, 0); 586 ppsetfile(p)->guard = INC_IGNORE; 587 message((-3, "%s: ignore", p)); 588 } 589 break; 590 case PP_IGNORELIST: 591 if (pp.initialized) 592 goto before; 593 pp.ignore = va_arg(ap, char*); 594 break; 595 case PP_INCLUDE: 596 if ((p = va_arg(ap, char*)) && *p) 597 { 598 pathcanon(p, 0); 599 if (stat(p, &st)) 600 break; 601 for (dp = pp.stddirs; dp = dp->next;) 602 if (dp->name && SAMEID(&dp->id, &st)) 603 break; 604 if (pp.cdir.path && SAMEID(&pp.cdir.id, &st)) 605 { 606 pp.cdir.path = 0; 607 pp.c = 1; 608 } 609 if (pp.hostdir.path && SAMEID(&pp.hostdir.id, &st)) 610 { 611 pp.hostdir.path = 0; 612 pp.hosted = 1; 613 } 614 if ((pp.mode & INIT) && !(pp.ro_mode & INIT)) 615 pp.hosted = 1; 616 c = dp && dp->c || pp.c == 1; 617 n = dp && (dp->type & TYPE_HOSTED) || pp.hosted == 1; 618 if (!dp || dp == pp.lastdir->next) 619 { 620 if (dp) 621 { 622 c = dp->c; 623 n = dp->type & TYPE_HOSTED; 624 } 625 dp = newof(0, struct ppdirs, 1, 0); 626 dp->name = p; 627 SAVEID(&dp->id, &st); 628 dp->type |= TYPE_INCLUDE; 629 dp->index = INC_LOCAL + pp.ignoresrc != 0; 630 dp->next = pp.lastdir->next; 631 pp.lastdir = pp.lastdir->next = dp; 632 } 633 dp->c = c; 634 if (n) 635 dp->type |= TYPE_HOSTED; 636 else 637 dp->type &= ~TYPE_HOSTED; 638 } 639 break; 640 case PP_INCREF: 641 pp.incref = va_arg(ap, PPINCREF); 642 break; 643 case PP_RESET: 644 pp.reset.on = 1; 645 break; 646 case PP_INIT: 647 if (pp.initialized) 648 { 649 error_info.errors = 0; 650 error_info.warnings = 0; 651 } 652 else 653 { 654 /* 655 * context initialization 656 */ 657 658 if (!initialized) 659 { 660 /* 661 * out of malloc is fatal 662 */ 663 664 memfatal(); 665 666 /* 667 * initialize the error message interface 668 */ 669 670 error_info.version = (char*)pp.version; 671 #if DEBUG & TRACE_debug 672 error_info.auxilliary = context; 673 pptrace(0); 674 #endif 675 676 /* 677 * initialize pplex tables 678 */ 679 680 ppfsm(FSM_INIT, NiL); 681 682 /* 683 * fixed macro stack size -- room for improvement 684 */ 685 686 pp.macp = newof(0, struct ppmacstk, DEFMACSTACK, 0); 687 pp.macp->next = pp.macp + 1; 688 pp.maxmac = (char*)pp.macp + DEFMACSTACK; 689 initialized = 1; 690 691 /* 692 * initial include/if control stack 693 */ 694 695 pp.control = newof(0, long, pp.constack, 0); 696 pp.maxcon = pp.control + pp.constack - 1; 697 } 698 699 /* 700 * validate modes 701 */ 702 703 switch (pp.arg_mode) 704 { 705 case 'a': 706 case 'C': 707 ppop(PP_COMPATIBILITY, 0); 708 ppop(PP_TRANSITION, 1); 709 break; 710 case 'A': 711 case 'c': 712 ppop(PP_COMPATIBILITY, 0); 713 ppop(PP_STRICT, 1); 714 break; 715 case 'f': 716 ppop(PP_COMPATIBILITY, 1); 717 ppop(PP_PLUSPLUS, 1); 718 ppop(PP_TRANSITION, 1); 719 break; 720 case 'F': 721 ppop(PP_COMPATIBILITY, 0); 722 ppop(PP_PLUSPLUS, 1); 723 break; 724 case 'k': 725 case 's': 726 ppop(PP_COMPATIBILITY, 1); 727 ppop(PP_STRICT, 1); 728 break; 729 case 'o': 730 case 'O': 731 ppop(PP_COMPATIBILITY, 1); 732 ppop(PP_TRANSITION, 0); 733 break; 734 case 't': 735 ppop(PP_COMPATIBILITY, 1); 736 ppop(PP_TRANSITION, 1); 737 break; 738 } 739 if (!(pp.state & WARN) && !(pp.arg_style & STYLE_gnu)) 740 ppop(PP_PEDANTIC, 1); 741 if (pp.state & PASSTHROUGH) 742 { 743 if (pp.state & COMPILE) 744 { 745 pp.state &= ~PASSTHROUGH; 746 error(1, "passthrough ignored for compile"); 747 } 748 else 749 { 750 ppop(PP_COMPATIBILITY, 1); 751 ppop(PP_HOSTDIR, "-", 1); 752 ppop(PP_SPACEOUT, 1); 753 set(&pp.state, DISABLE, va_arg(ap, int)); 754 } 755 } 756 757 /* 758 * create the hash tables 759 */ 760 761 if (!pp.symtab) 762 pp.symtab = hashalloc(NiL, HASH_name, "symbols", 0); 763 if (!pp.dirtab) 764 { 765 pp.dirtab = hashalloc(REFONE, HASH_name, "directives", 0); 766 inithash(pp.dirtab, directives); 767 } 768 if (!pp.filtab) 769 pp.filtab = hashalloc(REFALL, HASH_name, "files", 0); 770 if (!pp.prdtab) 771 pp.prdtab = hashalloc(REFALL, HASH_name, "predicates", 0); 772 if (!pp.strtab) 773 { 774 pp.strtab = hashalloc(REFALL, HASH_name, "strings", 0); 775 inithash(pp.strtab, options); 776 inithash(pp.strtab, predicates); 777 inithash(pp.strtab, variables); 778 } 779 pp.optflags[X_PROTOTYPED] = OPT_GLOBAL; 780 pp.optflags[X_SYSTEM_HEADER] = OPT_GLOBAL|OPT_PASS; 781 782 /* 783 * mark macros that are builtin predicates 784 */ 785 786 for (kp = predicates; s = kp->name; kp++) 787 { 788 if (!ppisid(*s)) 789 s++; 790 ppassert(DEFINE, s, 0); 791 } 792 793 /* 794 * the remaining entry names must be allocated 795 */ 796 797 hashset(pp.dirtab, HASH_ALLOCATE); 798 hashset(pp.filtab, HASH_ALLOCATE); 799 hashset(pp.prdtab, HASH_ALLOCATE); 800 hashset(pp.strtab, HASH_ALLOCATE); 801 hashset(pp.symtab, HASH_ALLOCATE); 802 if (pp.test & TEST_nonoise) 803 { 804 c = error_info.trace; 805 error_info.trace = 0; 806 } 807 #if DEBUG 808 if (!(pp.test & TEST_noinit)) 809 { 810 #endif 811 812 /* 813 * compose, push and read the builtin initialization script 814 */ 815 816 if (!(sp = sfstropen())) 817 error(3, "temporary buffer allocation error"); 818 sfprintf(sp, 819 "\ 820 #%s %s:%s \"/#<assert> /\" \"/assert /%s #/\"\n\ 821 #%s %s:%s \"/#<unassert> /\" \"/unassert /%s #/\"\n\ 822 ", 823 dirname(PRAGMA), 824 pp.pass, 825 keyname(X_MAP), 826 dirname(DEFINE), 827 dirname(PRAGMA), 828 pp.pass, 829 keyname(X_MAP), 830 dirname(UNDEF)); 831 if (pp.ppdefault && *pp.ppdefault) 832 { 833 if (pp.probe) 834 { 835 c = pp.lastdir->next->type; 836 pp.lastdir->next->type = 0; 837 } 838 if (ppsearch(pp.ppdefault, T_STRING, SEARCH_EXISTS) < 0) 839 { 840 free(pp.ppdefault); 841 if (!(pp.ppdefault = pathprobe(pp.path, NiL, "C", pp.pass, pp.probe ? pp.probe : PPPROBE, 0))) 842 error(1, "cannot determine default definitions for %s", pp.probe ? pp.probe : PPPROBE); 843 } 844 if (pp.ppdefault) 845 sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), pp.ppdefault); 846 if (pp.probe) 847 pp.lastdir->next->type = c; 848 } 849 while (pp.firstop) 850 { 851 switch (pp.firstop->op) 852 { 853 case PP_ASSERT: 854 sfprintf(sp, "#%s #%s\n", dirname(DEFINE), pp.firstop->value); 855 break; 856 case PP_DEFINE: 857 if (*pp.firstop->value == '#') 858 sfprintf(sp, "#%s %s\n", dirname(DEFINE), pp.firstop->value); 859 else 860 { 861 if (s = strchr(pp.firstop->value, '=')) 862 sfprintf(sp, "#%s %-.*s %s\n", dirname(DEFINE), s - pp.firstop->value, pp.firstop->value, s + 1); 863 else 864 sfprintf(sp, "#%s %s 1\n", dirname(DEFINE), pp.firstop->value); 865 } 866 break; 867 case PP_DIRECTIVE: 868 sfprintf(sp, "#%s\n", pp.firstop->value); 869 break; 870 case PP_OPTION: 871 if (s = strchr(pp.firstop->value, '=')) 872 sfprintf(sp, "#%s %s:%-.*s %s\n", dirname(PRAGMA), pp.pass, s - pp.firstop->value, pp.firstop->value, s + 1); 873 else 874 sfprintf(sp, "#%s %s:%s\n", dirname(PRAGMA), pp.pass, pp.firstop->value); 875 break; 876 case PP_READ: 877 sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), pp.firstop->value); 878 break; 879 case PP_UNDEF: 880 sfprintf(sp, "#%s %s\n", dirname(UNDEF), pp.firstop->value); 881 break; 882 } 883 pp.lastop = pp.firstop; 884 pp.firstop = pp.firstop->next; 885 free(pp.lastop); 886 } 887 sfprintf(sp, 888 "\ 889 #%s %s:%s\n\ 890 #%s %s:%s\n\ 891 #%s !#%s(%s)\n\ 892 #%s !#%s(%s) || #%s(%s)\n\ 893 " 894 , dirname(PRAGMA) 895 , pp.pass 896 , keyname(X_BUILTIN) 897 , dirname(PRAGMA) 898 , pp.pass 899 , keyname(X_PREDEFINED) 900 , dirname(IF) 901 , keyname(X_OPTION) 902 , keyname(X_PLUSPLUS) 903 , dirname(IF) 904 , keyname(X_OPTION) 905 , keyname(X_COMPATIBILITY) 906 , keyname(X_OPTION) 907 , keyname(X_TRANSITION) 908 ); 909 sfprintf(sp, 910 "\ 911 #%s __STDC__\n\ 912 #%s __STDC__ #(STDC)\n\ 913 #%s\n\ 914 #%s #%s(%s)\n\ 915 #%s %s:%s\n\ 916 #%s %s:%s\n\ 917 #%s __STRICT__ 1\n\ 918 #%s\n\ 919 #%s\n\ 920 " 921 , dirname(IFNDEF) 922 , dirname(DEFINE) 923 , dirname(ENDIF) 924 , dirname(IF) 925 , keyname(X_OPTION) 926 , keyname(X_STRICT) 927 , dirname(PRAGMA) 928 , pp.pass 929 , keyname(X_ALLMULTIPLE) 930 , dirname(PRAGMA) 931 , pp.pass 932 , keyname(X_READONLY) 933 , dirname(DEFINE) 934 , dirname(ENDIF) 935 , dirname(ENDIF) 936 ); 937 for (kp = readonlys; s = kp->name; kp++) 938 { 939 if (!ppisid(*s)) 940 s++; 941 sfprintf(sp, "#%s %s\n", dirname(UNDEF), s); 942 } 943 sfprintf(sp, 944 "\ 945 #%s\n\ 946 #%s __STDPP__ 1\n\ 947 #%s %s:no%s\n\ 948 " 949 , dirname(ENDIF) 950 , dirname(DEFINE) 951 , dirname(PRAGMA) 952 , pp.pass 953 , keyname(X_PREDEFINED) 954 ); 955 if (!pp.truncate) 956 sfprintf(sp, 957 "\ 958 #%s __STDPP__directive #(%s)\n\ 959 " 960 , dirname(DEFINE) 961 , keyname(V_DIRECTIVE) 962 ); 963 for (kp = variables; s = kp->name; kp++) 964 if (ppisid(*s) || *s++ == '+') 965 { 966 t = *s == '_' ? "" : "__"; 967 sfprintf(sp, "#%s %s%s%s #(%s)\n" , dirname(DEFINE), t, s, t, s); 968 } 969 sfprintf(sp, 970 "\ 971 #%s %s:no%s\n\ 972 #%s %s:no%s\n\ 973 " 974 , dirname(PRAGMA) 975 , pp.pass 976 , keyname(X_READONLY) 977 , dirname(PRAGMA) 978 , pp.pass 979 , keyname(X_BUILTIN) 980 ); 981 t = sfstruse(sp); 982 debug((-9, "\n/* begin initialization */\n%s/* end initialization */", t)); 983 ppcomment = pp.comment; 984 pp.comment = 0; 985 pplinesync = pp.linesync; 986 pp.linesync = 0; 987 PUSH_INIT(pp.pass, t); 988 pp.mode |= INIT; 989 while (pplex()); 990 pp.mode &= ~INIT; 991 pp.comment = ppcomment; 992 pp.linesync = pplinesync; 993 pp.prefix = 0; 994 sfstrclose(sp); 995 if (error_info.trace) 996 for (dp = pp.firstdir; dp; dp = dp->next) 997 message((-1, "include directory %s%s%s%s", dp->name, (dp->type & TYPE_VENDOR) ? " [VENDOR]" : "", (dp->type & TYPE_HOSTED) ? " [HOSTED]" : "", dp->c ? " [C]" : "")); 998 #if DEBUG 999 } 1000 if (pp.test & TEST_nonoise) 1001 error_info.trace = c; 1002 #endif 1003 { 1004 /* 1005 * this is sleazy but at least it's 1006 * hidden in the library 1007 */ 1008 #include <preroot.h> 1009 #if FS_PREROOT 1010 struct pplist* preroot; 1011 1012 if ((preroot = (struct pplist*)hashget(pp.prdtab, "preroot"))) 1013 setpreroot(NiL, preroot->value); 1014 #endif 1015 } 1016 if (pp.ignoresrc) 1017 { 1018 if (pp.ignoresrc > 1 && pp.stddirs != pp.firstdir) 1019 error(1, "directories up to and including %s are for \"...\" include files only", pp.stddirs->name); 1020 pp.lcldirs = pp.lcldirs->next; 1021 } 1022 if (pp.ignore) 1023 { 1024 if (*pp.ignore) 1025 ppmapinclude(pp.ignore, NiL); 1026 else 1027 pp.ignore = 0; 1028 } 1029 if (pp.standalone) 1030 pp.state |= STANDALONE; 1031 #if COMPATIBLE 1032 ppfsm(FSM_COMPATIBILITY, NiL); 1033 #endif 1034 ppfsm(FSM_PLUSPLUS, NiL); 1035 pp.initialized = 1; 1036 if (pp.reset.on) 1037 { 1038 pp.reset.symtab = pp.symtab; 1039 pp.symtab = 0; 1040 pp.reset.ro_state = pp.ro_state; 1041 pp.reset.ro_mode = pp.ro_mode; 1042 pp.reset.ro_option = pp.ro_option; 1043 } 1044 } 1045 if (pp.reset.on) 1046 { 1047 if (pp.symtab) 1048 { 1049 hashwalk(pp.filtab, 0, unguard, NiL); 1050 hashfree(pp.symtab); 1051 } 1052 pp.symtab = hashalloc(NiL, HASH_name, "symbols", HASH_free, undefine, HASH_set, HASH_ALLOCATE|HASH_BUCKET, 0); 1053 hashview(pp.symtab, pp.reset.symtab); 1054 pp.ro_state = pp.reset.ro_state; 1055 pp.ro_mode = pp.reset.ro_mode; 1056 pp.ro_option = pp.reset.ro_option; 1057 } 1058 #if CHECKPOINT 1059 if (pp.mode & DUMP) 1060 { 1061 if (!pp.pragma) 1062 error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA)); 1063 (*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1); 1064 } 1065 #endif 1066 if (n = pp.filedeps.flags) 1067 { 1068 if (!(n & PP_deps_file)) 1069 { 1070 pp.state |= NOTEXT; 1071 pp.option |= KEEPNOTEXT; 1072 pp.linesync = 0; 1073 } 1074 if (n & PP_deps_generated) 1075 pp.mode |= GENDEPS; 1076 if (n & PP_deps_local) 1077 pp.mode &= ~HEADERDEPS; 1078 else if (!(pp.mode & FILEDEPS)) 1079 pp.mode |= HEADERDEPS; 1080 pp.mode |= FILEDEPS; 1081 } 1082 1083 /* 1084 * push the main input file -- special case for hosted mark 1085 */ 1086 1087 if (pp.firstdir->type & TYPE_HOSTED) 1088 pp.mode |= MARKHOSTED; 1089 else 1090 pp.mode &= ~MARKHOSTED; 1091 #if CHECKPOINT 1092 if (!(pp.mode & DUMP)) 1093 #endif 1094 { 1095 if (!(p = error_info.file)) 1096 p = ""; 1097 else 1098 { 1099 error_info.file = 0; 1100 if (*p) 1101 { 1102 pathcanon(p, 0); 1103 p = ppsetfile(p)->name; 1104 } 1105 } 1106 PUSH_FILE(p, 0); 1107 } 1108 if (pp.mode & FILEDEPS) 1109 { 1110 if (s = strrchr(error_info.file, '/')) 1111 s++; 1112 else 1113 s = error_info.file; 1114 if (!*s) 1115 s = "-"; 1116 s = strcpy(pp.tmpbuf, s); 1117 if ((t = p = strrchr(s, '.')) && (*++p == 'c' || *p == 'C')) 1118 { 1119 if (c = *++p) 1120 while (*++p == c); 1121 if (*p) 1122 t = 0; 1123 else 1124 t++; 1125 } 1126 if (!t) 1127 { 1128 t = s + strlen(s); 1129 *t++ = '.'; 1130 } 1131 *(t + 1) = 0; 1132 if (pp.state & NOTEXT) 1133 pp.filedeps.sp = sfstdout; 1134 else 1135 { 1136 *t = 'd'; 1137 if (!(pp.filedeps.sp = sfopen(NiL, s, "w"))) 1138 error(ERROR_SYSTEM|3, "%s: cannot create", s); 1139 } 1140 *t = 'o'; 1141 pp.column = sfprintf(pp.filedeps.sp, "%s :", s); 1142 if (*error_info.file) 1143 pp.column += sfprintf(pp.filedeps.sp, " %s", error_info.file); 1144 } 1145 if (xp = pp.firsttx) 1146 { 1147 if (!(sp = sfstropen())) 1148 error(3, "temporary buffer allocation error"); 1149 while (xp) 1150 { 1151 sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), xp->value); 1152 xp = xp->next; 1153 } 1154 t = sfstruse(sp); 1155 PUSH_BUFFER("options", t, 1); 1156 sfstrclose(sp); 1157 } 1158 break; 1159 case PP_INPUT: 1160 #if CHECKPOINT && POOL 1161 if (!(pp.mode & DUMP) || pp.pool.input) 1162 #else 1163 #if CHECKPOINT 1164 if (!(pp.mode & DUMP)) 1165 #else 1166 #if POOL 1167 if (pp.pool.input) 1168 #endif 1169 #endif 1170 #endif 1171 { 1172 p = va_arg(ap, char*); 1173 if (!error_info.file) 1174 error_info.file = p; 1175 close(0); 1176 if (open(p, O_RDONLY) != 0) 1177 error(ERROR_SYSTEM|3, "%s: cannot read", p); 1178 if (strmatch(p, "*.(s|S|as|AS|asm|ASM)")) 1179 { 1180 set(&pp.mode, CATLITERAL, 0); 1181 ppop(PP_SPACEOUT, 1); 1182 } 1183 break; 1184 } 1185 /*FALLTHROUGH*/ 1186 case PP_TEXT: 1187 if (pp.initialized) 1188 goto before; 1189 if ((p = va_arg(ap, char*)) && *p) 1190 { 1191 if (pp.lasttx) 1192 pp.lasttx = pp.lasttx->next = newof(0, struct oplist, 1, 0); 1193 else 1194 pp.firsttx = pp.lasttx = newof(0, struct oplist, 1, 0); 1195 pp.lasttx->op = op; 1196 pp.lasttx->value = p; 1197 } 1198 break; 1199 case PP_KEYARGS: 1200 if (pp.initialized) 1201 goto before; 1202 set(&pp.option, KEYARGS, va_arg(ap, int)); 1203 if (pp.option & KEYARGS) 1204 #if MACKEYARGS 1205 set(&pp.mode, CATLITERAL, 1); 1206 #else 1207 error(3, "preprocessor not compiled with macro keyword arguments enabled [MACKEYARGS]"); 1208 #endif 1209 break; 1210 case PP_LINE: 1211 pp.linesync = va_arg(ap, PPLINESYNC); 1212 break; 1213 case PP_LINEBASE: 1214 if (va_arg(ap, int)) 1215 pp.flags |= PP_linebase; 1216 else 1217 pp.flags &= ~PP_linebase; 1218 break; 1219 case PP_LINEFILE: 1220 if (va_arg(ap, int)) 1221 pp.flags |= PP_linefile; 1222 else 1223 pp.flags &= ~PP_linefile; 1224 break; 1225 case PP_LINEID: 1226 if (!(p = va_arg(ap, char*))) 1227 pp.lineid = ""; 1228 else if (*p != '-') 1229 pp.lineid = strdup(p); 1230 else 1231 pp.option |= IGNORELINE; 1232 break; 1233 case PP_LINETYPE: 1234 if ((n = va_arg(ap, int)) >= 1) 1235 pp.flags |= PP_linetype; 1236 else 1237 pp.flags &= ~PP_linetype; 1238 if (n >= 2) 1239 pp.flags |= PP_linehosted; 1240 else 1241 pp.flags &= ~PP_linehosted; 1242 break; 1243 case PP_LOCAL: 1244 if (pp.initialized) 1245 goto before; 1246 pp.ignoresrc++; 1247 pp.stddirs = pp.lastdir; 1248 if (!(pp.ro_option & PREFIX)) 1249 pp.option &= ~PREFIX; 1250 break; 1251 case PP_MACREF: 1252 pp.macref = va_arg(ap, PPMACREF); 1253 break; 1254 case PP_MULTIPLE: 1255 set(&pp.mode, ALLMULTIPLE, va_arg(ap, int)); 1256 break; 1257 case PP_NOHASH: 1258 set(&pp.option, NOHASH, va_arg(ap, int)); 1259 break; 1260 case PP_NOISE: 1261 op = va_arg(ap, int); 1262 set(&pp.option, NOISE, op); 1263 set(&pp.option, NOISEFILTER, op < 0); 1264 break; 1265 case PP_OPTARG: 1266 pp.optarg = va_arg(ap, PPOPTARG); 1267 break; 1268 case PP_OUTPUT: 1269 pp.outfile = va_arg(ap, char*); 1270 if (identical(pp.outfile, 0)) 1271 error(3, "%s: identical to input", pp.outfile); 1272 close(1); 1273 if (open(pp.outfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1) 1274 error(ERROR_SYSTEM|3, "%s: cannot create", pp.outfile); 1275 break; 1276 case PP_PASSTHROUGH: 1277 if (!(pp.state & COMPILE)) 1278 set(&pp.state, PASSTHROUGH, va_arg(ap, int)); 1279 break; 1280 case PP_PEDANTIC: 1281 set(&pp.mode, PEDANTIC, va_arg(ap, int)); 1282 break; 1283 case PP_PLUSCOMMENT: 1284 set(&pp.option, PLUSCOMMENT, va_arg(ap, int)); 1285 if (pp.initialized) 1286 ppfsm(FSM_PLUSPLUS, NiL); 1287 break; 1288 case PP_PLUSPLUS: 1289 set(&pp.option, PLUSPLUS, va_arg(ap, int)); 1290 set(&pp.option, PLUSCOMMENT, va_arg(ap, int)); 1291 if (pp.initialized) 1292 ppfsm(FSM_PLUSPLUS, NiL); 1293 break; 1294 case PP_POOL: 1295 if (pp.initialized) 1296 goto before; 1297 if (va_arg(ap, int)) 1298 { 1299 #if POOL 1300 pp.pool.input = dup(0); 1301 pp.pool.output = dup(1); 1302 p = "/dev/null"; 1303 if (!identical(p, 0)) 1304 { 1305 if (!identical(p, 1)) 1306 ppop(PP_OUTPUT, p); 1307 ppop(PP_INPUT, p); 1308 } 1309 #else 1310 error(3, "preprocessor not compiled with input pool enabled [POOL]"); 1311 #endif 1312 } 1313 break; 1314 case PP_PRAGMA: 1315 pp.pragma = va_arg(ap, PPPRAGMA); 1316 break; 1317 case PP_PRAGMAFLAGS: 1318 if (p = va_arg(ap, char*)) 1319 { 1320 n = OPT_GLOBAL; 1321 if (*p == '-') 1322 p++; 1323 else 1324 n |= OPT_PASS; 1325 if ((c = (int)hashref(pp.strtab, p)) > 0 && c <= X_last_option) 1326 pp.optflags[c] = n; 1327 } 1328 break; 1329 case PP_PROBE: 1330 pp.probe = va_arg(ap, char*); 1331 break; 1332 case PP_QUOTE: 1333 p = va_arg(ap, char*); 1334 c = va_arg(ap, int); 1335 if (p) 1336 ppfsm(c ? FSM_QUOTADD : FSM_QUOTDEL, p); 1337 break; 1338 case PP_REGUARD: 1339 set(&pp.option, REGUARD, va_arg(ap, int)); 1340 break; 1341 case PP_RESERVED: 1342 if ((pp.state & COMPILE) && (p = va_arg(ap, char*))) 1343 { 1344 if (!(sp = sfstropen())) 1345 error(3, "temporary buffer allocation error"); 1346 sfputr(sp, p, -1); 1347 p = sfstruse(sp); 1348 if (s = strchr(p, '=')) 1349 *s++ = 0; 1350 else 1351 s = p; 1352 while (*s == '_') 1353 s++; 1354 for (t = s + strlen(s); t > s && *(t - 1) == '_'; t--); 1355 if (*t == '_') 1356 *t = 0; 1357 else 1358 t = 0; 1359 op = ((key = ppkeyref(pp.symtab, s)) && (key->sym.flags & SYM_LEX)) ? key->lex : T_NOISE; 1360 if (pp.test & 0x0400) 1361 error(1, "reserved#1 `%s' %d", s, op); 1362 if (t) 1363 *t = '_'; 1364 if (!(key = ppkeyget(pp.symtab, p))) 1365 key = ppkeyset(pp.symtab, NiL); 1366 else if (!(key->sym.flags & SYM_LEX)) 1367 { 1368 struct ppsymbol tmp; 1369 1370 tmp = key->sym; 1371 hashlook(pp.symtab, p, HASH_DELETE, NiL); 1372 key = ppkeyset(pp.symtab, NiL); 1373 key->sym.flags = tmp.flags; 1374 key->sym.macro = tmp.macro; 1375 key->sym.value = tmp.value; 1376 key->sym.hidden = tmp.hidden; 1377 } 1378 if (!(key->sym.flags & SYM_KEYWORD)) 1379 { 1380 key->sym.flags |= SYM_KEYWORD|SYM_LEX; 1381 key->lex = op; 1382 if (pp.test & 0x0400) 1383 error(1, "reserved#2 `%s' %d", p, op); 1384 } 1385 sfstrclose(sp); 1386 } 1387 break; 1388 case PP_SPACEOUT: 1389 set(&pp.state, SPACEOUT, va_arg(ap, int)); 1390 break; 1391 case PP_STANDALONE: 1392 if (pp.initialized) 1393 goto before; 1394 pp.standalone = 1; 1395 break; 1396 case PP_STANDARD: 1397 if ((pp.lastdir->next->name = ((p = va_arg(ap, char*)) && *p) ? p : NiL) && !stat(p, &st)) 1398 SAVEID(&pp.lastdir->next->id, &st); 1399 for (dp = pp.firstdir; dp; dp = dp->next) 1400 if (dp->name) 1401 for (hp = pp.firstdir; hp != dp; hp = hp->next) 1402 if (hp->name && SAMEID(&hp->id, &dp->id)) 1403 { 1404 hp->c = dp->c; 1405 if (dp->type & TYPE_HOSTED) 1406 hp->type |= TYPE_HOSTED; 1407 else 1408 hp->type &= ~TYPE_HOSTED; 1409 } 1410 break; 1411 case PP_STRICT: 1412 set(&pp.state, TRANSITION, 0); 1413 pp.flags &= ~PP_transition; 1414 set(&pp.state, STRICT, va_arg(ap, int)); 1415 if (pp.state & STRICT) 1416 pp.flags |= PP_strict; 1417 else 1418 pp.flags &= ~PP_strict; 1419 break; 1420 case PP_TEST: 1421 if (p = va_arg(ap, char*)) 1422 for (;;) 1423 { 1424 while (*p == ' ' || *p == '\t') p++; 1425 for (s = p; n = *s; s++) 1426 if (n == ',' || n == ' ' || n == '\t') 1427 { 1428 *s++ = 0; 1429 break; 1430 } 1431 if (!*p) 1432 break; 1433 n = 0; 1434 if (*p == 'n' && *(p + 1) == 'o') 1435 { 1436 p += 2; 1437 op = 0; 1438 } 1439 else 1440 op = 1; 1441 if (streq(p, "count")) 1442 n = TEST_count; 1443 else if (streq(p, "hashcount")) 1444 n = TEST_hashcount; 1445 else if (streq(p, "hashdump")) 1446 n = TEST_hashdump; 1447 else if (streq(p, "hit")) 1448 n = TEST_hit; 1449 else if (streq(p, "init")) 1450 n = TEST_noinit|TEST_INVERT; 1451 else if (streq(p, "noise")) 1452 n = TEST_nonoise|TEST_INVERT; 1453 else if (streq(p, "proto")) 1454 n = TEST_noproto|TEST_INVERT; 1455 else if (*p >= '0' && *p <= '9') 1456 n = strtoul(p, NiL, 0); 1457 else 1458 { 1459 error(1, "%s: unknown test", p); 1460 break; 1461 } 1462 if (n & TEST_INVERT) 1463 { 1464 n &= ~TEST_INVERT; 1465 op = !op; 1466 } 1467 if (op) 1468 pp.test |= n; 1469 else 1470 pp.test &= ~n; 1471 p = s; 1472 debug((-4, "test = 0%o", pp.test)); 1473 } 1474 break; 1475 case PP_TRANSITION: 1476 set(&pp.state, STRICT, 0); 1477 pp.flags &= ~PP_strict; 1478 set(&pp.state, TRANSITION, va_arg(ap, int)); 1479 if (pp.state & TRANSITION) 1480 pp.flags |= PP_transition; 1481 else 1482 pp.flags &= ~PP_transition; 1483 break; 1484 case PP_TRUNCATE: 1485 if (pp.initialized) 1486 goto before; 1487 if ((op = va_arg(ap, int)) < 0) 1488 op = 0; 1489 set(&pp.option, TRUNCATE, op); 1490 if (pp.option & TRUNCATE) 1491 { 1492 Hash_bucket_t* b; 1493 Hash_bucket_t* p; 1494 Hash_position_t* pos; 1495 Hash_table_t* tab; 1496 1497 pp.truncate = op; 1498 tab = pp.symtab; 1499 pp.symtab = hashalloc(NiL, HASH_set, tab ? HASH_ALLOCATE : 0, HASH_compare, trunccomp, HASH_hash, trunchash, HASH_name, "truncate", 0); 1500 if (tab && (pos = hashscan(tab, 0))) 1501 { 1502 if (p = hashnext(pos)) 1503 do 1504 { 1505 b = hashnext(pos); 1506 hashlook(pp.symtab, (char*)p, HASH_BUCKET|HASH_INSTALL, NiL); 1507 } while (p = b); 1508 hashdone(pos); 1509 } 1510 } 1511 else 1512 pp.truncate = 0; 1513 break; 1514 case PP_VENDOR: 1515 p = va_arg(ap, char*); 1516 c = va_arg(ap, int) != 0; 1517 if (!p || !*p) 1518 for (dp = pp.firstdir; dp; dp = dp->next) 1519 dp->type &= ~TYPE_VENDOR; 1520 else if (streq(p, "-")) 1521 { 1522 for (dp = pp.firstdir; dp; dp = dp->next) 1523 if (c) 1524 dp->type |= TYPE_VENDOR; 1525 else 1526 dp->type &= ~TYPE_VENDOR; 1527 } 1528 else if (!stat((pathcanon(p, 0), p), &st)) 1529 { 1530 c = 0; 1531 for (dp = pp.firstdir; dp; dp = dp->next) 1532 { 1533 if (!c && ((dp->type & TYPE_VENDOR) || dp->name && SAMEID(&dp->id, &st))) 1534 c = 1; 1535 if (c) 1536 dp->type |= TYPE_VENDOR; 1537 else 1538 dp->type &= ~TYPE_VENDOR; 1539 } 1540 } 1541 break; 1542 case PP_WARN: 1543 set(&pp.state, WARN, va_arg(ap, int)); 1544 break; 1545 before: 1546 error(3, "ppop(%d): preprocessor operation must be done before PP_INIT", op); 1547 break; 1548 default: 1549 error(3, "ppop(%d): invalid preprocessor operation", op); 1550 break; 1551 } 1552 va_end(ap); 1553 } 1554