1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1986-2007 AT&T Knowledge Ventures * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Knowledge Ventures * 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 control directive support 26 */ 27 28 #include "pplib.h" 29 30 #include <regex.h> 31 32 #define TOKOP_DUP (1<<0) 33 #define TOKOP_STRING (1<<1) 34 #define TOKOP_UNSET (1<<2) 35 36 struct edit 37 { 38 struct edit* next; 39 regex_t re; 40 }; 41 42 struct map 43 { 44 struct map* next; 45 regex_t re; 46 struct edit* edit; 47 }; 48 49 #define RESTORE (COLLECTING|CONDITIONAL|DEFINITION|DIRECTIVE|DISABLE|EOF2NL|HEADER|NOSPACE|NOVERTICAL|PASSEOF|STRIP) 50 51 /* 52 * common predicate assertion operations 53 * op is DEFINE or UNDEF 54 */ 55 56 static void 57 assert(int op, char* pred, char* args) 58 { 59 register struct pplist* a; 60 register struct ppsymbol* sym; 61 register struct pplist* p; 62 register struct pplist* q; 63 64 if (!args) switch (op) 65 { 66 case DEFINE: 67 goto mark; 68 case UNDEF: 69 a = 0; 70 goto unmark; 71 } 72 if (a = (struct pplist*)hashget(pp.prdtab, pred)) 73 { 74 p = 0; 75 q = a; 76 while (q) 77 { 78 if (streq(q->value, args)) 79 { 80 if (op == DEFINE) return; 81 q = q->next; 82 if (p) p->next = q; 83 else a = q; 84 } 85 else 86 { 87 p = q; 88 q = q->next; 89 } 90 } 91 if (op == UNDEF) 92 { 93 unmark: 94 hashput(pp.prdtab, pred, a); 95 if (sym = ppsymref(pp.symtab, pred)) 96 sym->flags &= ~SYM_PREDICATE; 97 return; 98 } 99 } 100 if (op == DEFINE) 101 { 102 p = newof(0, struct pplist, 1, 0); 103 p->next = a; 104 p->value = strdup(args); 105 hashput(pp.prdtab, NiL, p); 106 mark: 107 if ((pp.state & COMPILE) && pp.truncate) return; 108 if (sym = ppsymset(pp.symtab, pred)) 109 sym->flags |= SYM_PREDICATE; 110 } 111 } 112 113 /* 114 * tokenize string ppop() 115 * 116 * op PP_* op 117 * name option name 118 * s string of option values 119 * n option sense 120 * flags TOKOP_* flags 121 */ 122 123 static void 124 tokop(int op, char* name, register char* s, register int n, int flags) 125 { 126 register int c; 127 register char* t; 128 129 if (!(flags & TOKOP_UNSET) && !n) error(2, "%s: option cannot be unset", name); 130 else if (!s) ppop(op, s, n); 131 else if (flags & TOKOP_STRING) 132 { 133 PUSH_LINE(s); 134 for (;;) 135 { 136 pp.state &= ~NOSPACE; 137 c = pplex(); 138 pp.state |= NOSPACE; 139 if (!c) break; 140 if (c != ' ') 141 ppop(op, (flags & TOKOP_DUP) ? strdup(pp.token) : pp.token, n); 142 } 143 POP_LINE(); 144 } 145 else do 146 { 147 while (*s == ' ') s++; 148 for (t = s; *t && *t != ' '; t++); 149 if (*t) *t++ = 0; 150 else t = 0; 151 if (*s) ppop(op, (flags & TOKOP_DUP) ? strdup(s) : s, n); 152 } while (s = t); 153 } 154 155 /* 156 * return symbol pointer for next token macro (re)definition 157 */ 158 159 static struct ppsymbol* 160 macsym(int tok) 161 { 162 register struct ppsymbol* sym; 163 164 if (tok != T_ID) 165 { 166 error(2, "%s: invalid macro name", pptokstr(pp.token, 0)); 167 return 0; 168 } 169 sym = pprefmac(pp.token, REF_CREATE); 170 if ((sym->flags & SYM_FINAL) && (pp.mode & HOSTED)) return 0; 171 if (sym->flags & (SYM_ACTIVE|SYM_READONLY)) 172 { 173 if (!(pp.option & ALLPOSSIBLE)) 174 error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active"); 175 return 0; 176 } 177 if (!sym->macro) sym->macro = newof(0, struct ppmacro, 1, 0); 178 return sym; 179 } 180 181 /* 182 * get one space canonical pplex() line, sans '\n', and place in p 183 * x is max+1 pos in p 184 * 0 returned if line too large 185 * otherwise end of p ('\0') returned 186 */ 187 188 static char* 189 getline(register char* p, char* x, int disable) 190 { 191 register int c; 192 register char* s; 193 char* b; 194 long restore; 195 196 restore = pp.state & (NOSPACE|STRIP); 197 pp.state &= ~(NEWLINE|NOSPACE|STRIP); 198 pp.state |= EOF2NL; 199 b = p; 200 while ((c = pplex()) != '\n') 201 { 202 if (disable) 203 { 204 if (c == ' ') 205 /*ignore*/; 206 else if (disable == 1) 207 disable = (c == T_ID && streq(pp.token, pp.pass)) ? 2 : 0; 208 else 209 { 210 disable = 0; 211 if (c == ':') 212 pp.state |= DISABLE; 213 } 214 } 215 s = pp.token; 216 while (*p = *s++) 217 if (++p >= x) 218 { 219 p = 0; 220 goto done; 221 } 222 } 223 if (p > b && *(p - 1) == ' ') 224 p--; 225 if (p >= x) 226 p = 0; 227 else 228 *p = 0; 229 done: 230 pp.state &= ~(NOSPACE|STRIP); 231 pp.state |= restore; 232 return p; 233 } 234 235 /* 236 * regex error handler 237 */ 238 239 void 240 regfatal(regex_t* p, int level, int code) 241 { 242 char buf[128]; 243 244 regerror(code, p, buf, sizeof(buf)); 245 regfree(p); 246 error(level, "regular expression: %s", buf); 247 } 248 249 /* 250 * process a single directive line 251 */ 252 253 int 254 ppcontrol(void) 255 { 256 register char* p; 257 register int c; 258 register int n; 259 register char* s; 260 register struct ppmacro* mac; 261 register struct ppsymbol* sym; 262 struct edit* edit; 263 struct map* map; 264 struct ppfile* fp; 265 int o; 266 int directive; 267 long restore; 268 struct pptuple* rp; 269 struct pptuple* tp; 270 char* v; 271 int emitted; 272 273 union 274 { 275 struct map* best; 276 struct ppinstk* inp; 277 struct pplist* list; 278 char* string; 279 struct ppsymbol* symbol; 280 int type; 281 PPLINESYNC linesync; 282 } var; 283 284 static char __va_args__[] = "__VA_ARGS__"; 285 static int i0; 286 static int i1; 287 static int i2; 288 static int i3; 289 static int i4; 290 291 static long n1; 292 static long n2; 293 static long n3; 294 295 static char* p0; 296 static char* p1; 297 static char* p2; 298 static char* p3; 299 static char* p4; 300 static char* p5; 301 static char* p6; 302 303 static struct ppmacro old; 304 static char* formargs[MAXFORMALS]; 305 #if MACKEYARGS 306 static char* formvals[MAXFORMALS]; 307 #endif 308 309 emitted = 0; 310 if (pp.state & SKIPCONTROL) pp.level--; 311 restore = (pp.state & RESTORE)|NEWLINE; 312 if (pp.state & PASSTHROUGH) restore |= DISABLE; 313 else restore &= ~DISABLE; 314 pp.state &= ~(NEWLINE|RESTORE|SKIPCONTROL); 315 pp.state |= DIRECTIVE|DISABLE|EOF2NL|NOSPACE|NOVERTICAL; 316 #if COMPATIBLE 317 if ((pp.state & (COMPATIBILITY|STRICT)) == COMPATIBILITY || (pp.mode & HOSTED)) pp.state &= ~NOVERTICAL; 318 #else 319 if (pp.mode & HOSTED) pp.state &= ~NOVERTICAL; 320 #endif 321 switch (c = pplex()) 322 { 323 case T_DECIMAL: 324 case T_OCTAL: 325 if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 326 error(1, "# <line> [ \"<file>\" [ <type> ] ]: non-standard directive"); 327 directive = INCLUDE; 328 goto linesync; 329 case T_ID: 330 switch (directive = (int)hashref(pp.dirtab, pp.token)) 331 { 332 case ELIF: 333 else_if: 334 if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev) 335 goto eatdirective; 336 if (pp.control <= pp.in->control) 337 { 338 error(2, "no matching #%s for #%s", dirname(IF), dirname(ELIF)); 339 goto eatdirective; 340 } 341 if (pp.control == (pp.in->control + 1)) pp.in->flags |= IN_noguard; 342 if (*pp.control & HADELSE) 343 { 344 error(2, "invalid #%s after #%s", dirname(ELIF), dirname(ELSE)); 345 *pp.control |= SKIP; 346 goto eatdirective; 347 } 348 if (*pp.control & KEPT) 349 { 350 *pp.control |= SKIP; 351 goto eatdirective; 352 } 353 if (directive == IFDEF || directive == IFNDEF) 354 { 355 *pp.control &= ~SKIP; 356 goto else_ifdef; 357 } 358 conditional: 359 if (ppexpr(&i1)) 360 { 361 *pp.control &= ~SKIP; 362 *pp.control |= KEPT; 363 } 364 else *pp.control |= SKIP; 365 c = (pp.state & NEWLINE) ? '\n' : ' '; 366 goto eatdirective; 367 case ELSE: 368 if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev) 369 goto eatdirective; 370 if ((pp.option & ELSEIF) && (c = pplex()) == T_ID && ((n = (int)hashref(pp.dirtab, pp.token)) == IF || n == IFDEF || n == IFNDEF)) 371 { 372 error(1, "#%s %s is non-standard -- use #%s", dirname(directive), dirname(n), dirname(ELIF)); 373 directive = n; 374 goto else_if; 375 } 376 if (pp.control <= pp.in->control) error(2, "no matching #%s for #%s", dirname(IF), dirname(ELSE)); 377 else 378 { 379 if (pp.control == (pp.in->control + 1)) pp.in->flags |= IN_noguard; 380 if (!(*pp.control & KEPT)) 381 { 382 *pp.control &= ~SKIP; 383 *pp.control |= HADELSE|KEPT; 384 } 385 else 386 { 387 if (*pp.control & HADELSE) error(2, "more than one #%s for #%s", dirname(ELSE), dirname(IF)); 388 *pp.control |= HADELSE|SKIP; 389 } 390 } 391 goto enddirective; 392 case ENDIF: 393 if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev) 394 goto eatdirective; 395 if (pp.control <= pp.in->control) error(2, "no matching #%s for #%s", dirname(IF), dirname(ENDIF)); 396 else if (--pp.control == pp.in->control && pp.in->symbol) 397 { 398 if (pp.in->flags & IN_endguard) pp.in->flags |= IN_noguard; 399 else 400 { 401 pp.in->flags &= ~IN_tokens; 402 pp.in->flags |= IN_endguard; 403 } 404 } 405 goto enddirective; 406 case IF: 407 case IFDEF: 408 case IFNDEF: 409 if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev) 410 goto eatdirective; 411 pushcontrol(); 412 SETIFBLOCK(pp.control); 413 if (*pp.control & SKIP) 414 { 415 *pp.control |= KEPT; 416 goto eatdirective; 417 } 418 if (directive == IF) goto conditional; 419 else_ifdef: 420 if ((c = pplex()) == T_ID) 421 { 422 sym = pprefmac(pp.token, REF_IF); 423 if (directive == IFNDEF && pp.control == pp.in->control + 1) 424 { 425 if (pp.in->flags & (IN_defguard|IN_endguard)) 426 pp.in->flags |= IN_noguard; 427 else 428 { 429 pp.in->flags |= IN_defguard; 430 if (!(pp.in->flags & IN_tokens)) 431 pp.in->symbol = sym ? sym : pprefmac(pp.token, REF_CREATE); 432 } 433 } 434 } 435 else 436 { 437 sym = 0; 438 if (!(pp.mode & HOSTED)) 439 error(1, "%s: invalid macro name", pptokstr(pp.token, 0)); 440 } 441 *pp.control |= ((sym != 0) == (directive == IFDEF)) ? KEPT : SKIP; 442 goto enddirective; 443 case INCLUDE: 444 if (*pp.control & SKIP) 445 { 446 pp.state |= HEADER; 447 c = pplex(); 448 pp.state &= ~HEADER; 449 goto eatdirective; 450 } 451 pp.state &= ~DISABLE; 452 pp.state |= HEADER|STRIP; 453 switch (c = pplex()) 454 { 455 case T_STRING: 456 p = pp.token; 457 do pp.token = pp.toknxt; while ((c = pplex()) == T_STRING); 458 *pp.token = 0; 459 pp.token = p; 460 /*FALLTHROUGH*/ 461 case T_HEADER: 462 header: 463 if (!*pp.token) 464 { 465 error(2, "#%s: null file name", dirname(INCLUDE)); 466 break; 467 } 468 if (*pp.token == '/' && !(pp.mode & (HOSTED|RELAX))) 469 error(1, "#%s: reference to %s is not portable", dirname(INCLUDE), pp.token); 470 n = ppsearch(pp.token, c, SEARCH_INCLUDE); 471 break; 472 case '<': 473 /* 474 * HEADEREXPAND|HEADEREXPANDALL gets us here 475 */ 476 477 if (!(p = pp.hdrbuf) && !(p = pp.hdrbuf = newof(0, char, MAXTOKEN, 0))) 478 error(3, "out of space"); 479 pp.state &= ~NOSPACE; 480 while ((c = pplex()) && c != '>') 481 { 482 v = p + 1; 483 STRCOPY(p, pp.token, s); 484 if (p == v && *(p - 1) == ' ' && pp.in->type != IN_MACRO) 485 p--; 486 } 487 pp.state |= NOSPACE; 488 *p++ = 0; 489 memcpy(pp.token, pp.hdrbuf, p - pp.hdrbuf); 490 c = T_HEADER; 491 goto header; 492 default: 493 error(2, "#%s: \"...\" or <...> argument expected", dirname(INCLUDE)); 494 goto eatdirective; 495 } 496 goto enddirective; 497 case 0: 498 { 499 regmatch_t match[10]; 500 501 /*UNDENT*/ 502 p = pp.valbuf; 503 *p++ = '#'; 504 STRCOPY(p, pp.token, s); 505 p0 = p; 506 pp.mode |= EXPOSE; 507 pp.state |= HEADER; 508 p6 = getline(p, &pp.valbuf[MAXTOKEN], 0); 509 pp.state &= ~HEADER; 510 pp.mode &= ~EXPOSE; 511 if (!p6) 512 { 513 *p0 = 0; 514 error(2, "%s: directive too long", pp.valbuf); 515 c = 0; 516 goto eatdirective; 517 } 518 p1 = p2 = p3 = p4 = 0; 519 p5 = *p ? p + 1 : 0; 520 checkmap: 521 i0 = *p0; 522 p = pp.valbuf; 523 var.best = 0; 524 n = 0; 525 for (map = (struct map*)pp.maps; map; map = map->next) 526 if (!(i1 = regexec(&map->re, p, elementsof(match), match, 0))) 527 { 528 if ((c = match[0].rm_eo - match[0].rm_so) > n) 529 { 530 n = c; 531 var.best = map; 532 } 533 } 534 else if (i1 != REG_NOMATCH) 535 regfatal(&map->re, 3, i1); 536 c = '\n'; 537 if (map = var.best) 538 { 539 if ((pp.state & (STRICT|WARN)) && !(pp.mode & (HOSTED|RELAX))) 540 { 541 *p0 = 0; 542 if (!(pp.state & WARN) || strcmp(p + 1, dirname(PRAGMA))) 543 error(1, "%s: non-standard directive", p); 544 *p0 = i0; 545 } 546 if (!(*pp.control & SKIP)) 547 { 548 n = 0; 549 for (edit = map->edit; edit; edit = edit->next) 550 if (!(i0 = regexec(&edit->re, p, elementsof(match), match, 0))) 551 { 552 n++; 553 if (i0 = regsubexec(&edit->re, p, elementsof(match), match)) 554 regfatal(&edit->re, 3, i0); 555 p = edit->re.re_sub->re_buf; 556 if (edit->re.re_sub->re_flags & REG_SUB_STOP) 557 break; 558 } 559 else if (i0 != REG_NOMATCH) 560 regfatal(&edit->re, 3, i0); 561 if (n && *p) 562 { 563 p1 = s = oldof(0, char, 0, strlen(p) + 32); 564 while (*s = *p++) s++; 565 debug((-4, "map: %s", p1)); 566 *s++ = '\n'; 567 *s = 0; 568 error_info.line++; 569 PUSH_RESCAN(p1); 570 error_info.line--; 571 directive = LINE; 572 } 573 } 574 goto donedirective; 575 } 576 if (directive != PRAGMA && (!(*pp.control & SKIP) || !(pp.mode & (HOSTED|RELAX)))) 577 { 578 *p0 = 0; 579 error(1, "%s: unknown directive", pptokstr(pp.valbuf, 0)); 580 *p0 = i0; 581 } 582 pass: 583 if (!(*pp.control & SKIP) && pp.pragma && !(pp.state & NOTEXT) && (directive == PRAGMA || !(pp.mode & INIT))) 584 { 585 *p0 = 0; 586 if (p2) *p2 = 0; 587 if (p4) 588 { 589 if (p4 == p5) 590 { 591 p5 = strcpy(pp.tmpbuf, p5); 592 if (p = strchr(p5, MARK)) 593 { 594 s = p; 595 while (*p) 596 if ((*s++ = *p++) == MARK && *p == MARK) p++; 597 *s = 0; 598 } 599 } 600 *p4 = 0; 601 } 602 if (p = (char*)memchr(pp.valbuf + 1, MARK, p6 - pp.valbuf - 1)) 603 { 604 s = p; 605 while (p < p6) switch (*s++ = *p++) 606 { 607 case 0: 608 s = p; 609 break; 610 case MARK: 611 p++; 612 break; 613 } 614 *s = 0; 615 } 616 (*pp.pragma)(pp.valbuf + 1, p1, p3, p5, (pp.state & COMPILE) || (pp.mode & INIT) != 0); 617 emitted = 1; 618 } 619 goto donedirective; 620 621 /*INDENT*/ 622 } 623 } 624 if (*pp.control & SKIP) goto eatdirective; 625 switch (directive) 626 { 627 #if MACDEF 628 case ENDMAC: 629 c = pplex(); 630 error(2, "no matching #%s for #%s", dirname(MACDEF), dirname(ENDMAC)); 631 goto enddirective; 632 #endif 633 #if MACDEF 634 case MACDEF: 635 if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 636 error(1, "#%s: non-standard directive", pp.token); 637 /*FALLTHROUGH*/ 638 #endif 639 case DEFINE: 640 n2 = error_info.line; 641 if ((c = pplex()) == '#' && directive == DEFINE) 642 goto assertion; 643 if (c == '<') 644 { 645 n = 1; 646 c = pplex(); 647 } 648 else 649 n = 0; 650 if (!(sym = macsym(c))) 651 goto eatdirective; 652 if (pp.truncate) 653 ppfsm(FSM_MACRO, pp.token); 654 mac = sym->macro; 655 if ((pp.option & ALLPOSSIBLE) && !pp.in->prev->prev && mac->value) 656 goto eatdirective; 657 if (n) 658 goto tuple; 659 old = *mac; 660 i0 = sym->flags; 661 sym->flags &= ~(SYM_BUILTIN|SYM_EMPTY|SYM_FINAL|SYM_FUNCTION|SYM_INIT|SYM_INITIAL|SYM_MULTILINE|SYM_NOEXPAND|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 662 #if MACDEF 663 if (directive == MACDEF) 664 sym->flags |= SYM_MULTILINE; 665 #endif 666 mac->arity = 0; 667 mac->formals = 0; 668 mac->value = 0; 669 pp.state &= ~NOSPACE; 670 pp.state |= DEFINITION|NOEXPAND; 671 switch (c = pplex()) 672 { 673 case '(': 674 sym->flags |= SYM_FUNCTION; 675 pp.state |= NOSPACE; 676 #if MACKEYARGS 677 if (pp.option & KEYARGS) 678 { 679 n = 2 * MAXTOKEN; 680 p = mac->formals = oldof(0, char, 0, n); 681 if ((c = pplex()) == T_ID) for (;;) 682 { 683 if (mac->arity < MAXFORMALS) 684 { 685 if (mac->arity) p++; 686 formargs[mac->arity] = p; 687 STRAPP(p, pp.token, s); 688 formvals[mac->arity++] = p1 = p; 689 if (mac->arity == 1) *p++ = ' '; 690 *p++ = ' '; 691 *p = 0; 692 } 693 else error(2, "%s: formal argument %s ignored", sym->name, pp.token); 694 switch (c = pplex()) 695 { 696 case '=': 697 c = pplex(); 698 break; 699 case ',': 700 break; 701 default: 702 goto endformals; 703 } 704 pp.state &= ~NOSPACE; 705 p0 = 0; 706 for (;;) 707 { 708 switch (c) 709 { 710 case '\n': 711 goto endformals; 712 case '(': 713 p0++; 714 break; 715 case ')': 716 if (!p0--) 717 { 718 if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') *--p = 0; 719 goto endformals; 720 } 721 break; 722 case ',': 723 if (!p0) 724 { 725 if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') *--p = 0; 726 goto nextformal; 727 } 728 break; 729 case ' ': 730 if (p > formvals[mac->arity - 1] && *(p - 1) == ' ') continue; 731 break; 732 } 733 STRCOPY(p, pp.token, s); 734 if (p > &mac->formals[n - MAXTOKEN] && (s = newof(mac->formals, char, n += MAXTOKEN, 0)) != mac->formals) 735 { 736 n1 = s - mac->formals; 737 for (n = 0; n < mac->arity; n++) 738 { 739 formargs[n] += n1; 740 formvals[n] += n1; 741 } 742 c = p - mac->formals; 743 mac->formals = s; 744 p = mac->formals + c; 745 } 746 c = pplex(); 747 } 748 nextformal: 749 pp.state |= NOSPACE; 750 if ((c = pplex()) != T_ID) 751 { 752 c = ','; 753 break; 754 } 755 } 756 endformals: /*NOP*/; 757 } 758 else 759 #endif 760 { 761 p = mac->formals = oldof(0, char, 0, MAXFORMALS * (MAXID + 1)); 762 c = pplex(); 763 #if COMPATIBLE 764 if ((pp.state & COMPATIBILITY) && c == ',') 765 { 766 if ((pp.state & WARN) && !(pp.mode & HOSTED)) 767 error(1, "%s: macro formal argument expected", sym->name); 768 while ((c = pplex()) == ','); 769 } 770 #endif 771 for (;;) 772 { 773 if (c == T_VARIADIC) 774 { 775 if (sym->flags & SYM_VARIADIC) 776 error(2, "%s: %s: duplicate macro formal argument", sym->name, pp.token); 777 sym->flags |= SYM_VARIADIC; 778 v = __va_args__; 779 } 780 else if (c == T_ID) 781 { 782 v = pp.token; 783 if (sym->flags & SYM_VARIADIC) 784 error(2, "%s: %s: macro formal argument cannot follow ...", sym->name, v); 785 else if (streq(v, __va_args__)) 786 error(2, "%s: %s: invalid macro formal argument", sym->name, v); 787 } 788 else 789 break; 790 if (mac->arity < MAXFORMALS) 791 { 792 for (n = 0; n < mac->arity; n++) 793 if (streq(formargs[n], v)) 794 error(2, "%s: %s: duplicate macro formal argument", sym->name, v); 795 formargs[mac->arity++] = p; 796 STRAPP(p, v, s); 797 } 798 else 799 error(2, "%s: %s: macro formal argument ignored", sym->name, v); 800 if ((c = pplex()) == ',') 801 { 802 c = pplex(); 803 #if COMPATIBLE 804 if ((pp.state & COMPATIBILITY) && c == ',') 805 { 806 if ((pp.state & WARN) && !(pp.mode & HOSTED)) 807 error(1, "%s: macro formal argument expected", sym->name); 808 while ((c = pplex()) == ','); 809 } 810 #endif 811 } 812 else if (c != T_VARIADIC) 813 break; 814 else 815 { 816 if (sym->flags & SYM_VARIADIC) 817 error(2, "%s: %s: duplicate macro formal argument", sym->name, pp.token); 818 sym->flags |= SYM_VARIADIC; 819 c = pplex(); 820 break; 821 } 822 } 823 if (mac->arity && (s = newof(mac->formals, char, p - mac->formals, 0)) != mac->formals) 824 { 825 n1 = s - mac->formals; 826 for (n = 0; n < mac->arity; n++) 827 formargs[n] += n1; 828 mac->formals = s; 829 } 830 } 831 if (!mac->arity) 832 { 833 free(mac->formals); 834 mac->formals = 0; 835 } 836 switch (c) 837 { 838 case ')': 839 #if MACKEYARGS 840 pp.state |= NOEXPAND|NOSPACE; 841 #else 842 pp.state |= NOEXPAND; 843 #endif 844 c = pplex(); 845 break; 846 default: 847 error(2, "%s: invalid macro formal argument list", sym->name); 848 if (mac->formals) 849 { 850 free(mac->formals); 851 mac->formals = 0; 852 mac->arity = 0; 853 } 854 free(mac); 855 sym->macro = 0; 856 goto eatdirective; 857 } 858 pp.state &= ~NOSPACE; 859 break; 860 case ' ': 861 case '\t': 862 c = pplex(); 863 break; 864 } 865 n = 2 * MAXTOKEN; 866 #if MACKEYARGS 867 p1 = p; 868 #endif 869 p = mac->value = oldof(0, char, 0, n); 870 var.type = 0; 871 n1 = 0; 872 #if MACDEF 873 i2 = i3 = 0; 874 n3 = pp.state; 875 #endif 876 if ((pp.option & PLUSPLUS) && (pp.state & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY) 877 switch (c) 878 { 879 case '+': 880 case '-': 881 case '&': 882 case '|': 883 case '<': 884 case '>': 885 case ':': 886 case '=': 887 *p++ = ' '; 888 break; 889 } 890 o = 0; 891 for (;;) 892 { 893 switch (c) 894 { 895 case T_ID: 896 for (c = 0; c < mac->arity; c++) 897 if (streq(formargs[c], pp.token)) 898 { 899 #if COMPATIBLE 900 if (!(pp.state & COMPATIBILITY)) 901 #endif 902 if (var.type != TOK_TOKCAT && p > mac->value && *(p - 1) != ' ' && !(pp.option & PRESERVE)) *p++ = ' '; 903 *p++ = MARK; 904 #if COMPATIBLE 905 if ((pp.state & (COMPATIBILITY|TRANSITION)) == COMPATIBILITY) *p++ = 'C'; 906 else 907 #endif 908 *p++ = (n1 || var.type == TOK_TOKCAT) ? 'C' : 'A'; 909 *p++ = c + ARGOFFSET; 910 var.type = TOK_FORMAL|TOK_ID; 911 c = '>'; 912 goto checkvalue; 913 } 914 if (var.type == TOK_BUILTIN) switch ((int)hashget(pp.strtab, pp.token)) 915 { 916 case V_DEFAULT: 917 case V_EMPTY: 918 sym->flags |= SYM_EMPTY; 919 break; 920 } 921 else if (pp.hiding && (var.symbol = ppsymref(pp.symtab, pp.token)) && var.symbol->hidden) 922 { 923 for (var.inp = pp.in; var.inp->type != IN_FILE && var.inp->prev; var.inp = var.inp->prev); 924 p += sfsprintf(p, MAXTOKEN, "_%d_%s_hIDe", var.inp->hide, pp.token); 925 var.type = TOK_ID; 926 goto checkvalue; 927 } 928 var.type = TOK_ID; 929 break; 930 case '#': 931 var.type = 0; 932 #if MACDEF 933 if (!(sym->flags & (SYM_FUNCTION|SYM_MULTILINE))) break; 934 #else 935 if (!(sym->flags & SYM_FUNCTION)) break; 936 #endif 937 pp.state |= NOSPACE; 938 c = pplex(); 939 if (c == '@') 940 { 941 c = pplex(); 942 i4 = 'S'; 943 } 944 else i4 = 'Q'; 945 pp.state &= ~NOSPACE; 946 if (c != T_ID) c = mac->arity; 947 else for (c = 0; c < mac->arity; c++) 948 if (streq(formargs[c], pp.token)) 949 break; 950 if (c >= mac->arity) 951 { 952 #if MACDEF 953 if (sym->flags & SYM_MULTILINE) 954 { 955 if (n3 & NEWLINE) 956 { 957 pp.state &= ~NOEXPAND; 958 switch ((int)hashref(pp.dirtab, pp.token)) 959 { 960 case ENDMAC: 961 if (!i2--) goto gotdefinition; 962 break; 963 case INCLUDE: 964 /* PARSE HEADER constant */ 965 break; 966 case MACDEF: 967 i2++; 968 break; 969 } 970 *p++ = '#'; 971 } 972 } 973 else 974 #endif 975 #if COMPATIBLE 976 if (pp.state & COMPATIBILITY) *p++ = '#'; 977 else 978 #endif 979 error(2, "# must precede a formal parameter"); 980 } 981 else 982 { 983 if (p > mac->value && ppisidig(*(p - 1)) && !(pp.option & PRESERVE)) *p++ = ' '; 984 *p++ = MARK; 985 *p++ = i4; 986 *p++ = c + ARGOFFSET; 987 goto checkvalue; 988 } 989 break; 990 case T_TOKCAT: 991 if (p <= mac->value) error(2, "%s lhs operand omitted", pp.token); 992 else 993 { 994 if (*(p - 1) == ' ') p--; 995 if (var.type == (TOK_FORMAL|TOK_ID)) *(p - 2) = 'C'; 996 } 997 pp.state |= NOSPACE; 998 c = pplex(); 999 pp.state &= ~NOSPACE; 1000 if (c == '\n') error(2, "%s rhs operand omitted", pptokchr(T_TOKCAT)); 1001 var.type = TOK_TOKCAT; 1002 continue; 1003 case '(': 1004 if (*pp.token == '#') 1005 { 1006 var.type = TOK_BUILTIN; 1007 n1++; 1008 } 1009 else 1010 { 1011 var.type = 0; 1012 if (n1) n1++; 1013 } 1014 break; 1015 case ')': 1016 var.type = 0; 1017 if (n1) n1--; 1018 break; 1019 case T_STRING: 1020 case T_CHARCONST: 1021 pp.state &= ~NOEXPAND; 1022 var.type = 0; 1023 if (strchr(pp.token, MARK)) pp.state &= ~NOEXPAND; 1024 #if COMPATIBLE 1025 /*UNDENT*/ 1026 1027 if ((sym->flags & SYM_FUNCTION) && (pp.state & (COMPATIBILITY|TRANSITION))) 1028 { 1029 char* v; 1030 1031 s = pp.token; 1032 for (;;) 1033 { 1034 if (!*s) goto checkvalue; 1035 if (ppisid(*s)) 1036 { 1037 v = s; 1038 while (ppisid(*++s)); 1039 i1 = *s; 1040 *s = 0; 1041 for (c = 0; c < mac->arity; c++) 1042 if (streq(formargs[c], v)) 1043 { 1044 *p++ = MARK; 1045 *p++ = 'C'; 1046 *p++ = c + ARGOFFSET; 1047 if (!(pp.mode & HOSTED) && (!(pp.state & COMPATIBILITY) || (pp.state & WARN))) switch (*pp.token) 1048 { 1049 case '"': 1050 error(1, "use the # operator to \"...\" quote macro arguments"); 1051 break; 1052 case '\'': 1053 error(1, "macro arguments should be '...' quoted before substitution"); 1054 break; 1055 } 1056 goto quotearg; 1057 } 1058 STRCOPY2(p, v); 1059 quotearg: 1060 *s = i1; 1061 } 1062 else *p++ = *s++; 1063 } 1064 } 1065 /*INDENT*/ 1066 #endif 1067 break; 1068 case '\n': 1069 #if MACDEF 1070 if (sym->flags & SYM_MULTILINE) 1071 { 1072 if (pp.state & EOF2NL) 1073 { 1074 error_info.line++; 1075 pp.state |= HIDDEN; 1076 pp.hidden++; 1077 var.type = 0; 1078 if (!i3++) 1079 goto checkvalue; 1080 break; 1081 } 1082 pp.state |= EOF2NL; 1083 error(2, "%s: missing #%s", sym->name, dirname(ENDMAC)); 1084 } 1085 #endif 1086 goto gotdefinition; 1087 case 0: 1088 c = '\n'; 1089 goto gotdefinition; 1090 #if COMPATIBLE 1091 case ' ': 1092 if (pp.state & COMPATIBILITY) var.type = 0; 1093 if (pp.option & PRESERVE) break; 1094 if (p > mac->value && *(p - 1) != ' ') *p++ = ' '; 1095 goto checkvalue; 1096 case '\t': 1097 if (var.type & TOK_ID) 1098 { 1099 while ((c = pplex()) == '\t'); 1100 if (c == T_ID) 1101 { 1102 if (var.type == (TOK_FORMAL|TOK_ID)) *(p - 2) = 'C'; 1103 var.type = TOK_TOKCAT; 1104 if (pp.state & WARN) error(1, "use the ## operator to concatenate macro arguments"); 1105 } 1106 else var.type = 0; 1107 continue; 1108 } 1109 var.type = 0; 1110 if (pp.option & PRESERVE) break; 1111 if (p > mac->value && *(p - 1) != ' ') *p++ = ' '; 1112 goto checkvalue; 1113 #endif 1114 case MARK: 1115 pp.state &= ~NOEXPAND; 1116 /*FALLTHROUGH*/ 1117 1118 default: 1119 var.type = 0; 1120 break; 1121 } 1122 STRCOPY(p, pp.token, s); 1123 checkvalue: 1124 o = c; 1125 if (p > &mac->value[n - MAXTOKEN] && (s = newof(mac->value, char, n += MAXTOKEN, 0)) != mac->value) 1126 { 1127 c = p - mac->value; 1128 mac->value = s; 1129 p = mac->value + c; 1130 } 1131 #if MACDEF 1132 n3 = pp.state; 1133 #endif 1134 c = pplex(); 1135 } 1136 gotdefinition: 1137 while (p > mac->value && *(p - 1) == ' ') p--; 1138 if (p > mac->value && (pp.option & PLUSPLUS) && (pp.state & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY) 1139 switch (o) 1140 { 1141 case '+': 1142 case '-': 1143 case '&': 1144 case '|': 1145 case '<': 1146 case '>': 1147 case ':': 1148 case '=': 1149 *p++ = ' '; 1150 break; 1151 } 1152 *p = 0; 1153 #if MACKEYARGS 1154 if (!mac->arity) /* ok */; 1155 else if (pp.option & KEYARGS) 1156 { 1157 p0 = mac->formals; 1158 mac->formkeys = newof(0, struct ppkeyarg, n, p1 - p0 + 1); 1159 s = (char*)&mac->formkeys[mac->arity]; 1160 (void)memcpy(s, p0, p1 - p0 + 1); 1161 free(p0); 1162 for (n = 0; n < mac->arity; n++) 1163 { 1164 mac->formkeys[n].name = s + (formargs[n] - p0); 1165 mac->formkeys[n].value = s + (formvals[n] - p0); 1166 } 1167 } 1168 else 1169 #endif 1170 for (n = 1; n < mac->arity; n++) 1171 *(formargs[n] - 1) = ','; 1172 if (old.value) 1173 { 1174 if ((i0 & SYM_FUNCTION) != (sym->flags & SYM_FUNCTION) || old.arity != mac->arity || !streq(old.value, mac->value)) goto redefined; 1175 if (!old.formals) 1176 { 1177 if (mac->formals) goto redefined; 1178 } 1179 else if (mac->formals) 1180 { 1181 #if MACKEYARGS 1182 if (pp.option & KEYARGS) 1183 { 1184 for (n = 0; n < mac->arity; n++) 1185 if (!streq(mac->formkeys[n].name, old.formkeys[n].name) || !streq(mac->formkeys[n].value, old.formkeys[n].value)) 1186 goto redefined; 1187 } 1188 else 1189 #endif 1190 if (!streq(mac->formals, old.formals)) goto redefined; 1191 } 1192 #if MACKEYARGS 1193 if (pp.option & KEYARGS) 1194 { 1195 if (mac->formkeys) free(mac->formkeys); 1196 mac->formkeys = old.formkeys; 1197 } 1198 else 1199 #endif 1200 { 1201 if (mac->formals) free(mac->formals); 1202 mac->formals = old.formals; 1203 } 1204 free(mac->value); 1205 mac->value = old.value; 1206 goto benign; 1207 redefined: 1208 if (!(pp.mode & HOSTED) || !(i0 & SYM_INITIAL)) 1209 error(1, "%s redefined", sym->name); 1210 #if MACKEYARGS 1211 if ((pp.option & KEYARGS) && mac->formkeys) 1212 free(mac->formkeys); 1213 #endif 1214 #if MACKEYARGS 1215 if (!(pp.option & KEYARGS)) 1216 #endif 1217 if (old.formals) free(old.formals); 1218 free(old.value); 1219 } 1220 else if (!pp.truncate) ppfsm(FSM_MACRO, sym->name); 1221 mac->value = newof(mac->value, char, (mac->size = p - mac->value) + 1, 0); 1222 if ((pp.option & (DEFINITIONS|PREDEFINITIONS|REGUARD)) && !sym->hidden && !(sym->flags & SYM_MULTILINE) && ((pp.option & PREDEFINITIONS) || !(pp.mode & INIT)) && ((pp.option & (DEFINITIONS|PREDEFINITIONS)) || !(pp.state & NOTEXT))) 1223 { 1224 ppsync(); 1225 ppprintf("#%s %s", dirname(DEFINE), sym->name); 1226 if (sym->flags & SYM_FUNCTION) 1227 { 1228 ppputchar('('); 1229 if (mac->formals) 1230 ppprintf("%s", mac->formals); 1231 ppputchar(')'); 1232 } 1233 if ((p = mac->value) && *p) 1234 { 1235 ppputchar(' '); 1236 i0 = 0; 1237 while (n = *p++) 1238 { 1239 if (n != MARK || (n = *p++) == MARK) 1240 { 1241 ppputchar(n); 1242 i0 = ppisid(n); 1243 } 1244 else 1245 { 1246 if (n == 'Q') 1247 ppputchar('#'); 1248 else if (i0) 1249 { 1250 ppputchar('#'); 1251 ppputchar('#'); 1252 } 1253 s = formargs[*p++ - ARGOFFSET]; 1254 while ((n = *s++) && n != ',') 1255 ppputchar(n); 1256 if (ppisid(*p) || *p == MARK) 1257 { 1258 ppputchar('#'); 1259 ppputchar('#'); 1260 } 1261 i0 = 0; 1262 } 1263 ppcheckout(); 1264 } 1265 } 1266 emitted = 1; 1267 } 1268 benign: 1269 if (pp.mode & BUILTIN) sym->flags |= SYM_BUILTIN; 1270 if (pp.option & FINAL) sym->flags |= SYM_FINAL; 1271 if (pp.mode & INIT) sym->flags |= SYM_INIT; 1272 if (pp.option & INITIAL) sym->flags |= SYM_INITIAL; 1273 if (pp.state & NOEXPAND) sym->flags |= SYM_NOEXPAND; 1274 if (pp.option & PREDEFINED) sym->flags |= SYM_PREDEFINED; 1275 if (pp.mode & READONLY) sym->flags |= SYM_READONLY; 1276 if (pp.macref) (*pp.macref)(sym, error_info.file, n2, mac ? error_info.line - n2 + 1 : REF_UNDEF, mac ? strsum(mac->value, (long)mac->arity) : 0L); 1277 break; 1278 assertion: 1279 c = pplex(); 1280 if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1281 error(1, "#%s #%s: assertions are non-standard", dirname(directive), pptokstr(pp.token, 0)); 1282 if (c != T_ID) 1283 { 1284 error(2, "%s: invalid predicate name", pptokstr(pp.token, 0)); 1285 goto eatdirective; 1286 } 1287 switch ((int)hashref(pp.strtab, pp.token)) 1288 { 1289 case X_DEFINED: 1290 case X_EXISTS: 1291 case X_STRCMP: 1292 error(2, "%s is a builtin predicate", pp.token); 1293 goto eatdirective; 1294 case X_SIZEOF: 1295 error(2, "%s cannot be a predicate", pp.token); 1296 goto eatdirective; 1297 } 1298 strcpy(pp.tmpbuf, pp.token); 1299 switch (pppredargs()) 1300 { 1301 case T_ID: 1302 case T_STRING: 1303 assert(directive, pp.tmpbuf, pp.args); 1304 break; 1305 case 0: 1306 assert(directive, pp.tmpbuf, NiL); 1307 break; 1308 default: 1309 error(2, "invalid predicate argument list"); 1310 goto eatdirective; 1311 } 1312 break; 1313 tuple: 1314 pp.state |= DEFINITION|NOEXPAND|NOSPACE; 1315 rp = 0; 1316 tp = mac->tuple; 1317 if (!tp && !mac->value) 1318 ppfsm(FSM_MACRO, sym->name); 1319 while ((c = pplex()) && c != '>' && c != '\n') 1320 { 1321 for (; tp; tp = tp->nomatch) 1322 if (streq(tp->token, pp.token)) 1323 break; 1324 if (!tp) 1325 { 1326 if (!(tp = newof(0, struct pptuple, 1, strlen(pp.token)))) 1327 error(3, "out of space"); 1328 strcpy(tp->token, pp.token); 1329 if (rp) 1330 { 1331 tp->nomatch = rp; 1332 rp->nomatch = tp; 1333 } 1334 else 1335 { 1336 tp->nomatch = mac->tuple; 1337 mac->tuple = tp; 1338 } 1339 } 1340 rp = tp; 1341 tp = tp->match; 1342 } 1343 pp.state &= ~NOSPACE; 1344 if (!rp || c != '>') 1345 error(2, "%s: > omitted in tuple macro definition", sym->name); 1346 else 1347 { 1348 n = 2 * MAXTOKEN; 1349 p = v = oldof(0, char, 0, n); 1350 while ((c = pplex()) && c != '\n') 1351 if (p > v || c != ' ') 1352 { 1353 STRCOPY(p, pp.token, s); 1354 if (p > &v[n - MAXTOKEN] && (s = newof(v, char, n += MAXTOKEN, 0)) != v) 1355 { 1356 c = p - v; 1357 v = s; 1358 p = v + c; 1359 } 1360 } 1361 while (p > v && *(p - 1) == ' ') 1362 p--; 1363 n = p - v; 1364 tp = newof(0, struct pptuple, 1, n); 1365 strcpy(tp->token, v); 1366 tp->match = rp->match; 1367 rp->match = tp; 1368 } 1369 goto benign; 1370 case WARNING: 1371 if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1372 error(1, "#%s: non-standard directive", pp.token); 1373 /*FALLTHROUGH*/ 1374 case ERROR: 1375 pp.state &= ~DISABLE; 1376 p = pp.tmpbuf; 1377 while ((c = pplex()) != '\n') 1378 if (p + strlen(pp.token) < &pp.tmpbuf[MAXTOKEN]) 1379 { 1380 STRCOPY(p, pp.token, s); 1381 pp.state &= ~NOSPACE; 1382 } 1383 *p = 0; 1384 p = *pp.tmpbuf ? pp.tmpbuf : ((directive == WARNING) ? "user warning" : "user error"); 1385 n = (directive == WARNING) ? 1 : 3; 1386 error(n, "%s", p); 1387 break; 1388 case LET: 1389 n2 = error_info.line; 1390 if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1391 error(1, "#%s: non-standard directive", pp.token); 1392 if (!(sym = macsym(c = pplex()))) goto eatdirective; 1393 if ((c = pplex()) != '=') 1394 { 1395 error(2, "%s: = expected", sym->name); 1396 goto eatdirective; 1397 } 1398 sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_MULTILINE|SYM_PREDEFINED|SYM_VARIADIC); 1399 mac = sym->macro; 1400 mac->arity = 0; 1401 if (mac->value) 1402 { 1403 if (!(sym->flags & SYM_REDEFINE) && !sym->hidden) 1404 error(1, "%s: redefined", sym->name); 1405 #if MACKEYARGS 1406 if ((pp.option & KEYARGS) && mac->formkeys) free(mac->formkeys); 1407 else 1408 #endif 1409 free(mac->formals); 1410 mac->formals = 0; 1411 n = strlen(mac->value) + 1; 1412 } 1413 else 1414 { 1415 ppfsm(FSM_MACRO, sym->name); 1416 n = 0; 1417 } 1418 n1 = ppexpr(&i1); 1419 if (i1) c = sfsprintf(pp.tmpbuf, MAXTOKEN, "%luU", n1); 1420 else c = sfsprintf(pp.tmpbuf, MAXTOKEN, "%ld", n1); 1421 if (n < ++c) 1422 { 1423 if (mac->value) free(mac->value); 1424 mac->value = oldof(0, char, 0, c); 1425 } 1426 strcpy(mac->value, pp.tmpbuf); 1427 sym->flags |= SYM_REDEFINE; 1428 c = (pp.state & NEWLINE) ? '\n' : ' '; 1429 goto benign; 1430 case LINE: 1431 pp.state &= ~DISABLE; 1432 if ((c = pplex()) == '#') 1433 { 1434 c = pplex(); 1435 directive = INCLUDE; 1436 } 1437 if (c != T_DECIMAL && c != T_OCTAL) 1438 { 1439 error(1, "#%s: line number expected", dirname(LINE)); 1440 goto eatdirective; 1441 } 1442 linesync: 1443 n = error_info.line; 1444 error_info.line = strtol(pp.token, NiL, 0); 1445 if (error_info.line == 0 && directive == LINE && (pp.state & STRICT) && !(pp.mode & HOSTED)) 1446 error(1, "#%s: line number should be > 0", dirname(LINE)); 1447 pp.state &= ~DISABLE; 1448 pp.state |= STRIP; 1449 switch (c = pplex()) 1450 { 1451 case T_STRING: 1452 s = error_info.file; 1453 if (*(p = pp.token)) pathcanon(p, 0); 1454 fp = ppsetfile(p); 1455 error_info.file = fp->name; 1456 if (error_info.line == 1) 1457 ppmultiple(fp, INC_TEST); 1458 switch (c = pplex()) 1459 { 1460 case '\n': 1461 break; 1462 case T_DECIMAL: 1463 case T_OCTAL: 1464 if (directive == LINE && (pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1465 error(1, "#%s: integer file type argument is non-standard", dirname(LINE)); 1466 break; 1467 default: 1468 error(1, "#%s: integer file type argument expected", dirname(LINE)); 1469 break; 1470 } 1471 if (directive == LINE) pp.in->flags &= ~IN_ignoreline; 1472 else if (pp.incref) 1473 { 1474 if (error_info.file != s) 1475 { 1476 switch (*pp.token) 1477 { 1478 case PP_sync_push: 1479 if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1480 else (*pp.incref)(s, error_info.file, n, PP_SYNC_PUSH); 1481 break; 1482 case PP_sync_pop: 1483 if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1484 else (*pp.incref)(s, error_info.file, n - 1, PP_SYNC_POP); 1485 break; 1486 case PP_sync_ignore: 1487 if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1488 else 1489 { 1490 (*pp.incref)(s, error_info.file, n, PP_SYNC_IGNORE); 1491 error_info.file = s; 1492 } 1493 break; 1494 default: 1495 if (*s) 1496 { 1497 if (fp == pp.insert) 1498 pp.insert = 0; 1499 else if (error_info.line == 1 && !pp.insert) 1500 (*pp.incref)(s, error_info.file, n, PP_SYNC_PUSH); 1501 else 1502 { 1503 if (!pp.insert) pp.insert = ppgetfile(s); 1504 (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1505 } 1506 } 1507 break; 1508 } 1509 } 1510 } 1511 break; 1512 case '\n': 1513 break; 1514 default: 1515 error(1, "#%s: \"file-name\" expected", dirname(LINE)); 1516 break; 1517 } 1518 if (directive == LINE && (pp.in->flags & IN_ignoreline)) 1519 error_info.line = n + 1; 1520 else 1521 { 1522 pp.hidden = 0; 1523 pp.state &= ~HIDDEN; 1524 if (pp.linesync) 1525 { 1526 #if CATSTRINGS 1527 if (pp.state & JOINING) pp.state |= HIDDEN|SYNCLINE; 1528 else 1529 #endif 1530 { 1531 s = pp.lineid; 1532 n = pp.flags; 1533 if (directive == LINE) 1534 { 1535 pp.flags &= ~PP_linetype; 1536 if (pp.macref) pp.lineid = dirname(LINE); 1537 } 1538 (*pp.linesync)(error_info.line, error_info.file); 1539 pp.flags = n; 1540 pp.lineid = s; 1541 } 1542 } 1543 } 1544 directive = LINE; 1545 break; 1546 case PRAGMA: 1547 /* 1548 * #pragma [STDC] [pass:] [no]option [arg ...] 1549 * 1550 * pragma args are not expanded by default 1551 * 1552 * if STDC is present then it is silently passed on 1553 * 1554 * if pass is pp.pass then the option is used 1555 * and verified but is not passed on 1556 * 1557 * if pass is omitted then the option is passed on 1558 * 1559 * otherwise if pass is non-null and not pp.pass then 1560 * the option is passed on but not used 1561 * 1562 * if the line does not match this form then 1563 * it is passed on unchanged 1564 * 1565 * #directive pass: option [...] 1566 * ^ ^ ^ ^ ^ ^ ^ ^ 1567 * pp.valbuf p0 p1 p2 p3 p4 p5 p6 1568 * 1569 * p? 0 if component omitted 1570 * i0 0 if ``no''option 1571 */ 1572 1573 p = pp.valbuf; 1574 *p++ = '#'; 1575 STRCOPY(p, pp.token, s); 1576 p0 = p; 1577 if (pp.option & PRAGMAEXPAND) 1578 pp.state &= ~DISABLE; 1579 if (!(p6 = getline(p, &pp.valbuf[MAXTOKEN], !!(pp.option & PRAGMAEXPAND)))) 1580 { 1581 *p0 = 0; 1582 error(2, "%s: directive too long", pp.valbuf); 1583 c = 0; 1584 goto eatdirective; 1585 } 1586 p1 = ++p; 1587 while (ppisid(*p)) 1588 p++; 1589 if (p == p1) 1590 { 1591 p5 = p; 1592 p4 = 0; 1593 p3 = 0; 1594 p2 = 0; 1595 p1 = 0; 1596 } 1597 else if (*p != ':') 1598 { 1599 p5 = *p ? p + (*p == ' ') : 0; 1600 p4 = p; 1601 p3 = p1; 1602 p2 = 0; 1603 p1 = 0; 1604 } 1605 else 1606 { 1607 p2 = p++; 1608 p3 = p; 1609 while (ppisid(*p)) 1610 p++; 1611 if (p == p3) 1612 { 1613 p4 = p1; 1614 p3 = 0; 1615 p2 = 0; 1616 p1 = 0; 1617 } 1618 else 1619 p4 = p; 1620 p5 = *p4 ? p4 + (*p4 == ' ') : 0; 1621 } 1622 if (!p1 && p3 && (p4 - p3) == 4 && strneq(p3, "STDC", 4)) 1623 goto pass; 1624 if ((pp.state & WARN) && !(pp.mode & (HOSTED|RELAX))) 1625 error(1, "#%s: non-standard directive", dirname(PRAGMA)); 1626 i0 = !p3 || *p3 != 'n' || *(p3 + 1) != 'o'; 1627 if (!p3) 1628 goto checkmap; 1629 if (p1) 1630 { 1631 *p2 = 0; 1632 n = streq(p1, pp.pass); 1633 *p2 = ':'; 1634 if (!n) 1635 goto checkmap; 1636 } 1637 else 1638 n = 0; 1639 i2 = *p4; 1640 *p4 = 0; 1641 if (((i1 = (int)hashref(pp.strtab, p3 + (i0 ? 0 : 2))) < 1 || i1 > X_last_option) && (i0 || (i1 = (int)hashref(pp.strtab, p3)) > X_last_option)) 1642 i1 = 0; 1643 if ((pp.state & (COMPATIBILITY|STRICT)) == STRICT && !(pp.mode & (HOSTED|RELAX))) 1644 { 1645 if (pp.optflags[i1] & OPT_GLOBAL) 1646 goto donedirective; 1647 if (n || (pp.mode & WARN)) 1648 { 1649 n = 0; 1650 error(1, "#%s: non-standard directive ignored", dirname(PRAGMA)); 1651 } 1652 i1 = 0; 1653 } 1654 if (!n) 1655 { 1656 if (!(pp.optflags[i1] & OPT_GLOBAL)) 1657 { 1658 *p4 = i2; 1659 goto checkmap; 1660 } 1661 if (!(pp.optflags[i1] & OPT_PASS)) 1662 n = 1; 1663 } 1664 else if (!i1) 1665 error(2, "%s: unknown option", p1); 1666 else if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1667 error(1, "%s: non-standard option", p1); 1668 p = p5; 1669 switch (i1) 1670 { 1671 case X_ALLMULTIPLE: 1672 ppop(PP_MULTIPLE, i0); 1673 break; 1674 case X_ALLPOSSIBLE: 1675 setoption(ALLPOSSIBLE, i0); 1676 break; 1677 case X_BUILTIN: 1678 setmode(BUILTIN, i0); 1679 break; 1680 case X_CATLITERAL: 1681 setmode(CATLITERAL, i0); 1682 if (pp.mode & CATLITERAL) 1683 setoption(STRINGSPLIT, 0); 1684 break; 1685 case X_CDIR: 1686 tokop(PP_CDIR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 1687 break; 1688 case X_CHECKPOINT: 1689 #if CHECKPOINT 1690 ppload(p); 1691 #else 1692 error(3, "%s: preprocessor not compiled with checkpoint enabled", p3); 1693 #endif 1694 break; 1695 case X_CHOP: 1696 tokop(PP_CHOP, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 1697 break; 1698 case X_COMPATIBILITY: 1699 ppop(PP_COMPATIBILITY, i0); 1700 break; 1701 case X_DEBUG: 1702 error_info.trace = i0 ? (p ? -strtol(p, NiL, 0) : -1) : 0; 1703 break; 1704 case X_ELSEIF: 1705 setoption(ELSEIF, i0); 1706 break; 1707 case X_EXTERNALIZE: 1708 setmode(EXTERNALIZE, i0); 1709 break; 1710 case X_FINAL: 1711 setoption(FINAL, i0); 1712 break; 1713 case X_HEADEREXPAND: 1714 setoption(HEADEREXPAND, i0); 1715 break; 1716 case X_HEADEREXPANDALL: 1717 setoption(HEADEREXPANDALL, i0); 1718 break; 1719 case X_HIDE: 1720 case X_NOTE: 1721 PUSH_LINE(p); 1722 /* UNDENT...*/ 1723 while (c = pplex()) 1724 { 1725 if (c != T_ID) error(1, "%s: %s: identifier expected", p3, pp.token); 1726 else if (sym = ppsymset(pp.symtab, pp.token)) 1727 { 1728 if (i1 == X_NOTE) 1729 { 1730 sym->flags &= ~SYM_NOTICED; 1731 ppfsm(FSM_MACRO, sym->name); 1732 } 1733 else if (i0) 1734 { 1735 if (!sym->hidden && !(sym->hidden = newof(0, struct pphide, 1, 0))) 1736 error(3, "out of space"); 1737 if (!sym->macro) 1738 ppfsm(FSM_MACRO, sym->name); 1739 if (!sym->hidden->level++) 1740 { 1741 pp.hiding++; 1742 if (sym->macro && !(sym->flags & (SYM_ACTIVE|SYM_READONLY))) 1743 { 1744 sym->hidden->macro = sym->macro; 1745 sym->macro = 0; 1746 sym->hidden->flags = sym->flags; 1747 sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 1748 } 1749 } 1750 } 1751 else if (sym->hidden) 1752 { 1753 if ((mac = sym->macro) && !(sym->flags & (SYM_ACTIVE|SYM_READONLY))) 1754 { 1755 if (mac->formals) free(mac->formals); 1756 free(mac->value); 1757 free(mac); 1758 sym->macro = 0; 1759 sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 1760 } 1761 if (!--sym->hidden->level) 1762 { 1763 pp.hiding--; 1764 if (sym->hidden->macro) 1765 { 1766 sym->macro = sym->hidden->macro; 1767 sym->flags = sym->hidden->flags; 1768 } 1769 free(sym->hidden); 1770 sym->hidden = 0; 1771 } 1772 } 1773 } 1774 } 1775 /*...INDENT*/ 1776 POP_LINE(); 1777 break; 1778 case X_HOSTDIR: 1779 tokop(PP_HOSTDIR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 1780 break; 1781 case X_HOSTED: 1782 setmode(HOSTED, i0); 1783 break; 1784 case X_HOSTEDTRANSITION: 1785 setmode(HOSTEDTRANSITION, i0); 1786 break; 1787 case X_ID: 1788 tokop(PP_ID, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 1789 break; 1790 case X_IGNORE: 1791 tokop(PP_IGNORE, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 1792 break; 1793 case X_INCLUDE: 1794 tokop(PP_INCLUDE, p3, p, i0, TOKOP_STRING|TOKOP_DUP); 1795 break; 1796 case X_INITIAL: 1797 setoption(INITIAL, i0); 1798 break; 1799 case X_KEYARGS: 1800 ppop(PP_KEYARGS, i0); 1801 break; 1802 case X_LINE: 1803 if (pp.linesync) pp.olinesync = pp.linesync; 1804 pp.linesync = i0 ? pp.olinesync : (PPLINESYNC)0; 1805 break; 1806 case X_LINEBASE: 1807 ppop(PP_LINEBASE, i0); 1808 break; 1809 case X_LINEFILE: 1810 ppop(PP_LINEFILE, i0); 1811 break; 1812 case X_LINEID: 1813 ppop(PP_LINEID, i0 ? p : (char*)0); 1814 break; 1815 case X_LINETYPE: 1816 ppop(PP_LINETYPE, i0 ? (p ? strtol(p, NiL, 0) : 1) : 0); 1817 break; 1818 case X_MACREF: 1819 if (!p) 1820 { 1821 if (i0 && !pp.macref) 1822 { 1823 ppop(PP_LINETYPE, 1); 1824 ppop(PP_MACREF, ppmacref); 1825 } 1826 else error(2, "%s: option cannot be unset", p3); 1827 } 1828 else if (s = strchr(p, ' ')) 1829 { 1830 if (pp.macref && (s = strchr(p, ' '))) 1831 { 1832 *s++ = 0; 1833 c = strtol(s, NiL, 0); 1834 var.type = pp.truncate; 1835 pp.truncate = PPTOKSIZ; 1836 (*pp.macref)(pprefmac(p, REF_CREATE), error_info.file, error_info.line - (c == REF_NORMAL ? 2 : 1), c, (s = strchr(s, ' ')) ? strtol(s, NiL, 0) : 0L); 1837 pp.truncate = var.type; 1838 } 1839 error_info.line -= 2; 1840 } 1841 break; 1842 case X_MAP: 1843 /*UNDENT*/ 1844 /* 1845 * #pragma pp:map [id ...] "/from/[,/to/]" [ "/old/new/[glnu]" ... ] 1846 */ 1847 1848 if (!i0) 1849 { 1850 error(2, "%s: option cannot be unset", p3); 1851 goto donedirective; 1852 } 1853 if (!p5) 1854 { 1855 error(2, "%s: address argument expected", p3); 1856 goto donedirective; 1857 } 1858 PUSH_LINE(p5); 1859 while ((c = pplex()) == T_ID) 1860 { 1861 sfsprintf(pp.tmpbuf, MAXTOKEN, "__%s__", s = pp.token); 1862 if (c = (int)hashget(pp.dirtab, s)) 1863 { 1864 hashput(pp.dirtab, 0, 0); 1865 hashput(pp.dirtab, pp.tmpbuf, c); 1866 } 1867 if (c = (int)hashget(pp.strtab, s)) 1868 { 1869 hashput(pp.strtab, 0, 0); 1870 hashput(pp.strtab, pp.tmpbuf, c); 1871 } 1872 } 1873 if (c != T_STRING || !*(s = pp.token)) 1874 { 1875 if (c) 1876 error(2, "%s: %s: address argument expected", p3, pptokstr(pp.token, 0)); 1877 goto eatmap; 1878 } 1879 map = newof(0, struct map, 1, 0); 1880 1881 /* 1882 * /from/ 1883 */ 1884 1885 if (i0 = regcomp(&map->re, s, REG_AUGMENTED|REG_DELIMITED|REG_LENIENT|REG_NULL)) 1886 regfatal(&map->re, 3, i0); 1887 if (*(s += map->re.re_npat)) 1888 { 1889 error(2, "%s: invalid characters after pattern: %s ", p3, s); 1890 goto eatmap; 1891 } 1892 1893 /* 1894 * /old/new/[flags] 1895 */ 1896 1897 edit = 0; 1898 while ((c = pplex()) == T_STRING) 1899 { 1900 if (!*(s = pp.token)) 1901 { 1902 error(2, "%s: substitution argument expected", p3); 1903 goto eatmap; 1904 } 1905 if (edit) 1906 edit = edit->next = newof(0, struct edit, 1, 0); 1907 else 1908 edit = map->edit = newof(0, struct edit, 1, 0); 1909 if (!(i0 = regcomp(&edit->re, s, REG_AUGMENTED|REG_DELIMITED|REG_LENIENT|REG_NULL)) && !(i0 = regsubcomp(&edit->re, s += edit->re.re_npat, NiL, 0, 0))) 1910 s += edit->re.re_npat; 1911 if (i0) 1912 regfatal(&edit->re, 3, i0); 1913 if (*s) 1914 { 1915 error(2, "%s: invalid characters after substitution: %s ", p3, s); 1916 goto eatmap; 1917 } 1918 } 1919 if (c) 1920 { 1921 error(2, "%s: %s: substitution argument expected", p3, pptokstr(pp.token, 0)); 1922 goto eatmap; 1923 } 1924 map->next = (struct map*)pp.maps; 1925 pp.maps = (char*)map; 1926 eatmap: 1927 POP_LINE(); 1928 /*INDENT*/ 1929 break; 1930 case X_MAPINCLUDE: 1931 ppmapinclude(NiL, p5); 1932 break; 1933 case X_MODERN: 1934 setoption(MODERN, i0); 1935 break; 1936 case X_MULTIPLE: 1937 n = 1; 1938 if (pp.in->type == IN_FILE) 1939 ppmultiple(ppsetfile(error_info.file), i0 ? INC_CLEAR : INC_TEST); 1940 break; 1941 case X_NATIVE: 1942 setoption(NATIVE, i0); 1943 break; 1944 case X_OPSPACE: 1945 ppfsm(FSM_OPSPACE, i0 ? p4 : (char*)0); 1946 break; 1947 case X_PASSTHROUGH: 1948 ppop(PP_PASSTHROUGH, i0); 1949 break; 1950 case X_PEDANTIC: 1951 ppop(PP_PEDANTIC, i0); 1952 break; 1953 case X_PLUSCOMMENT: 1954 ppop(PP_PLUSCOMMENT, i0); 1955 break; 1956 case X_PLUSPLUS: 1957 ppop(PP_PLUSPLUS, i0); 1958 break; 1959 case X_PLUSSPLICE: 1960 setoption(PLUSSPLICE, i0); 1961 break; 1962 case X_PRAGMAEXPAND: 1963 setoption(PRAGMAEXPAND, i0); 1964 break; 1965 case X_PRAGMAFLAGS: 1966 tokop(PP_PRAGMAFLAGS, p3, p, i0, 0); 1967 break; 1968 case X_PREDEFINED: 1969 setoption(PREDEFINED, i0); 1970 break; 1971 case X_PREFIX: 1972 setoption(PREFIX, i0); 1973 break; 1974 case X_PRESERVE: 1975 setoption(PRESERVE, i0); 1976 if (pp.option & PRESERVE) 1977 { 1978 setmode(CATLITERAL, 0); 1979 ppop(PP_COMPATIBILITY, 1); 1980 ppop(PP_TRANSITION, 0); 1981 ppop(PP_PLUSCOMMENT, 1); 1982 ppop(PP_SPACEOUT, 1); 1983 setoption(STRINGSPAN, 1); 1984 setoption(STRINGSPLIT, 0); 1985 ppop(PP_HOSTDIR, "-", 1); 1986 } 1987 break; 1988 case X_PROTOTYPED: 1989 /* 1990 * this option doesn't bump the token count 1991 */ 1992 1993 n = 1; 1994 directive = ENDIF; 1995 #if PROTOTYPE 1996 setoption(PROTOTYPED, i0); 1997 #else 1998 error(1, "preprocessor not compiled with prototype conversion enabled"); 1999 #endif 2000 break; 2001 case X_PROTO: 2002 setoption(NOPROTO, !i0); 2003 break; 2004 case X_QUOTE: 2005 tokop(PP_QUOTE, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 2006 break; 2007 case X_READONLY: 2008 setmode(READONLY, i0); 2009 break; 2010 case X_REGUARD: 2011 setoption(REGUARD, i0); 2012 break; 2013 case X_RESERVED: 2014 tokop(PP_RESERVED, p3, p, i0, 0); 2015 break; 2016 case X_SPACEOUT: 2017 if (!(pp.state & (COMPATIBILITY|COMPILE))) 2018 ppop(PP_SPACEOUT, i0); 2019 break; 2020 case X_SPLICECAT: 2021 setoption(SPLICECAT, i0); 2022 break; 2023 case X_SPLICESPACE: 2024 setoption(SPLICESPACE, i0); 2025 break; 2026 case X_STANDARD: 2027 tokop(PP_STANDARD, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 2028 break; 2029 case X_STRICT: 2030 ppop(PP_STRICT, i0); 2031 break; 2032 case X_STRINGSPAN: 2033 setoption(STRINGSPAN, i0); 2034 break; 2035 case X_STRINGSPLIT: 2036 setoption(STRINGSPLIT, i0); 2037 if (pp.option & STRINGSPLIT) 2038 setmode(CATLITERAL, 0); 2039 break; 2040 case X_SYSTEM_HEADER: 2041 if (i0) 2042 { 2043 pp.mode |= HOSTED; 2044 pp.flags |= PP_hosted; 2045 pp.in->flags |= IN_hosted; 2046 } 2047 else 2048 { 2049 pp.mode &= ~HOSTED; 2050 pp.flags &= ~PP_hosted; 2051 pp.in->flags &= ~PP_hosted; 2052 } 2053 break; 2054 case X_TEST: 2055 ppop(PP_TEST, p); 2056 break; 2057 case X_TEXT: 2058 if (!(pp.option & KEEPNOTEXT)) 2059 setstate(NOTEXT, !i0); 2060 break; 2061 case X_TRANSITION: 2062 ppop(PP_TRANSITION, i0); 2063 if (pp.state & TRANSITION) ppop(PP_COMPATIBILITY, i0); 2064 break; 2065 case X_TRUNCATE: 2066 ppop(PP_TRUNCATE, i0 ? (p ? strtol(p, NiL, 0) : TRUNCLENGTH) : 0); 2067 break; 2068 case X_VENDOR: 2069 tokop(PP_VENDOR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 2070 break; 2071 case X_VERSION: 2072 if (!(*pp.control & SKIP) && pp.pragma && !(pp.state & NOTEXT)) 2073 { 2074 sfsprintf(pp.tmpbuf, MAXTOKEN, "\"%s\"", pp.version); 2075 (*pp.pragma)(dirname(PRAGMA), pp.pass, p3, pp.tmpbuf, !n); 2076 if (pp.linesync && !n) 2077 (*pp.linesync)(error_info.line, error_info.file); 2078 emitted = 1; 2079 } 2080 break; 2081 case X_WARN: 2082 ppop(PP_WARN, i0); 2083 break; 2084 case X_ZEOF: 2085 setoption(ZEOF, i0); 2086 break; 2087 #if DEBUG 2088 case 0: 2089 case X_INCLUDED: 2090 case X_NOTICED: 2091 case X_OPTION: 2092 case X_STATEMENT: 2093 break; 2094 default: 2095 error(PANIC, "%s: option recognized but not implemented", pp.valbuf); 2096 break; 2097 #endif 2098 } 2099 *p4 = i2; 2100 if (!n) 2101 goto checkmap; 2102 goto donedirective; 2103 case RENAME: 2104 if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 2105 error(1, "#%s: non-standard directive", pp.token); 2106 if ((c = pplex()) != T_ID) 2107 { 2108 error(1, "%s: invalid macro name", pptokstr(pp.token, 0)); 2109 goto eatdirective; 2110 } 2111 if (!(sym = pprefmac(pp.token, REF_DELETE)) || !sym->macro) 2112 goto eatdirective; 2113 if (sym->flags & (SYM_ACTIVE|SYM_READONLY)) 2114 { 2115 if (!(pp.option & ALLPOSSIBLE)) 2116 error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active"); 2117 goto eatdirective; 2118 } 2119 if ((c = pplex()) != T_ID) 2120 { 2121 error(1, "%s: invalid macro name", pptokstr(pp.token, 0)); 2122 goto eatdirective; 2123 } 2124 var.symbol = pprefmac(pp.token, REF_CREATE); 2125 if (mac = var.symbol->macro) 2126 { 2127 if (var.symbol->flags & (SYM_ACTIVE|SYM_READONLY)) 2128 { 2129 if (!(pp.option & ALLPOSSIBLE)) 2130 error(2, "%s: macro is %s", var.symbol->name, (var.symbol->flags & SYM_READONLY) ? "readonly" : "active"); 2131 goto eatdirective; 2132 } 2133 if (!(pp.mode & HOSTED) || !(var.symbol->flags & SYM_INITIAL)) 2134 error(1, "%s redefined", var.symbol->name); 2135 if (mac->formals) free(mac->formals); 2136 free(mac->value); 2137 free(mac); 2138 } 2139 ppfsm(FSM_MACRO, var.symbol->name); 2140 var.symbol->flags = sym->flags; 2141 sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 2142 var.symbol->macro = sym->macro; 2143 sym->macro = 0; 2144 break; 2145 case UNDEF: 2146 if ((c = pplex()) != T_ID) 2147 { 2148 error(1, "%s: invalid macro name", pptokstr(pp.token, 0)); 2149 goto eatdirective; 2150 } 2151 if (sym = pprefmac(pp.token, REF_DELETE)) 2152 { 2153 if (mac = sym->macro) 2154 { 2155 if (sym->flags & (SYM_ACTIVE|SYM_READONLY)) 2156 { 2157 if (!(pp.option & ALLPOSSIBLE)) 2158 error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active"); 2159 goto eatdirective; 2160 } 2161 if (mac->formals) free(mac->formals); 2162 free(mac->value); 2163 free(mac); 2164 mac = sym->macro = 0; 2165 } 2166 if ((pp.option & (DEFINITIONS|PREDEFINITIONS|REGUARD)) && !sym->hidden && !(sym->flags & SYM_MULTILINE) && ((pp.option & PREDEFINITIONS) || !(pp.mode & INIT)) && ((pp.option & (DEFINITIONS|PREDEFINITIONS)) || !(pp.state & NOTEXT))) 2167 { 2168 ppsync(); 2169 ppprintf("#%s %s", dirname(UNDEF), sym->name); 2170 emitted = 1; 2171 } 2172 sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 2173 n2 = error_info.line; 2174 goto benign; 2175 } 2176 else pprefmac(pp.token, REF_UNDEF); 2177 break; 2178 #if DEBUG 2179 default: 2180 error(PANIC, "#%s: directive recognized but not implemented", pp.token); 2181 goto eatdirective; 2182 #endif 2183 } 2184 break; 2185 case '\n': 2186 break; 2187 default: 2188 error(1, "%s: invalid directive name", pptokstr(pp.token, 0)); 2189 goto eatdirective; 2190 } 2191 enddirective: 2192 #if COMPATIBLE 2193 if (c != '\n' && !(pp.state & COMPATIBILITY)) 2194 #else 2195 if (c != '\n') 2196 #endif 2197 { 2198 pp.state |= DISABLE|NOSPACE; 2199 if ((c = pplex()) != '\n' && (pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC) 2200 error(1, "%s: invalid characters after directive", pptokstr(pp.token, 0)); 2201 } 2202 eatdirective: 2203 if (c != '\n') 2204 { 2205 pp.state |= DISABLE; 2206 while (pplex() != '\n'); 2207 } 2208 donedirective: 2209 #if _HUH_2002_05_09 2210 if (!(pp.state & EOF2NL)) 2211 error(2, "%s in directive", pptokchr(0)); 2212 #endif 2213 pp.state &= ~RESTORE; 2214 pp.mode &= ~RELAX; 2215 if (!(*pp.control & SKIP)) 2216 { 2217 pp.state |= restore; 2218 switch (directive) 2219 { 2220 case LINE: 2221 return 0; 2222 case INCLUDE: 2223 if (pp.include) 2224 { 2225 error_info.line++; 2226 PUSH_FILE(pp.include, n); 2227 if (!pp.vendor && (pp.found->type & TYPE_VENDOR)) 2228 pp.vendor = 1; 2229 pp.include = 0; 2230 return 0; 2231 } 2232 if (pp.incref) 2233 (*pp.incref)(error_info.file, ppgetfile(pp.path)->name, error_info.line, PP_SYNC_IGNORE); 2234 else if (pp.linesync && pp.macref) 2235 { 2236 pp.flags |= PP_lineignore; 2237 (*pp.linesync)(error_info.line, ppgetfile(pp.path)->name); 2238 } 2239 /*FALLTHROUGH*/ 2240 default: 2241 pp.in->flags |= IN_tokens; 2242 /*FALLTHROUGH*/ 2243 case ENDIF: 2244 error_info.line++; 2245 if (emitted) 2246 { 2247 ppputchar('\n'); 2248 ppcheckout(); 2249 } 2250 else 2251 { 2252 pp.state |= HIDDEN; 2253 pp.hidden++; 2254 } 2255 return 0; 2256 } 2257 } 2258 pp.state |= restore|HIDDEN|SKIPCONTROL; 2259 pp.hidden++; 2260 pp.level++; 2261 error_info.line++; 2262 return 0; 2263 } 2264 2265 /* 2266 * grow the pp nesting control stack 2267 */ 2268 2269 void 2270 ppnest(void) 2271 { 2272 register struct ppinstk* ip; 2273 int oz; 2274 int nz; 2275 long adjust; 2276 long* op; 2277 long* np; 2278 2279 oz = pp.constack; 2280 op = pp.maxcon - oz + 1; 2281 nz = oz * 2; 2282 np = newof(op, long, nz, 0); 2283 if (adjust = (np - op)) 2284 { 2285 ip = pp.in; 2286 do 2287 { 2288 if (ip->control) 2289 ip->control += adjust; 2290 } while (ip = ip->prev); 2291 } 2292 pp.control = np + oz; 2293 pp.constack = nz; 2294 pp.maxcon = np + nz - 1; 2295 } 2296