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 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 if ((pp.state & WARN) && !(pp.mode & (HOSTED|RELAX)) && var.type != TOK_TOKCAT && !(var.type & TOK_ID)) 911 { 912 s = pp.in->nextchr; 913 while ((c = *s++) && (c == ' ' || c == '\t')); 914 if (c == '\n') 915 c = 0; 916 else if (c == '*' && *s == ')') 917 c = ')'; 918 else if (c == '=' || ppisidig(c) || c == *s || *s == '=') 919 c = 0; 920 if (o != '.' && o != T_PTRMEM) 921 { 922 if ((var.type & TOK_ID) || o == ' ' || ppisseparate(o)) 923 o = 0; 924 if (!((o == 0 || o == '(' || o == ')' || o == '[' || o == ']' || o == ',' || o == '|' || o == ';' || o == '{' || o == '}') && (c == '(' || c == ')' || c == '[' || c == ']' || c == ',' || c == '|' || c == ';' || c == '}' || c == 0)) && !(o == '*' && c == ')')) 925 error(1, "%s: %s: formal should be parenthesized in macro value (t=%x o=%#c c=%#c)", sym->name, pp.token, var.type, o, c); 926 } 927 } 928 var.type = TOK_FORMAL|TOK_ID; 929 c = '>'; 930 goto checkvalue; 931 } 932 if (var.type == TOK_BUILTIN) switch ((int)hashget(pp.strtab, pp.token)) 933 { 934 case V_DEFAULT: 935 case V_EMPTY: 936 sym->flags |= SYM_EMPTY; 937 break; 938 } 939 else if (pp.hiding && (var.symbol = ppsymref(pp.symtab, pp.token)) && var.symbol->hidden) 940 { 941 for (var.inp = pp.in; var.inp->type != IN_FILE && var.inp->prev; var.inp = var.inp->prev); 942 p += sfsprintf(p, MAXTOKEN, "_%d_%s_hIDe", var.inp->hide, pp.token); 943 var.type = TOK_ID; 944 goto checkvalue; 945 } 946 var.type = TOK_ID; 947 break; 948 case '#': 949 var.type = 0; 950 #if MACDEF 951 if (!(sym->flags & (SYM_FUNCTION|SYM_MULTILINE))) break; 952 #else 953 if (!(sym->flags & SYM_FUNCTION)) break; 954 #endif 955 pp.state |= NOSPACE; 956 c = pplex(); 957 if (c == '@') 958 { 959 c = pplex(); 960 i4 = 'S'; 961 } 962 else i4 = 'Q'; 963 pp.state &= ~NOSPACE; 964 if (c != T_ID) c = mac->arity; 965 else for (c = 0; c < mac->arity; c++) 966 if (streq(formargs[c], pp.token)) 967 break; 968 if (c >= mac->arity) 969 { 970 #if MACDEF 971 if (sym->flags & SYM_MULTILINE) 972 { 973 if (n3 & NEWLINE) 974 { 975 pp.state &= ~NOEXPAND; 976 switch ((int)hashref(pp.dirtab, pp.token)) 977 { 978 case ENDMAC: 979 if (!i2--) goto gotdefinition; 980 break; 981 case INCLUDE: 982 /* PARSE HEADER constant */ 983 break; 984 case MACDEF: 985 i2++; 986 break; 987 } 988 *p++ = '#'; 989 } 990 } 991 else 992 #endif 993 #if COMPATIBLE 994 if (pp.state & COMPATIBILITY) *p++ = '#'; 995 else 996 #endif 997 error(2, "# must precede a formal parameter"); 998 } 999 else 1000 { 1001 if (p > mac->value && ppisidig(*(p - 1)) && !(pp.option & PRESERVE)) *p++ = ' '; 1002 *p++ = MARK; 1003 *p++ = i4; 1004 *p++ = c + ARGOFFSET; 1005 goto checkvalue; 1006 } 1007 break; 1008 case T_TOKCAT: 1009 if (p <= mac->value) error(2, "%s lhs operand omitted", pp.token); 1010 else 1011 { 1012 if (*(p - 1) == ' ') p--; 1013 if (var.type == (TOK_FORMAL|TOK_ID)) *(p - 2) = 'C'; 1014 } 1015 pp.state |= NOSPACE; 1016 c = pplex(); 1017 pp.state &= ~NOSPACE; 1018 if (c == '\n') error(2, "%s rhs operand omitted", pptokchr(T_TOKCAT)); 1019 var.type = TOK_TOKCAT; 1020 continue; 1021 case '(': 1022 if (*pp.token == '#') 1023 { 1024 var.type = TOK_BUILTIN; 1025 n1++; 1026 } 1027 else 1028 { 1029 var.type = 0; 1030 if (n1) n1++; 1031 } 1032 break; 1033 case ')': 1034 var.type = 0; 1035 if (n1) n1--; 1036 break; 1037 case T_STRING: 1038 case T_CHARCONST: 1039 pp.state &= ~NOEXPAND; 1040 var.type = 0; 1041 if (strchr(pp.token, MARK)) pp.state &= ~NOEXPAND; 1042 #if COMPATIBLE 1043 /*UNDENT*/ 1044 1045 if ((sym->flags & SYM_FUNCTION) && (pp.state & (COMPATIBILITY|TRANSITION))) 1046 { 1047 char* v; 1048 1049 s = pp.token; 1050 for (;;) 1051 { 1052 if (!*s) goto checkvalue; 1053 if (ppisid(*s)) 1054 { 1055 v = s; 1056 while (ppisid(*++s)); 1057 i1 = *s; 1058 *s = 0; 1059 for (c = 0; c < mac->arity; c++) 1060 if (streq(formargs[c], v)) 1061 { 1062 *p++ = MARK; 1063 *p++ = 'C'; 1064 *p++ = c + ARGOFFSET; 1065 if (!(pp.mode & HOSTED) && (!(pp.state & COMPATIBILITY) || (pp.state & WARN))) switch (*pp.token) 1066 { 1067 case '"': 1068 error(1, "use the # operator to \"...\" quote macro arguments"); 1069 break; 1070 case '\'': 1071 error(1, "macro arguments should be '...' quoted before substitution"); 1072 break; 1073 } 1074 goto quotearg; 1075 } 1076 STRCOPY2(p, v); 1077 quotearg: 1078 *s = i1; 1079 } 1080 else *p++ = *s++; 1081 } 1082 } 1083 /*INDENT*/ 1084 #endif 1085 break; 1086 case '\n': 1087 #if MACDEF 1088 if (sym->flags & SYM_MULTILINE) 1089 { 1090 if (pp.state & EOF2NL) 1091 { 1092 error_info.line++; 1093 pp.state |= HIDDEN; 1094 pp.hidden++; 1095 var.type = 0; 1096 if (!i3++) 1097 goto checkvalue; 1098 break; 1099 } 1100 pp.state |= EOF2NL; 1101 error(2, "%s: missing #%s", sym->name, dirname(ENDMAC)); 1102 } 1103 #endif 1104 goto gotdefinition; 1105 case 0: 1106 c = '\n'; 1107 goto gotdefinition; 1108 #if COMPATIBLE 1109 case ' ': 1110 if (pp.state & COMPATIBILITY) var.type = 0; 1111 if (pp.option & PRESERVE) break; 1112 if (p > mac->value && *(p - 1) != ' ') *p++ = ' '; 1113 goto checkvalue; 1114 case '\t': 1115 if (var.type & TOK_ID) 1116 { 1117 while ((c = pplex()) == '\t'); 1118 if (c == T_ID) 1119 { 1120 if (var.type == (TOK_FORMAL|TOK_ID)) *(p - 2) = 'C'; 1121 var.type = TOK_TOKCAT; 1122 if (pp.state & WARN) error(1, "use the ## operator to concatenate macro arguments"); 1123 } 1124 else var.type = 0; 1125 continue; 1126 } 1127 var.type = 0; 1128 if (pp.option & PRESERVE) break; 1129 if (p > mac->value && *(p - 1) != ' ') *p++ = ' '; 1130 goto checkvalue; 1131 #endif 1132 case MARK: 1133 pp.state &= ~NOEXPAND; 1134 /*FALLTHROUGH*/ 1135 1136 default: 1137 var.type = 0; 1138 break; 1139 } 1140 STRCOPY(p, pp.token, s); 1141 checkvalue: 1142 o = c; 1143 if (p > &mac->value[n - MAXTOKEN] && (s = newof(mac->value, char, n += MAXTOKEN, 0)) != mac->value) 1144 { 1145 c = p - mac->value; 1146 mac->value = s; 1147 p = mac->value + c; 1148 } 1149 #if MACDEF 1150 n3 = pp.state; 1151 #endif 1152 c = pplex(); 1153 } 1154 gotdefinition: 1155 while (p > mac->value && *(p - 1) == ' ') p--; 1156 if (p > mac->value && (pp.option & PLUSPLUS) && (pp.state & (COMPATIBILITY|TRANSITION)) != COMPATIBILITY) 1157 switch (o) 1158 { 1159 case '+': 1160 case '-': 1161 case '&': 1162 case '|': 1163 case '<': 1164 case '>': 1165 case ':': 1166 case '=': 1167 *p++ = ' '; 1168 break; 1169 } 1170 *p = 0; 1171 #if MACKEYARGS 1172 if (!mac->arity) /* ok */; 1173 else if (pp.option & KEYARGS) 1174 { 1175 p0 = mac->formals; 1176 mac->formkeys = newof(0, struct ppkeyarg, n, p1 - p0 + 1); 1177 s = (char*)&mac->formkeys[mac->arity]; 1178 (void)memcpy(s, p0, p1 - p0 + 1); 1179 free(p0); 1180 for (n = 0; n < mac->arity; n++) 1181 { 1182 mac->formkeys[n].name = s + (formargs[n] - p0); 1183 mac->formkeys[n].value = s + (formvals[n] - p0); 1184 } 1185 } 1186 else 1187 #endif 1188 for (n = 1; n < mac->arity; n++) 1189 *(formargs[n] - 1) = ','; 1190 if (old.value) 1191 { 1192 if ((i0 & SYM_FUNCTION) != (sym->flags & SYM_FUNCTION) || old.arity != mac->arity || !streq(old.value, mac->value)) goto redefined; 1193 if (!old.formals) 1194 { 1195 if (mac->formals) goto redefined; 1196 } 1197 else if (mac->formals) 1198 { 1199 #if MACKEYARGS 1200 if (pp.option & KEYARGS) 1201 { 1202 for (n = 0; n < mac->arity; n++) 1203 if (!streq(mac->formkeys[n].name, old.formkeys[n].name) || !streq(mac->formkeys[n].value, old.formkeys[n].value)) 1204 goto redefined; 1205 } 1206 else 1207 #endif 1208 if (!streq(mac->formals, old.formals)) goto redefined; 1209 } 1210 #if MACKEYARGS 1211 if (pp.option & KEYARGS) 1212 { 1213 if (mac->formkeys) free(mac->formkeys); 1214 mac->formkeys = old.formkeys; 1215 } 1216 else 1217 #endif 1218 { 1219 if (mac->formals) free(mac->formals); 1220 mac->formals = old.formals; 1221 } 1222 free(mac->value); 1223 mac->value = old.value; 1224 goto benign; 1225 redefined: 1226 if (!(pp.mode & HOSTED) || !(i0 & SYM_INITIAL)) 1227 error(1, "%s redefined", sym->name); 1228 #if MACKEYARGS 1229 if ((pp.option & KEYARGS) && mac->formkeys) 1230 free(mac->formkeys); 1231 #endif 1232 #if MACKEYARGS 1233 if (!(pp.option & KEYARGS)) 1234 #endif 1235 if (old.formals) free(old.formals); 1236 free(old.value); 1237 } 1238 else if (!pp.truncate) ppfsm(FSM_MACRO, sym->name); 1239 mac->value = newof(mac->value, char, (mac->size = p - mac->value) + 1, 0); 1240 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))) 1241 { 1242 ppsync(); 1243 ppprintf("#%s %s", dirname(DEFINE), sym->name); 1244 if (sym->flags & SYM_FUNCTION) 1245 { 1246 ppputchar('('); 1247 if (mac->formals) 1248 ppprintf("%s", mac->formals); 1249 ppputchar(')'); 1250 } 1251 if ((p = mac->value) && *p) 1252 { 1253 ppputchar(' '); 1254 i0 = 0; 1255 while (n = *p++) 1256 { 1257 if (n != MARK || (n = *p++) == MARK) 1258 { 1259 ppputchar(n); 1260 i0 = ppisid(n); 1261 } 1262 else 1263 { 1264 if (n == 'Q') 1265 ppputchar('#'); 1266 else if (i0) 1267 { 1268 ppputchar('#'); 1269 ppputchar('#'); 1270 } 1271 s = formargs[*p++ - ARGOFFSET]; 1272 while ((n = *s++) && n != ',') 1273 ppputchar(n); 1274 if (ppisid(*p) || *p == MARK) 1275 { 1276 ppputchar('#'); 1277 ppputchar('#'); 1278 } 1279 i0 = 0; 1280 } 1281 ppcheckout(); 1282 } 1283 } 1284 emitted = 1; 1285 } 1286 benign: 1287 if (pp.mode & BUILTIN) sym->flags |= SYM_BUILTIN; 1288 if (pp.option & FINAL) sym->flags |= SYM_FINAL; 1289 if (pp.mode & INIT) sym->flags |= SYM_INIT; 1290 if (pp.option & INITIAL) sym->flags |= SYM_INITIAL; 1291 if (pp.state & NOEXPAND) sym->flags |= SYM_NOEXPAND; 1292 if (pp.option & PREDEFINED) sym->flags |= SYM_PREDEFINED; 1293 if (pp.mode & READONLY) sym->flags |= SYM_READONLY; 1294 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); 1295 break; 1296 assertion: 1297 c = pplex(); 1298 if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1299 error(1, "#%s #%s: assertions are non-standard", dirname(directive), pptokstr(pp.token, 0)); 1300 if (c != T_ID) 1301 { 1302 error(2, "%s: invalid predicate name", pptokstr(pp.token, 0)); 1303 goto eatdirective; 1304 } 1305 switch ((int)hashref(pp.strtab, pp.token)) 1306 { 1307 case X_DEFINED: 1308 case X_EXISTS: 1309 case X_STRCMP: 1310 error(2, "%s is a builtin predicate", pp.token); 1311 goto eatdirective; 1312 case X_SIZEOF: 1313 error(2, "%s cannot be a predicate", pp.token); 1314 goto eatdirective; 1315 } 1316 strcpy(pp.tmpbuf, pp.token); 1317 switch (pppredargs()) 1318 { 1319 case T_ID: 1320 case T_STRING: 1321 assert(directive, pp.tmpbuf, pp.args); 1322 break; 1323 case 0: 1324 assert(directive, pp.tmpbuf, NiL); 1325 break; 1326 default: 1327 error(2, "invalid predicate argument list"); 1328 goto eatdirective; 1329 } 1330 break; 1331 tuple: 1332 pp.state |= DEFINITION|NOEXPAND|NOSPACE; 1333 rp = 0; 1334 tp = mac->tuple; 1335 if (!tp && !mac->value) 1336 ppfsm(FSM_MACRO, sym->name); 1337 while ((c = pplex()) && c != '>' && c != '\n') 1338 { 1339 for (; tp; tp = tp->nomatch) 1340 if (streq(tp->token, pp.token)) 1341 break; 1342 if (!tp) 1343 { 1344 if (!(tp = newof(0, struct pptuple, 1, strlen(pp.token)))) 1345 error(3, "out of space"); 1346 strcpy(tp->token, pp.token); 1347 if (rp) 1348 { 1349 tp->nomatch = rp; 1350 rp->nomatch = tp; 1351 } 1352 else 1353 { 1354 tp->nomatch = mac->tuple; 1355 mac->tuple = tp; 1356 } 1357 } 1358 rp = tp; 1359 tp = tp->match; 1360 } 1361 pp.state &= ~NOSPACE; 1362 if (!rp || c != '>') 1363 error(2, "%s: > omitted in tuple macro definition", sym->name); 1364 else 1365 { 1366 n = 2 * MAXTOKEN; 1367 p = v = oldof(0, char, 0, n); 1368 while ((c = pplex()) && c != '\n') 1369 if (p > v || c != ' ') 1370 { 1371 STRCOPY(p, pp.token, s); 1372 if (p > &v[n - MAXTOKEN] && (s = newof(v, char, n += MAXTOKEN, 0)) != v) 1373 { 1374 c = p - v; 1375 v = s; 1376 p = v + c; 1377 } 1378 } 1379 while (p > v && *(p - 1) == ' ') 1380 p--; 1381 n = p - v; 1382 tp = newof(0, struct pptuple, 1, n); 1383 strcpy(tp->token, v); 1384 tp->match = rp->match; 1385 rp->match = tp; 1386 } 1387 goto benign; 1388 case WARNING: 1389 if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1390 error(1, "#%s: non-standard directive", pp.token); 1391 /*FALLTHROUGH*/ 1392 case ERROR: 1393 pp.state &= ~DISABLE; 1394 p = pp.tmpbuf; 1395 while ((c = pplex()) != '\n') 1396 if (p + strlen(pp.token) < &pp.tmpbuf[MAXTOKEN]) 1397 { 1398 STRCOPY(p, pp.token, s); 1399 pp.state &= ~NOSPACE; 1400 } 1401 *p = 0; 1402 p = *pp.tmpbuf ? pp.tmpbuf : ((directive == WARNING) ? "user warning" : "user error"); 1403 n = (directive == WARNING) ? 1 : 3; 1404 error(n, "%s", p); 1405 break; 1406 case LET: 1407 n2 = error_info.line; 1408 if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1409 error(1, "#%s: non-standard directive", pp.token); 1410 if (!(sym = macsym(c = pplex()))) goto eatdirective; 1411 if ((c = pplex()) != '=') 1412 { 1413 error(2, "%s: = expected", sym->name); 1414 goto eatdirective; 1415 } 1416 sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_MULTILINE|SYM_PREDEFINED|SYM_VARIADIC); 1417 mac = sym->macro; 1418 mac->arity = 0; 1419 if (mac->value) 1420 { 1421 if (!(sym->flags & SYM_REDEFINE) && !sym->hidden) 1422 error(1, "%s: redefined", sym->name); 1423 #if MACKEYARGS 1424 if ((pp.option & KEYARGS) && mac->formkeys) free(mac->formkeys); 1425 else 1426 #endif 1427 free(mac->formals); 1428 mac->formals = 0; 1429 n = strlen(mac->value) + 1; 1430 } 1431 else 1432 { 1433 ppfsm(FSM_MACRO, sym->name); 1434 n = 0; 1435 } 1436 n1 = ppexpr(&i1); 1437 if (i1) c = sfsprintf(pp.tmpbuf, MAXTOKEN, "%luU", n1); 1438 else c = sfsprintf(pp.tmpbuf, MAXTOKEN, "%ld", n1); 1439 if (n < ++c) 1440 { 1441 if (mac->value) free(mac->value); 1442 mac->value = oldof(0, char, 0, c); 1443 } 1444 strcpy(mac->value, pp.tmpbuf); 1445 sym->flags |= SYM_REDEFINE; 1446 c = (pp.state & NEWLINE) ? '\n' : ' '; 1447 goto benign; 1448 case LINE: 1449 pp.state &= ~DISABLE; 1450 if ((c = pplex()) == '#') 1451 { 1452 c = pplex(); 1453 directive = INCLUDE; 1454 } 1455 if (c != T_DECIMAL && c != T_OCTAL) 1456 { 1457 error(1, "#%s: line number expected", dirname(LINE)); 1458 goto eatdirective; 1459 } 1460 linesync: 1461 n = error_info.line; 1462 error_info.line = strtol(pp.token, NiL, 0); 1463 if (error_info.line == 0 && directive == LINE && (pp.state & STRICT) && !(pp.mode & HOSTED)) 1464 error(1, "#%s: line number should be > 0", dirname(LINE)); 1465 pp.state &= ~DISABLE; 1466 pp.state |= STRIP; 1467 switch (c = pplex()) 1468 { 1469 case T_STRING: 1470 s = error_info.file; 1471 if (*(p = pp.token)) pathcanon(p, 0); 1472 fp = ppsetfile(p); 1473 error_info.file = fp->name; 1474 if (error_info.line == 1) 1475 ppmultiple(fp, INC_TEST); 1476 switch (c = pplex()) 1477 { 1478 case '\n': 1479 break; 1480 case T_DECIMAL: 1481 case T_OCTAL: 1482 if (directive == LINE && (pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1483 error(1, "#%s: integer file type argument is non-standard", dirname(LINE)); 1484 break; 1485 default: 1486 error(1, "#%s: integer file type argument expected", dirname(LINE)); 1487 break; 1488 } 1489 if (directive == LINE) pp.in->flags &= ~IN_ignoreline; 1490 else if (pp.incref) 1491 { 1492 if (error_info.file != s) 1493 { 1494 switch (*pp.token) 1495 { 1496 case PP_sync_push: 1497 if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1498 else (*pp.incref)(s, error_info.file, n, PP_SYNC_PUSH); 1499 break; 1500 case PP_sync_pop: 1501 if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1502 else (*pp.incref)(s, error_info.file, n - 1, PP_SYNC_POP); 1503 break; 1504 case PP_sync_ignore: 1505 if (pp.insert) (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1506 else 1507 { 1508 (*pp.incref)(s, error_info.file, n, PP_SYNC_IGNORE); 1509 error_info.file = s; 1510 } 1511 break; 1512 default: 1513 if (*s) 1514 { 1515 if (fp == pp.insert) 1516 pp.insert = 0; 1517 else if (error_info.line == 1 && !pp.insert) 1518 (*pp.incref)(s, error_info.file, n, PP_SYNC_PUSH); 1519 else 1520 { 1521 if (!pp.insert) pp.insert = ppgetfile(s); 1522 (*pp.incref)(s, error_info.file, n, PP_SYNC_INSERT); 1523 } 1524 } 1525 break; 1526 } 1527 } 1528 } 1529 break; 1530 case '\n': 1531 break; 1532 default: 1533 error(1, "#%s: \"file-name\" expected", dirname(LINE)); 1534 break; 1535 } 1536 if (directive == LINE && (pp.in->flags & IN_ignoreline)) 1537 error_info.line = n + 1; 1538 else 1539 { 1540 pp.hidden = 0; 1541 pp.state &= ~HIDDEN; 1542 if (pp.linesync) 1543 { 1544 #if CATSTRINGS 1545 if (pp.state & JOINING) pp.state |= HIDDEN|SYNCLINE; 1546 else 1547 #endif 1548 { 1549 s = pp.lineid; 1550 n = pp.flags; 1551 if (directive == LINE) 1552 { 1553 pp.flags &= ~PP_linetype; 1554 if (pp.macref) pp.lineid = dirname(LINE); 1555 } 1556 (*pp.linesync)(error_info.line, error_info.file); 1557 pp.flags = n; 1558 pp.lineid = s; 1559 } 1560 } 1561 } 1562 directive = LINE; 1563 break; 1564 case PRAGMA: 1565 /* 1566 * #pragma [STDC] [pass:] [no]option [arg ...] 1567 * 1568 * pragma args are not expanded by default 1569 * 1570 * if STDC is present then it is silently passed on 1571 * 1572 * if pass is pp.pass then the option is used 1573 * and verified but is not passed on 1574 * 1575 * if pass is omitted then the option is passed on 1576 * 1577 * otherwise if pass is non-null and not pp.pass then 1578 * the option is passed on but not used 1579 * 1580 * if the line does not match this form then 1581 * it is passed on unchanged 1582 * 1583 * #directive pass: option [...] 1584 * ^ ^ ^ ^ ^ ^ ^ ^ 1585 * pp.valbuf p0 p1 p2 p3 p4 p5 p6 1586 * 1587 * p? 0 if component omitted 1588 * i0 0 if ``no''option 1589 */ 1590 1591 p = pp.valbuf; 1592 *p++ = '#'; 1593 STRCOPY(p, pp.token, s); 1594 p0 = p; 1595 if (pp.option & PRAGMAEXPAND) 1596 pp.state &= ~DISABLE; 1597 if (!(p6 = getline(p, &pp.valbuf[MAXTOKEN], !!(pp.option & PRAGMAEXPAND)))) 1598 { 1599 *p0 = 0; 1600 error(2, "%s: directive too long", pp.valbuf); 1601 c = 0; 1602 goto eatdirective; 1603 } 1604 p1 = ++p; 1605 while (ppisid(*p)) 1606 p++; 1607 if (p == p1) 1608 { 1609 p5 = p; 1610 p4 = 0; 1611 p3 = 0; 1612 p2 = 0; 1613 p1 = 0; 1614 } 1615 else if (*p != ':') 1616 { 1617 p5 = *p ? p + (*p == ' ') : 0; 1618 p4 = p; 1619 p3 = p1; 1620 p2 = 0; 1621 p1 = 0; 1622 } 1623 else 1624 { 1625 p2 = p++; 1626 p3 = p; 1627 while (ppisid(*p)) 1628 p++; 1629 if (p == p3) 1630 { 1631 p4 = p1; 1632 p3 = 0; 1633 p2 = 0; 1634 p1 = 0; 1635 } 1636 else 1637 p4 = p; 1638 p5 = *p4 ? p4 + (*p4 == ' ') : 0; 1639 } 1640 if (!p1 && p3 && (p4 - p3) == 4 && strneq(p3, "STDC", 4)) 1641 goto pass; 1642 if ((pp.state & WARN) && (pp.mode & (HOSTED|RELAX|PEDANTIC)) == PEDANTIC) 1643 error(1, "#%s: non-standard directive", dirname(PRAGMA)); 1644 i0 = !p3 || *p3 != 'n' || *(p3 + 1) != 'o'; 1645 if (!p3) 1646 goto checkmap; 1647 if (p1) 1648 { 1649 *p2 = 0; 1650 n = streq(p1, pp.pass); 1651 *p2 = ':'; 1652 if (!n) 1653 goto checkmap; 1654 } 1655 else 1656 n = 0; 1657 i2 = *p4; 1658 *p4 = 0; 1659 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)) 1660 i1 = 0; 1661 if ((pp.state & (COMPATIBILITY|STRICT)) == STRICT && !(pp.mode & (HOSTED|RELAX))) 1662 { 1663 if (pp.optflags[i1] & OPT_GLOBAL) 1664 goto donedirective; 1665 if (n || (pp.mode & WARN)) 1666 { 1667 n = 0; 1668 error(1, "#%s: non-standard directive ignored", dirname(PRAGMA)); 1669 } 1670 i1 = 0; 1671 } 1672 if (!n) 1673 { 1674 if (!(pp.optflags[i1] & OPT_GLOBAL)) 1675 { 1676 *p4 = i2; 1677 goto checkmap; 1678 } 1679 if (!(pp.optflags[i1] & OPT_PASS)) 1680 n = 1; 1681 } 1682 else if (!i1) 1683 error(2, "%s: unknown option", p1); 1684 else if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 1685 error(1, "%s: non-standard option", p1); 1686 p = p5; 1687 switch (i1) 1688 { 1689 case X_ALLMULTIPLE: 1690 ppop(PP_MULTIPLE, i0); 1691 break; 1692 case X_ALLPOSSIBLE: 1693 setoption(ALLPOSSIBLE, i0); 1694 break; 1695 case X_BUILTIN: 1696 setmode(BUILTIN, i0); 1697 break; 1698 case X_CATLITERAL: 1699 setmode(CATLITERAL, i0); 1700 if (pp.mode & CATLITERAL) 1701 setoption(STRINGSPLIT, 0); 1702 break; 1703 case X_CDIR: 1704 tokop(PP_CDIR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 1705 break; 1706 case X_CHECKPOINT: 1707 #if CHECKPOINT 1708 ppload(p); 1709 #else 1710 error(3, "%s: preprocessor not compiled with checkpoint enabled", p3); 1711 #endif 1712 break; 1713 case X_CHOP: 1714 tokop(PP_CHOP, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 1715 break; 1716 case X_COMPATIBILITY: 1717 ppop(PP_COMPATIBILITY, i0); 1718 break; 1719 case X_DEBUG: 1720 error_info.trace = i0 ? (p ? -strtol(p, NiL, 0) : -1) : 0; 1721 break; 1722 case X_ELSEIF: 1723 setoption(ELSEIF, i0); 1724 break; 1725 case X_EXTERNALIZE: 1726 setmode(EXTERNALIZE, i0); 1727 break; 1728 case X_FINAL: 1729 setoption(FINAL, i0); 1730 break; 1731 case X_HEADEREXPAND: 1732 setoption(HEADEREXPAND, i0); 1733 break; 1734 case X_HEADEREXPANDALL: 1735 setoption(HEADEREXPANDALL, i0); 1736 break; 1737 case X_HIDE: 1738 case X_NOTE: 1739 PUSH_LINE(p); 1740 /* UNDENT...*/ 1741 while (c = pplex()) 1742 { 1743 if (c != T_ID) error(1, "%s: %s: identifier expected", p3, pp.token); 1744 else if (sym = ppsymset(pp.symtab, pp.token)) 1745 { 1746 if (i1 == X_NOTE) 1747 { 1748 sym->flags &= ~SYM_NOTICED; 1749 ppfsm(FSM_MACRO, sym->name); 1750 } 1751 else if (i0) 1752 { 1753 if (!sym->hidden && !(sym->hidden = newof(0, struct pphide, 1, 0))) 1754 error(3, "out of space"); 1755 if (!sym->macro) 1756 ppfsm(FSM_MACRO, sym->name); 1757 if (!sym->hidden->level++) 1758 { 1759 pp.hiding++; 1760 if (sym->macro && !(sym->flags & (SYM_ACTIVE|SYM_READONLY))) 1761 { 1762 sym->hidden->macro = sym->macro; 1763 sym->macro = 0; 1764 sym->hidden->flags = sym->flags; 1765 sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 1766 } 1767 } 1768 } 1769 else if (sym->hidden) 1770 { 1771 if ((mac = sym->macro) && !(sym->flags & (SYM_ACTIVE|SYM_READONLY))) 1772 { 1773 if (mac->formals) free(mac->formals); 1774 free(mac->value); 1775 free(mac); 1776 sym->macro = 0; 1777 sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 1778 } 1779 if (!--sym->hidden->level) 1780 { 1781 pp.hiding--; 1782 if (sym->hidden->macro) 1783 { 1784 sym->macro = sym->hidden->macro; 1785 sym->flags = sym->hidden->flags; 1786 } 1787 free(sym->hidden); 1788 sym->hidden = 0; 1789 } 1790 } 1791 } 1792 } 1793 /*...INDENT*/ 1794 POP_LINE(); 1795 break; 1796 case X_HOSTDIR: 1797 tokop(PP_HOSTDIR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 1798 break; 1799 case X_HOSTED: 1800 setmode(HOSTED, i0); 1801 break; 1802 case X_HOSTEDTRANSITION: 1803 setmode(HOSTEDTRANSITION, i0); 1804 break; 1805 case X_ID: 1806 tokop(PP_ID, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 1807 break; 1808 case X_IGNORE: 1809 tokop(PP_IGNORE, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 1810 break; 1811 case X_INCLUDE: 1812 tokop(PP_INCLUDE, p3, p, i0, TOKOP_STRING|TOKOP_DUP); 1813 break; 1814 case X_INITIAL: 1815 setoption(INITIAL, i0); 1816 break; 1817 case X_KEYARGS: 1818 ppop(PP_KEYARGS, i0); 1819 break; 1820 case X_LINE: 1821 if (pp.linesync) pp.olinesync = pp.linesync; 1822 pp.linesync = i0 ? pp.olinesync : (PPLINESYNC)0; 1823 break; 1824 case X_LINEBASE: 1825 ppop(PP_LINEBASE, i0); 1826 break; 1827 case X_LINEFILE: 1828 ppop(PP_LINEFILE, i0); 1829 break; 1830 case X_LINEID: 1831 ppop(PP_LINEID, i0 ? p : (char*)0); 1832 break; 1833 case X_LINETYPE: 1834 ppop(PP_LINETYPE, i0 ? (p ? strtol(p, NiL, 0) : 1) : 0); 1835 break; 1836 case X_MACREF: 1837 if (!p) 1838 { 1839 if (i0 && !pp.macref) 1840 { 1841 ppop(PP_LINETYPE, 1); 1842 ppop(PP_MACREF, ppmacref); 1843 } 1844 else error(2, "%s: option cannot be unset", p3); 1845 } 1846 else if (s = strchr(p, ' ')) 1847 { 1848 if (pp.macref && (s = strchr(p, ' '))) 1849 { 1850 *s++ = 0; 1851 c = strtol(s, NiL, 0); 1852 var.type = pp.truncate; 1853 pp.truncate = PPTOKSIZ; 1854 (*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); 1855 pp.truncate = var.type; 1856 } 1857 error_info.line -= 2; 1858 } 1859 break; 1860 case X_MAP: 1861 /*UNDENT*/ 1862 /* 1863 * #pragma pp:map [id ...] "/from/[,/to/]" [ "/old/new/[glnu]" ... ] 1864 */ 1865 1866 if (!i0) 1867 { 1868 error(2, "%s: option cannot be unset", p3); 1869 goto donedirective; 1870 } 1871 if (!p5) 1872 { 1873 error(2, "%s: address argument expected", p3); 1874 goto donedirective; 1875 } 1876 PUSH_LINE(p5); 1877 while ((c = pplex()) == T_ID) 1878 { 1879 sfsprintf(pp.tmpbuf, MAXTOKEN, "__%s__", s = pp.token); 1880 if (c = (int)hashget(pp.dirtab, s)) 1881 { 1882 hashput(pp.dirtab, 0, 0); 1883 hashput(pp.dirtab, pp.tmpbuf, c); 1884 } 1885 if (c = (int)hashget(pp.strtab, s)) 1886 { 1887 hashput(pp.strtab, 0, 0); 1888 hashput(pp.strtab, pp.tmpbuf, c); 1889 } 1890 } 1891 if (c != T_STRING || !*(s = pp.token)) 1892 { 1893 if (c) 1894 error(2, "%s: %s: address argument expected", p3, pptokstr(pp.token, 0)); 1895 goto eatmap; 1896 } 1897 map = newof(0, struct map, 1, 0); 1898 1899 /* 1900 * /from/ 1901 */ 1902 1903 if (i0 = regcomp(&map->re, s, REG_AUGMENTED|REG_DELIMITED|REG_LENIENT|REG_NULL)) 1904 regfatal(&map->re, 3, i0); 1905 if (*(s += map->re.re_npat)) 1906 { 1907 error(2, "%s: invalid characters after pattern: %s ", p3, s); 1908 goto eatmap; 1909 } 1910 1911 /* 1912 * /old/new/[flags] 1913 */ 1914 1915 edit = 0; 1916 while ((c = pplex()) == T_STRING) 1917 { 1918 if (!*(s = pp.token)) 1919 { 1920 error(2, "%s: substitution argument expected", p3); 1921 goto eatmap; 1922 } 1923 if (edit) 1924 edit = edit->next = newof(0, struct edit, 1, 0); 1925 else 1926 edit = map->edit = newof(0, struct edit, 1, 0); 1927 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))) 1928 s += edit->re.re_npat; 1929 if (i0) 1930 regfatal(&edit->re, 3, i0); 1931 if (*s) 1932 { 1933 error(2, "%s: invalid characters after substitution: %s ", p3, s); 1934 goto eatmap; 1935 } 1936 } 1937 if (c) 1938 { 1939 error(2, "%s: %s: substitution argument expected", p3, pptokstr(pp.token, 0)); 1940 goto eatmap; 1941 } 1942 map->next = (struct map*)pp.maps; 1943 pp.maps = (char*)map; 1944 eatmap: 1945 POP_LINE(); 1946 /*INDENT*/ 1947 break; 1948 case X_MAPINCLUDE: 1949 ppmapinclude(NiL, p5); 1950 break; 1951 case X_MODERN: 1952 setoption(MODERN, i0); 1953 break; 1954 case X_MULTIPLE: 1955 n = 1; 1956 if (pp.in->type == IN_FILE) 1957 ppmultiple(ppsetfile(error_info.file), i0 ? INC_CLEAR : INC_TEST); 1958 break; 1959 case X_NATIVE: 1960 setoption(NATIVE, i0); 1961 break; 1962 case X_OPSPACE: 1963 ppfsm(FSM_OPSPACE, i0 ? p4 : (char*)0); 1964 break; 1965 case X_PASSTHROUGH: 1966 ppop(PP_PASSTHROUGH, i0); 1967 break; 1968 case X_PEDANTIC: 1969 ppop(PP_PEDANTIC, i0); 1970 break; 1971 case X_PLUSCOMMENT: 1972 ppop(PP_PLUSCOMMENT, i0); 1973 break; 1974 case X_PLUSPLUS: 1975 ppop(PP_PLUSPLUS, i0); 1976 break; 1977 case X_PLUSSPLICE: 1978 setoption(PLUSSPLICE, i0); 1979 break; 1980 case X_PRAGMAEXPAND: 1981 setoption(PRAGMAEXPAND, i0); 1982 break; 1983 case X_PRAGMAFLAGS: 1984 tokop(PP_PRAGMAFLAGS, p3, p, i0, 0); 1985 break; 1986 case X_PREDEFINED: 1987 setoption(PREDEFINED, i0); 1988 break; 1989 case X_PREFIX: 1990 setoption(PREFIX, i0); 1991 break; 1992 case X_PRESERVE: 1993 setoption(PRESERVE, i0); 1994 if (pp.option & PRESERVE) 1995 { 1996 setmode(CATLITERAL, 0); 1997 ppop(PP_COMPATIBILITY, 1); 1998 ppop(PP_TRANSITION, 0); 1999 ppop(PP_PLUSCOMMENT, 1); 2000 ppop(PP_SPACEOUT, 1); 2001 setoption(STRINGSPAN, 1); 2002 setoption(STRINGSPLIT, 0); 2003 ppop(PP_HOSTDIR, "-", 1); 2004 } 2005 break; 2006 case X_PROTOTYPED: 2007 /* 2008 * this option doesn't bump the token count 2009 */ 2010 2011 n = 1; 2012 directive = ENDIF; 2013 #if PROTOTYPE 2014 setoption(PROTOTYPED, i0); 2015 #else 2016 error(1, "preprocessor not compiled with prototype conversion enabled"); 2017 #endif 2018 break; 2019 case X_PROTO: 2020 setoption(NOPROTO, !i0); 2021 break; 2022 case X_QUOTE: 2023 tokop(PP_QUOTE, p3, p, i0, TOKOP_UNSET|TOKOP_STRING); 2024 break; 2025 case X_READONLY: 2026 setmode(READONLY, i0); 2027 break; 2028 case X_REGUARD: 2029 setoption(REGUARD, i0); 2030 break; 2031 case X_RESERVED: 2032 tokop(PP_RESERVED, p3, p, i0, 0); 2033 break; 2034 case X_SPACEOUT: 2035 if (!(pp.state & (COMPATIBILITY|COMPILE))) 2036 ppop(PP_SPACEOUT, i0); 2037 break; 2038 case X_SPLICECAT: 2039 setoption(SPLICECAT, i0); 2040 break; 2041 case X_SPLICESPACE: 2042 setoption(SPLICESPACE, i0); 2043 break; 2044 case X_STANDARD: 2045 tokop(PP_STANDARD, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 2046 break; 2047 case X_STRICT: 2048 ppop(PP_STRICT, i0); 2049 break; 2050 case X_STRINGSPAN: 2051 setoption(STRINGSPAN, i0); 2052 break; 2053 case X_STRINGSPLIT: 2054 setoption(STRINGSPLIT, i0); 2055 if (pp.option & STRINGSPLIT) 2056 setmode(CATLITERAL, 0); 2057 break; 2058 case X_SYSTEM_HEADER: 2059 if (i0) 2060 { 2061 pp.mode |= HOSTED; 2062 pp.flags |= PP_hosted; 2063 pp.in->flags |= IN_hosted; 2064 } 2065 else 2066 { 2067 pp.mode &= ~HOSTED; 2068 pp.flags &= ~PP_hosted; 2069 pp.in->flags &= ~PP_hosted; 2070 } 2071 break; 2072 case X_TEST: 2073 ppop(PP_TEST, p); 2074 break; 2075 case X_TEXT: 2076 if (!(pp.option & KEEPNOTEXT)) 2077 setstate(NOTEXT, !i0); 2078 break; 2079 case X_TRANSITION: 2080 ppop(PP_TRANSITION, i0); 2081 if (pp.state & TRANSITION) ppop(PP_COMPATIBILITY, i0); 2082 break; 2083 case X_TRUNCATE: 2084 ppop(PP_TRUNCATE, i0 ? (p ? strtol(p, NiL, 0) : TRUNCLENGTH) : 0); 2085 break; 2086 case X_VENDOR: 2087 tokop(PP_VENDOR, p3, p, i0, TOKOP_UNSET|TOKOP_STRING|TOKOP_DUP); 2088 break; 2089 case X_VERSION: 2090 if (!(*pp.control & SKIP) && pp.pragma && !(pp.state & NOTEXT)) 2091 { 2092 sfsprintf(pp.tmpbuf, MAXTOKEN, "\"%s\"", pp.version); 2093 (*pp.pragma)(dirname(PRAGMA), pp.pass, p3, pp.tmpbuf, !n); 2094 if (pp.linesync && !n) 2095 (*pp.linesync)(error_info.line, error_info.file); 2096 emitted = 1; 2097 } 2098 break; 2099 case X_WARN: 2100 ppop(PP_WARN, i0); 2101 break; 2102 case X_ZEOF: 2103 setoption(ZEOF, i0); 2104 break; 2105 #if DEBUG 2106 case 0: 2107 case X_INCLUDED: 2108 case X_NOTICED: 2109 case X_OPTION: 2110 case X_STATEMENT: 2111 break; 2112 default: 2113 error(PANIC, "%s: option recognized but not implemented", pp.valbuf); 2114 break; 2115 #endif 2116 } 2117 *p4 = i2; 2118 if (!n) 2119 goto checkmap; 2120 goto donedirective; 2121 case RENAME: 2122 if ((pp.state & STRICT) && !(pp.mode & (HOSTED|RELAX))) 2123 error(1, "#%s: non-standard directive", pp.token); 2124 if ((c = pplex()) != T_ID) 2125 { 2126 error(1, "%s: invalid macro name", pptokstr(pp.token, 0)); 2127 goto eatdirective; 2128 } 2129 if (!(sym = pprefmac(pp.token, REF_DELETE)) || !sym->macro) 2130 goto eatdirective; 2131 if (sym->flags & (SYM_ACTIVE|SYM_READONLY)) 2132 { 2133 if (!(pp.option & ALLPOSSIBLE)) 2134 error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active"); 2135 goto eatdirective; 2136 } 2137 if ((c = pplex()) != T_ID) 2138 { 2139 error(1, "%s: invalid macro name", pptokstr(pp.token, 0)); 2140 goto eatdirective; 2141 } 2142 var.symbol = pprefmac(pp.token, REF_CREATE); 2143 if (mac = var.symbol->macro) 2144 { 2145 if (var.symbol->flags & (SYM_ACTIVE|SYM_READONLY)) 2146 { 2147 if (!(pp.option & ALLPOSSIBLE)) 2148 error(2, "%s: macro is %s", var.symbol->name, (var.symbol->flags & SYM_READONLY) ? "readonly" : "active"); 2149 goto eatdirective; 2150 } 2151 if (!(pp.mode & HOSTED) || !(var.symbol->flags & SYM_INITIAL)) 2152 error(1, "%s redefined", var.symbol->name); 2153 if (mac->formals) free(mac->formals); 2154 free(mac->value); 2155 free(mac); 2156 } 2157 ppfsm(FSM_MACRO, var.symbol->name); 2158 var.symbol->flags = sym->flags; 2159 sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 2160 var.symbol->macro = sym->macro; 2161 sym->macro = 0; 2162 break; 2163 case UNDEF: 2164 if ((c = pplex()) != T_ID) 2165 { 2166 error(1, "%s: invalid macro name", pptokstr(pp.token, 0)); 2167 goto eatdirective; 2168 } 2169 if (sym = pprefmac(pp.token, REF_DELETE)) 2170 { 2171 if (mac = sym->macro) 2172 { 2173 if (sym->flags & (SYM_ACTIVE|SYM_READONLY)) 2174 { 2175 if (!(pp.option & ALLPOSSIBLE)) 2176 error(2, "%s: macro is %s", sym->name, (sym->flags & SYM_READONLY) ? "readonly" : "active"); 2177 goto eatdirective; 2178 } 2179 if (mac->formals) free(mac->formals); 2180 free(mac->value); 2181 free(mac); 2182 mac = sym->macro = 0; 2183 } 2184 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))) 2185 { 2186 ppsync(); 2187 ppprintf("#%s %s", dirname(UNDEF), sym->name); 2188 emitted = 1; 2189 } 2190 sym->flags &= ~(SYM_BUILTIN|SYM_FUNCTION|SYM_INIT|SYM_MULTILINE|SYM_PREDEFINED|SYM_REDEFINE|SYM_VARIADIC); 2191 n2 = error_info.line; 2192 goto benign; 2193 } 2194 else pprefmac(pp.token, REF_UNDEF); 2195 break; 2196 #if DEBUG 2197 default: 2198 error(PANIC, "#%s: directive recognized but not implemented", pp.token); 2199 goto eatdirective; 2200 #endif 2201 } 2202 break; 2203 case '\n': 2204 break; 2205 default: 2206 error(1, "%s: invalid directive name", pptokstr(pp.token, 0)); 2207 goto eatdirective; 2208 } 2209 enddirective: 2210 #if COMPATIBLE 2211 if (c != '\n' && !(pp.state & COMPATIBILITY)) 2212 #else 2213 if (c != '\n') 2214 #endif 2215 { 2216 pp.state |= DISABLE|NOSPACE; 2217 if ((c = pplex()) != '\n' && (pp.mode & (HOSTED|PEDANTIC)) == PEDANTIC) 2218 error(1, "%s: invalid characters after directive", pptokstr(pp.token, 0)); 2219 } 2220 eatdirective: 2221 if (c != '\n') 2222 { 2223 pp.state |= DISABLE; 2224 while (pplex() != '\n'); 2225 } 2226 donedirective: 2227 #if _HUH_2002_05_09 2228 if (!(pp.state & EOF2NL)) 2229 error(2, "%s in directive", pptokchr(0)); 2230 #endif 2231 pp.state &= ~RESTORE; 2232 pp.mode &= ~RELAX; 2233 if (!(*pp.control & SKIP)) 2234 { 2235 pp.state |= restore; 2236 switch (directive) 2237 { 2238 case LINE: 2239 return 0; 2240 case INCLUDE: 2241 if (pp.include) 2242 { 2243 error_info.line++; 2244 PUSH_FILE(pp.include, n); 2245 if (!pp.vendor && (pp.found->type & TYPE_VENDOR)) 2246 pp.vendor = 1; 2247 pp.include = 0; 2248 return 0; 2249 } 2250 if (pp.incref) 2251 (*pp.incref)(error_info.file, ppgetfile(pp.path)->name, error_info.line, PP_SYNC_IGNORE); 2252 else if (pp.linesync && pp.macref) 2253 { 2254 pp.flags |= PP_lineignore; 2255 (*pp.linesync)(error_info.line, ppgetfile(pp.path)->name); 2256 } 2257 /*FALLTHROUGH*/ 2258 default: 2259 pp.in->flags |= IN_tokens; 2260 /*FALLTHROUGH*/ 2261 case ENDIF: 2262 error_info.line++; 2263 if (emitted) 2264 { 2265 ppputchar('\n'); 2266 ppcheckout(); 2267 } 2268 else 2269 { 2270 pp.state |= HIDDEN; 2271 pp.hidden++; 2272 } 2273 return 0; 2274 } 2275 } 2276 pp.state |= restore|HIDDEN|SKIPCONTROL; 2277 pp.hidden++; 2278 pp.level++; 2279 error_info.line++; 2280 return 0; 2281 } 2282 2283 /* 2284 * grow the pp nesting control stack 2285 */ 2286 2287 void 2288 ppnest(void) 2289 { 2290 register struct ppinstk* ip; 2291 int oz; 2292 int nz; 2293 long adjust; 2294 long* op; 2295 long* np; 2296 2297 oz = pp.constack; 2298 op = pp.maxcon - oz + 1; 2299 nz = oz * 2; 2300 np = newof(op, long, nz, 0); 2301 if (adjust = (np - op)) 2302 { 2303 ip = pp.in; 2304 do 2305 { 2306 if (ip->control) 2307 ip->control += adjust; 2308 } while (ip = ip->prev); 2309 } 2310 pp.control = np + oz; 2311 pp.constack = nz; 2312 pp.maxcon = np + nz - 1; 2313 } 2314