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