1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1986-2009 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.probe) 845 pp.lastdir->next->type = c; 846 } 847 while (pp.firstop) 848 { 849 switch (pp.firstop->op) 850 { 851 case PP_ASSERT: 852 sfprintf(sp, "#%s #%s\n", dirname(DEFINE), pp.firstop->value); 853 break; 854 case PP_DEFINE: 855 if (*pp.firstop->value == '#') 856 sfprintf(sp, "#%s %s\n", dirname(DEFINE), pp.firstop->value); 857 else 858 { 859 if (s = strchr(pp.firstop->value, '=')) 860 sfprintf(sp, "#%s %-.*s %s\n", dirname(DEFINE), s - pp.firstop->value, pp.firstop->value, s + 1); 861 else 862 sfprintf(sp, "#%s %s 1\n", dirname(DEFINE), pp.firstop->value); 863 } 864 break; 865 case PP_DIRECTIVE: 866 sfprintf(sp, "#%s\n", pp.firstop->value); 867 break; 868 case PP_OPTION: 869 if (s = strchr(pp.firstop->value, '=')) 870 sfprintf(sp, "#%s %s:%-.*s %s\n", dirname(PRAGMA), pp.pass, s - pp.firstop->value, pp.firstop->value, s + 1); 871 else 872 sfprintf(sp, "#%s %s:%s\n", dirname(PRAGMA), pp.pass, pp.firstop->value); 873 break; 874 case PP_READ: 875 sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), pp.firstop->value); 876 break; 877 case PP_UNDEF: 878 sfprintf(sp, "#%s %s\n", dirname(UNDEF), pp.firstop->value); 879 break; 880 } 881 pp.lastop = pp.firstop; 882 pp.firstop = pp.firstop->next; 883 free(pp.lastop); 884 } 885 sfprintf(sp, 886 "\ 887 #%s %s:%s\n\ 888 #%s %s:%s\n\ 889 #%s !#%s(%s)\n\ 890 #%s !#%s(%s) || #%s(%s)\n\ 891 " 892 , dirname(PRAGMA) 893 , pp.pass 894 , keyname(X_BUILTIN) 895 , dirname(PRAGMA) 896 , pp.pass 897 , keyname(X_PREDEFINED) 898 , dirname(IF) 899 , keyname(X_OPTION) 900 , keyname(X_PLUSPLUS) 901 , dirname(IF) 902 , keyname(X_OPTION) 903 , keyname(X_COMPATIBILITY) 904 , keyname(X_OPTION) 905 , keyname(X_TRANSITION) 906 ); 907 sfprintf(sp, 908 "\ 909 #%s #%s(%s)\n\ 910 #%s %s:%s\n\ 911 #%s %s:%s\n\ 912 #%s __STRICT__ 1\n\ 913 #%s\n\ 914 #%s\n\ 915 " 916 , dirname(IF) 917 , keyname(X_OPTION) 918 , keyname(X_STRICT) 919 , dirname(PRAGMA) 920 , pp.pass 921 , keyname(X_ALLMULTIPLE) 922 , dirname(PRAGMA) 923 , pp.pass 924 , keyname(X_READONLY) 925 , dirname(DEFINE) 926 , dirname(ENDIF) 927 , dirname(ENDIF) 928 ); 929 for (kp = readonlys; s = kp->name; kp++) 930 { 931 if (!ppisid(*s)) 932 s++; 933 sfprintf(sp, "#%s %s\n", dirname(UNDEF), s); 934 } 935 sfprintf(sp, 936 "\ 937 #%s\n\ 938 #%s __STDPP__ 1\n\ 939 #%s %s:no%s\n\ 940 " 941 , dirname(ENDIF) 942 , dirname(DEFINE) 943 , dirname(PRAGMA) 944 , pp.pass 945 , keyname(X_PREDEFINED) 946 ); 947 if (!pp.truncate) 948 sfprintf(sp, 949 "\ 950 #%s __STDPP__directive #(%s)\n\ 951 " 952 , dirname(DEFINE) 953 , keyname(V_DIRECTIVE) 954 ); 955 for (kp = variables; s = kp->name; kp++) 956 if (ppisid(*s) || *s++ == '+') 957 { 958 t = *s == '_' ? "" : "__"; 959 sfprintf(sp, "#%s %s%s%s #(%s)\n" , dirname(DEFINE), t, s, t, s); 960 } 961 sfprintf(sp, 962 "\ 963 #%s %s:no%s\n\ 964 #%s %s:no%s\n\ 965 " 966 , dirname(PRAGMA) 967 , pp.pass 968 , keyname(X_READONLY) 969 , dirname(PRAGMA) 970 , pp.pass 971 , keyname(X_BUILTIN) 972 ); 973 if (pp.ppdefault && *pp.ppdefault) 974 sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), pp.ppdefault); 975 sfprintf(sp, 976 "\ 977 #%s !defined(__STDC__) && (!#option(compatibility) || #option(transition))\n\ 978 #%s __STDC__ #(STDC)\n\ 979 #%s\n\ 980 " 981 , dirname(IF) 982 , dirname(DEFINE) 983 , dirname(ENDIF) 984 ); 985 t = sfstruse(sp); 986 debug((-9, "\n/* begin initialization */\n%s/* end initialization */", t)); 987 ppcomment = pp.comment; 988 pp.comment = 0; 989 pplinesync = pp.linesync; 990 pp.linesync = 0; 991 PUSH_INIT(pp.pass, t); 992 pp.mode |= INIT; 993 while (pplex()); 994 pp.mode &= ~INIT; 995 pp.comment = ppcomment; 996 pp.linesync = pplinesync; 997 pp.prefix = 0; 998 sfstrclose(sp); 999 if (error_info.trace) 1000 for (dp = pp.firstdir; dp; dp = dp->next) 1001 message((-1, "include directory %s%s%s%s", dp->name, (dp->type & TYPE_VENDOR) ? " [VENDOR]" : "", (dp->type & TYPE_HOSTED) ? " [HOSTED]" : "", dp->c ? " [C]" : "")); 1002 #if DEBUG 1003 } 1004 if (pp.test & TEST_nonoise) 1005 error_info.trace = c; 1006 #endif 1007 { 1008 /* 1009 * this is sleazy but at least it's 1010 * hidden in the library 1011 */ 1012 #include <preroot.h> 1013 #if FS_PREROOT 1014 struct pplist* preroot; 1015 1016 if ((preroot = (struct pplist*)hashget(pp.prdtab, "preroot"))) 1017 setpreroot(NiL, preroot->value); 1018 #endif 1019 } 1020 if (pp.ignoresrc) 1021 { 1022 if (pp.ignoresrc > 1 && pp.stddirs != pp.firstdir) 1023 error(1, "directories up to and including %s are for \"...\" include files only", pp.stddirs->name); 1024 pp.lcldirs = pp.lcldirs->next; 1025 } 1026 if (pp.ignore) 1027 { 1028 if (*pp.ignore) 1029 ppmapinclude(pp.ignore, NiL); 1030 else 1031 pp.ignore = 0; 1032 } 1033 if (pp.standalone) 1034 pp.state |= STANDALONE; 1035 #if COMPATIBLE 1036 ppfsm(FSM_COMPATIBILITY, NiL); 1037 #endif 1038 ppfsm(FSM_PLUSPLUS, NiL); 1039 pp.initialized = 1; 1040 if (pp.reset.on) 1041 { 1042 pp.reset.symtab = pp.symtab; 1043 pp.symtab = 0; 1044 pp.reset.ro_state = pp.ro_state; 1045 pp.reset.ro_mode = pp.ro_mode; 1046 pp.reset.ro_option = pp.ro_option; 1047 } 1048 } 1049 if (pp.reset.on) 1050 { 1051 if (pp.symtab) 1052 { 1053 hashwalk(pp.filtab, 0, unguard, NiL); 1054 hashfree(pp.symtab); 1055 } 1056 pp.symtab = hashalloc(NiL, HASH_name, "symbols", HASH_free, undefine, HASH_set, HASH_ALLOCATE|HASH_BUCKET, 0); 1057 hashview(pp.symtab, pp.reset.symtab); 1058 pp.ro_state = pp.reset.ro_state; 1059 pp.ro_mode = pp.reset.ro_mode; 1060 pp.ro_option = pp.reset.ro_option; 1061 } 1062 #if CHECKPOINT 1063 if (pp.mode & DUMP) 1064 { 1065 if (!pp.pragma) 1066 error(3, "#%s must be enabled for checkpoints", dirname(PRAGMA)); 1067 (*pp.pragma)(dirname(PRAGMA), pp.pass, keyname(X_CHECKPOINT), pp.checkpoint, 1); 1068 } 1069 #endif 1070 if (n = pp.filedeps.flags) 1071 { 1072 if (!(n & PP_deps_file)) 1073 { 1074 pp.state |= NOTEXT; 1075 pp.option |= KEEPNOTEXT; 1076 pp.linesync = 0; 1077 } 1078 if (n & PP_deps_generated) 1079 pp.mode |= GENDEPS; 1080 if (n & PP_deps_local) 1081 pp.mode &= ~HEADERDEPS; 1082 else if (!(pp.mode & FILEDEPS)) 1083 pp.mode |= HEADERDEPS; 1084 pp.mode |= FILEDEPS; 1085 } 1086 1087 /* 1088 * push the main input file -- special case for hosted mark 1089 */ 1090 1091 if (pp.firstdir->type & TYPE_HOSTED) 1092 pp.mode |= MARKHOSTED; 1093 else 1094 pp.mode &= ~MARKHOSTED; 1095 #if CHECKPOINT 1096 if (!(pp.mode & DUMP)) 1097 #endif 1098 { 1099 if (!(p = error_info.file)) 1100 p = ""; 1101 else 1102 { 1103 error_info.file = 0; 1104 if (*p) 1105 { 1106 pathcanon(p, 0); 1107 p = ppsetfile(p)->name; 1108 } 1109 } 1110 PUSH_FILE(p, 0); 1111 } 1112 if (pp.mode & FILEDEPS) 1113 { 1114 if (s = strrchr(error_info.file, '/')) 1115 s++; 1116 else 1117 s = error_info.file; 1118 if (!*s) 1119 s = "-"; 1120 s = strcpy(pp.tmpbuf, s); 1121 if ((t = p = strrchr(s, '.')) && (*++p == 'c' || *p == 'C')) 1122 { 1123 if (c = *++p) 1124 while (*++p == c); 1125 if (*p) 1126 t = 0; 1127 else 1128 t++; 1129 } 1130 if (!t) 1131 { 1132 t = s + strlen(s); 1133 *t++ = '.'; 1134 } 1135 *(t + 1) = 0; 1136 if (pp.state & NOTEXT) 1137 pp.filedeps.sp = sfstdout; 1138 else 1139 { 1140 *t = 'd'; 1141 if (!(pp.filedeps.sp = sfopen(NiL, s, "w"))) 1142 error(ERROR_SYSTEM|3, "%s: cannot create", s); 1143 } 1144 *t = 'o'; 1145 pp.column = sfprintf(pp.filedeps.sp, "%s :", s); 1146 if (*error_info.file) 1147 pp.column += sfprintf(pp.filedeps.sp, " %s", error_info.file); 1148 } 1149 if (xp = pp.firsttx) 1150 { 1151 if (!(sp = sfstropen())) 1152 error(3, "temporary buffer allocation error"); 1153 while (xp) 1154 { 1155 sfprintf(sp, "#%s \"%s\"\n", dirname(INCLUDE), xp->value); 1156 xp = xp->next; 1157 } 1158 t = sfstruse(sp); 1159 PUSH_BUFFER("options", t, 1); 1160 sfstrclose(sp); 1161 } 1162 break; 1163 case PP_INPUT: 1164 #if CHECKPOINT && POOL 1165 if (!(pp.mode & DUMP) || pp.pool.input) 1166 #else 1167 #if CHECKPOINT 1168 if (!(pp.mode & DUMP)) 1169 #else 1170 #if POOL 1171 if (pp.pool.input) 1172 #endif 1173 #endif 1174 #endif 1175 { 1176 p = va_arg(ap, char*); 1177 if (!error_info.file) 1178 error_info.file = p; 1179 close(0); 1180 if (open(p, O_RDONLY) != 0) 1181 error(ERROR_SYSTEM|3, "%s: cannot read", p); 1182 if (strmatch(p, "*.(s|S|as|AS|asm|ASM)")) 1183 { 1184 set(&pp.mode, CATLITERAL, 0); 1185 ppop(PP_SPACEOUT, 1); 1186 } 1187 break; 1188 } 1189 /*FALLTHROUGH*/ 1190 case PP_TEXT: 1191 if (pp.initialized) 1192 goto before; 1193 if ((p = va_arg(ap, char*)) && *p) 1194 { 1195 if (pp.lasttx) 1196 pp.lasttx = pp.lasttx->next = newof(0, struct oplist, 1, 0); 1197 else 1198 pp.firsttx = pp.lasttx = newof(0, struct oplist, 1, 0); 1199 pp.lasttx->op = op; 1200 pp.lasttx->value = p; 1201 } 1202 break; 1203 case PP_KEYARGS: 1204 if (pp.initialized) 1205 goto before; 1206 set(&pp.option, KEYARGS, va_arg(ap, int)); 1207 if (pp.option & KEYARGS) 1208 #if MACKEYARGS 1209 set(&pp.mode, CATLITERAL, 1); 1210 #else 1211 error(3, "preprocessor not compiled with macro keyword arguments enabled [MACKEYARGS]"); 1212 #endif 1213 break; 1214 case PP_LINE: 1215 pp.linesync = va_arg(ap, PPLINESYNC); 1216 break; 1217 case PP_LINEBASE: 1218 if (va_arg(ap, int)) 1219 pp.flags |= PP_linebase; 1220 else 1221 pp.flags &= ~PP_linebase; 1222 break; 1223 case PP_LINEFILE: 1224 if (va_arg(ap, int)) 1225 pp.flags |= PP_linefile; 1226 else 1227 pp.flags &= ~PP_linefile; 1228 break; 1229 case PP_LINEID: 1230 if (!(p = va_arg(ap, char*))) 1231 pp.lineid = ""; 1232 else if (*p != '-') 1233 pp.lineid = strdup(p); 1234 else 1235 pp.option |= IGNORELINE; 1236 break; 1237 case PP_LINETYPE: 1238 if ((n = va_arg(ap, int)) >= 1) 1239 pp.flags |= PP_linetype; 1240 else 1241 pp.flags &= ~PP_linetype; 1242 if (n >= 2) 1243 pp.flags |= PP_linehosted; 1244 else 1245 pp.flags &= ~PP_linehosted; 1246 break; 1247 case PP_LOCAL: 1248 if (pp.initialized) 1249 goto before; 1250 pp.ignoresrc++; 1251 pp.stddirs = pp.lastdir; 1252 if (!(pp.ro_option & PREFIX)) 1253 pp.option &= ~PREFIX; 1254 break; 1255 case PP_MACREF: 1256 pp.macref = va_arg(ap, PPMACREF); 1257 break; 1258 case PP_MULTIPLE: 1259 set(&pp.mode, ALLMULTIPLE, va_arg(ap, int)); 1260 break; 1261 case PP_NOHASH: 1262 set(&pp.option, NOHASH, va_arg(ap, int)); 1263 break; 1264 case PP_NOISE: 1265 op = va_arg(ap, int); 1266 set(&pp.option, NOISE, op); 1267 set(&pp.option, NOISEFILTER, op < 0); 1268 break; 1269 case PP_OPTARG: 1270 pp.optarg = va_arg(ap, PPOPTARG); 1271 break; 1272 case PP_OUTPUT: 1273 pp.outfile = va_arg(ap, char*); 1274 if (identical(pp.outfile, 0)) 1275 error(3, "%s: identical to input", pp.outfile); 1276 close(1); 1277 if (open(pp.outfile, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) != 1) 1278 error(ERROR_SYSTEM|3, "%s: cannot create", pp.outfile); 1279 break; 1280 case PP_PASSTHROUGH: 1281 if (!(pp.state & COMPILE)) 1282 set(&pp.state, PASSTHROUGH, va_arg(ap, int)); 1283 break; 1284 case PP_PEDANTIC: 1285 set(&pp.mode, PEDANTIC, va_arg(ap, int)); 1286 break; 1287 case PP_PLUSCOMMENT: 1288 set(&pp.option, PLUSCOMMENT, va_arg(ap, int)); 1289 if (pp.initialized) 1290 ppfsm(FSM_PLUSPLUS, NiL); 1291 break; 1292 case PP_PLUSPLUS: 1293 set(&pp.option, PLUSPLUS, va_arg(ap, int)); 1294 set(&pp.option, PLUSCOMMENT, va_arg(ap, int)); 1295 if (pp.initialized) 1296 ppfsm(FSM_PLUSPLUS, NiL); 1297 break; 1298 case PP_POOL: 1299 if (pp.initialized) 1300 goto before; 1301 if (va_arg(ap, int)) 1302 { 1303 #if POOL 1304 pp.pool.input = dup(0); 1305 pp.pool.output = dup(1); 1306 p = "/dev/null"; 1307 if (!identical(p, 0)) 1308 { 1309 if (!identical(p, 1)) 1310 ppop(PP_OUTPUT, p); 1311 ppop(PP_INPUT, p); 1312 } 1313 #else 1314 error(3, "preprocessor not compiled with input pool enabled [POOL]"); 1315 #endif 1316 } 1317 break; 1318 case PP_PRAGMA: 1319 pp.pragma = va_arg(ap, PPPRAGMA); 1320 break; 1321 case PP_PRAGMAFLAGS: 1322 if (p = va_arg(ap, char*)) 1323 { 1324 n = OPT_GLOBAL; 1325 if (*p == '-') 1326 p++; 1327 else 1328 n |= OPT_PASS; 1329 if ((c = (int)hashref(pp.strtab, p)) > 0 && c <= X_last_option) 1330 pp.optflags[c] = n; 1331 } 1332 break; 1333 case PP_PROBE: 1334 pp.probe = va_arg(ap, char*); 1335 break; 1336 case PP_QUOTE: 1337 p = va_arg(ap, char*); 1338 c = va_arg(ap, int); 1339 if (p) 1340 ppfsm(c ? FSM_QUOTADD : FSM_QUOTDEL, p); 1341 break; 1342 case PP_REGUARD: 1343 set(&pp.option, REGUARD, va_arg(ap, int)); 1344 break; 1345 case PP_RESERVED: 1346 if ((pp.state & COMPILE) && (p = va_arg(ap, char*))) 1347 { 1348 if (!(sp = sfstropen())) 1349 error(3, "temporary buffer allocation error"); 1350 sfputr(sp, p, -1); 1351 p = sfstruse(sp); 1352 if (s = strchr(p, '=')) 1353 *s++ = 0; 1354 else 1355 s = p; 1356 while (*s == '_') 1357 s++; 1358 for (t = s + strlen(s); t > s && *(t - 1) == '_'; t--); 1359 if (*t == '_') 1360 *t = 0; 1361 else 1362 t = 0; 1363 op = ((key = ppkeyref(pp.symtab, s)) && (key->sym.flags & SYM_LEX)) ? key->lex : T_NOISE; 1364 if (pp.test & 0x0400) 1365 error(1, "reserved#1 `%s' %d", s, op); 1366 if (t) 1367 *t = '_'; 1368 if (!(key = ppkeyget(pp.symtab, p))) 1369 key = ppkeyset(pp.symtab, NiL); 1370 else if (!(key->sym.flags & SYM_LEX)) 1371 { 1372 struct ppsymbol tmp; 1373 1374 tmp = key->sym; 1375 hashlook(pp.symtab, p, HASH_DELETE, NiL); 1376 key = ppkeyset(pp.symtab, NiL); 1377 key->sym.flags = tmp.flags; 1378 key->sym.macro = tmp.macro; 1379 key->sym.value = tmp.value; 1380 key->sym.hidden = tmp.hidden; 1381 } 1382 if (!(key->sym.flags & SYM_KEYWORD)) 1383 { 1384 key->sym.flags |= SYM_KEYWORD|SYM_LEX; 1385 key->lex = op; 1386 if (pp.test & 0x0400) 1387 error(1, "reserved#2 `%s' %d", p, op); 1388 } 1389 sfstrclose(sp); 1390 } 1391 break; 1392 case PP_SPACEOUT: 1393 set(&pp.state, SPACEOUT, va_arg(ap, int)); 1394 break; 1395 case PP_STANDALONE: 1396 if (pp.initialized) 1397 goto before; 1398 pp.standalone = 1; 1399 break; 1400 case PP_STANDARD: 1401 if ((pp.lastdir->next->name = ((p = va_arg(ap, char*)) && *p) ? p : NiL) && !stat(p, &st)) 1402 SAVEID(&pp.lastdir->next->id, &st); 1403 for (dp = pp.firstdir; dp; dp = dp->next) 1404 if (dp->name) 1405 for (hp = pp.firstdir; hp != dp; hp = hp->next) 1406 if (hp->name && SAMEID(&hp->id, &dp->id)) 1407 { 1408 hp->c = dp->c; 1409 if (dp->type & TYPE_HOSTED) 1410 hp->type |= TYPE_HOSTED; 1411 else 1412 hp->type &= ~TYPE_HOSTED; 1413 } 1414 break; 1415 case PP_STRICT: 1416 set(&pp.state, TRANSITION, 0); 1417 pp.flags &= ~PP_transition; 1418 set(&pp.state, STRICT, va_arg(ap, int)); 1419 if (pp.state & STRICT) 1420 pp.flags |= PP_strict; 1421 else 1422 pp.flags &= ~PP_strict; 1423 break; 1424 case PP_TEST: 1425 if (p = va_arg(ap, char*)) 1426 for (;;) 1427 { 1428 while (*p == ' ' || *p == '\t') p++; 1429 for (s = p; n = *s; s++) 1430 if (n == ',' || n == ' ' || n == '\t') 1431 { 1432 *s++ = 0; 1433 break; 1434 } 1435 if (!*p) 1436 break; 1437 n = 0; 1438 if (*p == 'n' && *(p + 1) == 'o') 1439 { 1440 p += 2; 1441 op = 0; 1442 } 1443 else 1444 op = 1; 1445 if (streq(p, "count")) 1446 n = TEST_count; 1447 else if (streq(p, "hashcount")) 1448 n = TEST_hashcount; 1449 else if (streq(p, "hashdump")) 1450 n = TEST_hashdump; 1451 else if (streq(p, "hit")) 1452 n = TEST_hit; 1453 else if (streq(p, "init")) 1454 n = TEST_noinit|TEST_INVERT; 1455 else if (streq(p, "noise")) 1456 n = TEST_nonoise|TEST_INVERT; 1457 else if (streq(p, "proto")) 1458 n = TEST_noproto|TEST_INVERT; 1459 else if (*p >= '0' && *p <= '9') 1460 n = strtoul(p, NiL, 0); 1461 else 1462 { 1463 error(1, "%s: unknown test", p); 1464 break; 1465 } 1466 if (n & TEST_INVERT) 1467 { 1468 n &= ~TEST_INVERT; 1469 op = !op; 1470 } 1471 if (op) 1472 pp.test |= n; 1473 else 1474 pp.test &= ~n; 1475 p = s; 1476 debug((-4, "test = 0%o", pp.test)); 1477 } 1478 break; 1479 case PP_TRANSITION: 1480 set(&pp.state, STRICT, 0); 1481 pp.flags &= ~PP_strict; 1482 set(&pp.state, TRANSITION, va_arg(ap, int)); 1483 if (pp.state & TRANSITION) 1484 pp.flags |= PP_transition; 1485 else 1486 pp.flags &= ~PP_transition; 1487 break; 1488 case PP_TRUNCATE: 1489 if (pp.initialized) 1490 goto before; 1491 if ((op = va_arg(ap, int)) < 0) 1492 op = 0; 1493 set(&pp.option, TRUNCATE, op); 1494 if (pp.option & TRUNCATE) 1495 { 1496 Hash_bucket_t* b; 1497 Hash_bucket_t* p; 1498 Hash_position_t* pos; 1499 Hash_table_t* tab; 1500 1501 pp.truncate = op; 1502 tab = pp.symtab; 1503 pp.symtab = hashalloc(NiL, HASH_set, tab ? HASH_ALLOCATE : 0, HASH_compare, trunccomp, HASH_hash, trunchash, HASH_name, "truncate", 0); 1504 if (tab && (pos = hashscan(tab, 0))) 1505 { 1506 if (p = hashnext(pos)) 1507 do 1508 { 1509 b = hashnext(pos); 1510 hashlook(pp.symtab, (char*)p, HASH_BUCKET|HASH_INSTALL, NiL); 1511 } while (p = b); 1512 hashdone(pos); 1513 } 1514 } 1515 else 1516 pp.truncate = 0; 1517 break; 1518 case PP_VENDOR: 1519 p = va_arg(ap, char*); 1520 c = va_arg(ap, int) != 0; 1521 if (!p || !*p) 1522 for (dp = pp.firstdir; dp; dp = dp->next) 1523 dp->type &= ~TYPE_VENDOR; 1524 else if (streq(p, "-")) 1525 { 1526 for (dp = pp.firstdir; dp; dp = dp->next) 1527 if (c) 1528 dp->type |= TYPE_VENDOR; 1529 else 1530 dp->type &= ~TYPE_VENDOR; 1531 } 1532 else if (!stat((pathcanon(p, 0), p), &st)) 1533 { 1534 c = 0; 1535 for (dp = pp.firstdir; dp; dp = dp->next) 1536 { 1537 if (!c && ((dp->type & TYPE_VENDOR) || dp->name && SAMEID(&dp->id, &st))) 1538 c = 1; 1539 if (c) 1540 dp->type |= TYPE_VENDOR; 1541 else 1542 dp->type &= ~TYPE_VENDOR; 1543 } 1544 } 1545 break; 1546 case PP_WARN: 1547 set(&pp.state, WARN, va_arg(ap, int)); 1548 break; 1549 before: 1550 error(3, "ppop(%d): preprocessor operation must be done before PP_INIT", op); 1551 break; 1552 default: 1553 error(3, "ppop(%d): invalid preprocessor operation", op); 1554 break; 1555 } 1556 va_end(ap); 1557 } 1558