cpp.c (21385B)
1 #include <assert.h> 2 #include <ctype.h> 3 #include <limits.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include <time.h> 8 9 #include <scc/cstd.h> 10 #include <scc/scc.h> 11 #include "cc1.h" 12 13 struct ifstate { 14 unsigned char done; 15 unsigned char enabled; 16 unsigned char iselse; 17 }; 18 19 static unsigned ncmdlines; 20 static Symbol *symline, *symfile; 21 static struct ifstate ifstate[NR_COND]; 22 static int cppoff; 23 static struct items dirinclude; 24 25 unsigned cppctx; 26 int disexpand; 27 int disescape; 28 29 void 30 defdefine(char *name, char *val, char *source) 31 { 32 char buffer[INPUTSIZ+1]; 33 char *def, *fmt = "#define %s %s\n"; 34 Symbol *sym = &(Symbol) { 35 .name = name, 36 .flags = SDECLARED, 37 }; 38 39 if (!val) 40 val = ""; 41 if (strlen(fmt) + strlen(name) + strlen(val) > INPUTSIZ) { 42 errorp("macro definition '%s' too big", name); 43 return; 44 } 45 46 sprintf(buffer, fmt, name, val); 47 lineno = ++ncmdlines; 48 49 addinput(IPARAM, buffer, FAIL); 50 cpp(); 51 delinput(); 52 } 53 54 void 55 undefmacro(char *s) 56 { 57 killsym(lookup(NS_CPP, s, NOALLOC)); 58 } 59 60 void 61 icpp(void) 62 { 63 struct tm *tm; 64 time_t t; 65 static char sdate[14], stime[11]; 66 static struct { 67 char *name; 68 char *value; 69 } *bp, list[] = { 70 {"__STDC__", "1"}, 71 {"__STDC_HOSTED__", "1"}, 72 {"__SCC__", "1"}, 73 {"__DATE__", sdate}, 74 {"__TIME__", stime}, 75 {"__STDC_VERSION__", STDC_VERSION}, 76 {"__LINE__", NULL}, 77 {"__FILE__", NULL}, 78 {"__FLT_EVAL_METHOD__", "0"}, 79 {NULL, NULL} 80 }; 81 82 t = time(NULL); 83 tm = localtime(&t); 84 strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm); 85 strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm); 86 87 for (bp = list; bp->name; ++bp) 88 defdefine(bp->name, bp->value, "built-in"); 89 90 symline = lookup(NS_CPP, "__LINE__", ALLOC); 91 symfile = lookup(NS_CPP, "__FILE__", ALLOC); 92 93 ncmdlines = 0; 94 } 95 96 static void 97 nextcpp(Macro *mp) 98 { 99 int len, siz; 100 char *arg; 101 102 next(); 103 if (yytoken == EOFTOK) { 104 error("unterminated argument list invoking macro \"%s\"", 105 mp->sym->name); 106 } 107 108 if (yytoken == IDEN) 109 yylval.sym->flags |= SUSED; 110 111 len = strlen(yytext); 112 siz = mp->argsiz; 113 if (len+1 > INT_MAX - siz) { 114 error("too long argument invoking macro \"%s\"", 115 mp->sym->name); 116 } 117 118 arg = xrealloc(mp->arg, siz + len + 1); 119 if (siz > 0) { 120 arg[siz-1] = ' '; 121 memcpy(arg + siz, yytext, len+1); 122 } else { 123 memcpy(arg, yytext, len+1); 124 } 125 126 mp->arg = arg; 127 mp->argsiz = siz + len + 1; 128 } 129 130 static void 131 paren(Macro *mp) 132 { 133 for (;;) { 134 nextcpp(mp); 135 switch (yytoken) { 136 case ')': 137 return; 138 case '(': 139 paren(mp); 140 break; 141 } 142 } 143 } 144 145 static char * 146 parameter(Macro *mp) 147 { 148 int siz; 149 char *s, *begin, *end; 150 Input *ip = input; 151 152 mp->arg = NULL; 153 mp->argsiz = 0; 154 for (;;) { 155 nextcpp(mp); 156 switch (yytoken) { 157 case ')': 158 case ',': 159 /* remove "," or ")"*/ 160 begin = mp->arg; 161 end = mp->arg + mp->argsiz - 2; 162 163 while (end > begin && isspace(end[-1])) 164 --end; 165 while (begin < end && isspace(begin[0])) 166 ++begin; 167 168 siz = end - begin; 169 s = memcpy(xmalloc(siz+1), begin, siz); 170 s[siz] = '\0'; 171 free(mp->arg); 172 173 return s; 174 case '(': 175 paren(mp); 176 break; 177 } 178 } 179 } 180 181 static int 182 parsepars(Macro *mp) 183 { 184 int n; 185 186 if (mp->npars == -1) 187 return 1; 188 if (ahead() != '(') 189 return 0; 190 191 disexpand = 1; 192 next(); 193 n = 0; 194 195 if (mp->npars == 0 && ahead() == ')') { 196 next(); 197 } else { 198 do { 199 mp->arglist = xrealloc(mp->arglist, (n+1)*sizeof(char *)); 200 mp->arglist[n] = parameter(mp); 201 DBG("MACRO fetched arg '%s'", mp->arglist[n]); 202 } while (++n < NR_MACROARG && yytoken == ','); 203 } 204 205 if (yytoken != ')') 206 error("incorrect macro function-alike invocation"); 207 disexpand = 0; 208 209 if (n == NR_MACROARG) 210 error("too many parameters in macro \"%s\"", mp->sym->name); 211 if (n != mp->npars) { 212 error("macro \"%s\" received %d arguments, but it takes %d", 213 mp->sym->name, n, mp->npars); 214 } 215 216 return 1; 217 } 218 219 static int 220 concatoper(char *def, char *cur) 221 { 222 char *s; 223 224 for (s = cur + 4; isspace(*s); ++s) 225 ; 226 if (*s == CONCAT) 227 return 1; 228 229 for (s = cur; s > def && isspace(s[-1]); --s) 230 ; 231 if (s > def && s[-1] == CONCAT) 232 return 1; 233 234 return 0; 235 } 236 237 static int 238 expandarg(char *arg, char *def, char *curdef, char *buf, int bufsiz) 239 { 240 int siz; 241 char *s = buf; 242 243 /* gives priority to concatenation operators */ 244 if (concatoper(def, curdef)) { 245 siz = strlen(arg); 246 if (siz >= bufsiz) { 247 siz = -1; 248 } else { 249 memcpy(buf, arg, siz); 250 buf += siz; 251 } 252 } else { 253 addinput(IPARAM, arg, FAIL); 254 for (siz = 0; next() != EOFTOK; siz += yylen+1) { 255 if (yylen > bufsiz-2) { 256 siz = -1; 257 break; 258 } 259 memcpy(buf, yytext, yylen); 260 bufsiz -= yylen + 1; 261 buf += yylen; 262 *buf++ = ' '; 263 } 264 265 delinput(); 266 } 267 *buf = '\0'; 268 269 DBG("MACRO parameter '%s' expanded to '%s'", arg, s); 270 271 return siz; 272 } 273 274 static int 275 copymacro(Macro *mp) 276 { 277 int delim, c, esc; 278 char *s, *p, *arg, *bp; 279 int size, bufsiz; 280 281 if (mp->sym == symfile) 282 return sprintf(mp->buffer, "\"%s\" ", filenam); 283 if (mp->sym == symline) 284 return sprintf(mp->buffer, "%d ", lineno); 285 286 bp = mp->buffer; 287 bufsiz = mp->bufsiz; 288 for (s = mp->def; c = *s; ++s) { 289 switch (c) { 290 case '\'': 291 delim = '\''; 292 goto search_delim; 293 case '\"': 294 delim = '"'; 295 search_delim: 296 esc = 0; 297 p = s; 298 for (++s; c = *s; ++s) { 299 if (c == '\\' && !esc) 300 esc = 1; 301 else if (c == delim &&!esc) 302 break; 303 else 304 esc = 0; 305 } 306 size = s - p + 1; 307 if (size > bufsiz) 308 goto expansion_too_long; 309 memcpy(bp, p, size); 310 bufsiz -= size; 311 bp += size; 312 break; 313 case CONCAT: 314 /* token concatenation operator */ 315 DBG("MACRO concat"); 316 while (bp[-1] == ' ') 317 --bp, ++bufsiz; 318 while (s[1] == ' ') 319 ++s; 320 break; 321 case STRINGIZE: 322 /* stringfier operator */ 323 DBG("MACRO stringize"); 324 arg = mp->arglist[atoi(s += 2)]; 325 s += 2; 326 327 if (bufsiz < 3) 328 goto expansion_too_long; 329 330 *bp++ = '"'; 331 while ((c = *arg++) != '\0') { 332 if (c == '"') { 333 if (bufsiz < 3) 334 goto expansion_too_long; 335 *bp++ = '\\'; 336 *bp++ = '"'; 337 bufsiz -= 2; 338 } else { 339 if (bufsiz < 2) 340 goto expansion_too_long; 341 *bp++ = c; 342 bufsiz--; 343 } 344 } 345 *bp++ = '"'; 346 347 break; 348 case MACROPAR: 349 /* parameter substitution */ 350 arg = mp->arglist[atoi(s+1)]; 351 size = expandarg(arg, mp->def, s, bp, bufsiz); 352 if (size < 0) 353 goto expansion_too_long; 354 bp += size; 355 bufsiz -= size; 356 s += 3; 357 break; 358 default: 359 if (bufsiz-- == 0) 360 goto expansion_too_long; 361 *bp++ = c; 362 break; 363 } 364 } 365 *bp = '\0'; 366 367 return bp - mp->buffer; 368 369 expansion_too_long: 370 error("macro expansion of \"%s\" too long", mp->sym->name); 371 } 372 373 static void 374 addhideset(Input *ip, Symbol *sym) 375 { 376 Symbol **set; 377 Symbol **p; 378 379 set = ip->macro->hideset; 380 for (p = set; p < &set[NR_MACROARG] && *p; ++p) { 381 if (*p == sym) 382 return; 383 } 384 385 if (p == &set[NR_MACROARG]) 386 error("too complex macro expansion"); 387 388 *p = sym; 389 DBG("MACRO Adding %s to hideset of %s", 390 sym->name, ip->macro->sym->name); 391 } 392 393 static void 394 hide(Symbol *sym) 395 { 396 DBG("SYM: hidding symbol %s %d", sym->name, sym->hide); 397 sym->hide = 1; 398 } 399 400 static void 401 unhide(Symbol *sym) 402 { 403 DBG("SYM: unhidding symbol %s %d", sym->name, sym->hide); 404 sym->hide = 0; 405 } 406 407 void 408 delmacro(Macro *mp) 409 { 410 int i; 411 Symbol **p; 412 413 if (!mp) 414 return; 415 416 if (mp->arglist) { 417 for (i = 0; i < mp->npars; i++) 418 free(mp->arglist[i]); 419 } 420 421 for (p = mp->hideset; p < &mp->hideset[NR_MACROARG] && *p; ++p) 422 unhide(*p); 423 424 free(mp->arglist); 425 free(mp); 426 } 427 428 Macro * 429 newmacro(Symbol *sym) 430 { 431 Macro *mp; 432 433 mp = xmalloc(sizeof(*mp)); 434 *mp = (Macro) {0}; 435 mp->sym = sym; 436 mp->def = sym->u.s + 3; 437 if (sym->u.s) 438 mp->npars = atoi(sym->u.s); 439 440 return mp; 441 } 442 443 int 444 expand(Symbol *sym) 445 { 446 int siz; 447 Macro *mp; 448 Input *ip; 449 Symbol **p; 450 451 DBG("MACRO '%s' detected disexpand=%d hide=%d", 452 sym->name, disexpand, sym->hide); 453 454 if (disexpand || sym->hide || sym->token != IDEN) 455 return 0; 456 457 mp = newmacro(sym); 458 mp->fname = filenam; 459 460 if (!parsepars(mp)) { 461 delmacro(mp); 462 return 0; 463 } 464 465 addinput(IMACRO, mp, FAIL); 466 mp->buffer = input->line; 467 mp->bufsiz = INPUTSIZ-1; 468 469 siz = copymacro(mp); 470 mp->buffer[siz] = '\0'; 471 472 for (ip = input; ip; ip = ip->next) { 473 if ((ip->flags & ITYPE) == IMACRO) 474 addhideset(ip, sym); 475 } 476 477 for (p = mp->hideset; p < &mp->hideset[NR_MACROARG] && *p; ++p) 478 hide(*p); 479 480 DBG("MACRO '%s' expanded to :'%s'", mp->sym->name, mp->buffer); 481 482 return 1; 483 } 484 485 static int 486 getpars(Symbol *args[NR_MACROARG]) 487 { 488 int n, c; 489 Symbol *sym; 490 491 if (*input->p != '(') 492 return -1; 493 494 /* skip the '(' */ 495 next(); 496 next(); 497 if (yytoken == ')') 498 return 0; 499 500 n = 0; 501 do { 502 if (n == NR_MACROARG) { 503 cpperror("too many parameters in macro"); 504 return NR_MACROARG; 505 } 506 if (accept(ELLIPSIS)) { 507 args[n++] = NULL; 508 break; 509 } 510 if (yytoken != IDEN) { 511 cpperror("macro arguments must be identifiers"); 512 return NR_MACROARG; 513 } 514 if ((sym = install(NS_IDEN, yylval.sym)) == NULL) { 515 errorp("duplicated macro parameter '%s'", yytext); 516 } else { 517 sym->flags |= SUSED; 518 args[n++] = sym; 519 } 520 next(); 521 } while (accept(',')); 522 523 if (yytoken != ')') { 524 cpperror("expected ')' at the end of macro argument list"); 525 return NR_MACROARG; 526 } 527 528 return n; 529 } 530 531 static int 532 getdefs(Symbol *args[NR_MACROARG], int nargs, char *buffer, size_t bufsiz) 533 { 534 size_t len; 535 char *bp, *p; 536 Symbol **argp, *sym; 537 int c, id, token, prevc, ispar; 538 539 while (isspace(*input->p)) 540 ++input->p; 541 542 bp = buffer; 543 for (prevc = 0; (c = *input->p) != '\n' && c != '\0'; ++input->p) { 544 len = 1; 545 ispar = 0; 546 token = c; 547 sym = NULL; 548 549 if (c == '#') { 550 if (input->p[1] == '#') { 551 token = CONCAT; 552 ++input->p; 553 } else { 554 token = STRINGIZE; 555 } 556 } else if (c == '_' || isalpha(c)) { 557 token = IDEN; 558 for (p = input->p; isalnum(*p) || *p == '_'; ++p) 559 ; 560 len = p - input->p; 561 if (len > INTIDENTSIZ) { 562 cpperror("identifier too long in macro definition"); 563 return 0; 564 } 565 memcpy(yytext, input->p, len); 566 yytext[len] = '\0'; 567 yylen = len; 568 input->p = p - 1; 569 sym = lookup(NS_IDEN, yytext, NOALLOC); 570 } else if (c == '"') { 571 next(); 572 assert(yytoken == STRING); 573 token = STRING; 574 len = yylen; 575 } 576 577 if (sym && nargs > 0) { 578 for (argp = args; argp < &args[nargs]; ++argp) { 579 if (*argp == sym) 580 break; 581 } 582 if (argp != &args[nargs]) { 583 id = argp - args; 584 sprintf(yytext, 585 "%c%02d%c", MACROPAR, id, MACROPAR); 586 ispar = 1; 587 yylen = len = 4; 588 } 589 } 590 591 if (prevc == 0 && token == CONCAT) 592 goto wrong_concat; 593 594 if (prevc == STRINGIZE && !ispar) { 595 cpperror("'#' is not followed by a macro parameter"); 596 return 0; 597 } 598 599 if (len >= bufsiz) { 600 cpperror("macro too long"); 601 return 0; 602 } 603 604 if (token == IDEN || token == STRING) 605 memcpy(bp, yytext, yylen); 606 else 607 *bp = token; 608 609 bp += len; 610 bufsiz -= len; 611 prevc = token; 612 } 613 614 end_loop: 615 if ((yytoken = c) == '\0') 616 yytoken = EOFTOK; 617 if (prevc == CONCAT) 618 goto wrong_concat; 619 for ( ; bp > buffer && isspace(bp[-1]); --bp); 620 ; 621 *bp = '\0'; 622 return 1; 623 624 wrong_concat: 625 cpperror("'##' cannot appear at either ends of a macro expansion"); 626 return 0; 627 } 628 629 static void 630 define(void) 631 { 632 Symbol *sym,*args[NR_MACROARG]; 633 char buff[LINESIZ+1]; 634 int n; 635 636 if (cppoff) 637 return; 638 639 disescape = 1; 640 namespace = NS_CPP; 641 next(); 642 643 if (yytoken != IDEN) { 644 cpperror("macro names must be identifiers"); 645 return; 646 } 647 sym = yylval.sym; 648 649 namespace = NS_IDEN; /* Avoid polution in NS_CPP */ 650 if ((n = getpars(args)) == NR_MACROARG) 651 goto delete; 652 if (n > 0 && !args[n-1]) /* it is a variadic function */ 653 --n; 654 655 sprintf(buff, "%02d#", n); 656 if (!getdefs(args, n, buff+3, LINESIZ-3)) 657 goto delete; 658 659 if (sym->flags & SDECLARED) { 660 if (strcmp(sym->u.s, buff) != 0) 661 warn("'%s' redefined", sym->name); 662 free(sym->u.s); 663 } else { 664 sym = install(NS_CPP, sym); 665 sym->flags |= SDECLARED|SSTRING; 666 } 667 668 sym->u.s = xstrdup(buff); 669 DBG("MACRO '%s' defined as '%s'", sym->name, buff); 670 return; 671 672 delete: 673 killsym(sym); 674 } 675 676 void 677 incdir(char *dir) 678 { 679 if (!dir || *dir == '\0') 680 die("cc1: incorrect -I flag"); 681 newitem(&dirinclude, dir); 682 } 683 684 static int 685 includefile(char *dir, char *file, size_t filelen) 686 { 687 size_t dirlen; 688 char path[FILENAME_MAX]; 689 690 if (!dir) { 691 dirlen = 0; 692 if (filelen > FILENAME_MAX-1) 693 return 0; 694 } else { 695 dirlen = strlen(dir); 696 if (dirlen + filelen > FILENAME_MAX-2) 697 return 0; 698 memcpy(path, dir, dirlen); 699 if (dir[dirlen-1] != '/') 700 path[dirlen++] = '/'; 701 } 702 memcpy(path+dirlen, file, filelen); 703 path[dirlen + filelen] = '\0'; 704 705 return addinput(IFILE, path, NOFAIL); 706 } 707 708 static char * 709 cwd(char *buf) 710 { 711 char *p, *s = filenam; 712 size_t len; 713 714 if ((p = strrchr(s, '/')) == NULL) 715 return NULL; 716 if ((len = p - s) >= FILENAME_MAX) 717 die("cc1: current work directory too long"); 718 memcpy(buf, s, len); 719 buf[len] = '\0'; 720 return buf; 721 } 722 723 static void 724 include(void) 725 { 726 char dir[FILENAME_MAX], file[FILENAME_MAX], *p, **bp; 727 size_t filelen; 728 int n; 729 730 if (cppoff) 731 return; 732 733 disexpand = 0; 734 namespace = NS_IDEN; 735 next(); 736 737 switch (*yytext) { 738 case '<': 739 if ((p = strchr(input->begin, '>')) == NULL || p[-1] == '<') 740 goto bad_include; 741 filelen = p - input->begin; 742 if (filelen >= FILENAME_MAX) 743 goto too_long; 744 memcpy(file, input->begin, filelen); 745 file[filelen] = '\0'; 746 747 input->begin = input->p = p+1; 748 if (next() != '\n') 749 goto trailing_characters; 750 751 break; 752 case '"': 753 if (yylen < 3) 754 goto bad_include; 755 filelen = yylen-2; 756 if (filelen >= FILENAME_MAX) 757 goto too_long; 758 memcpy(file, yytext+1, filelen); 759 file[filelen] = '\0'; 760 761 if (next() != '\n') 762 goto trailing_characters; 763 764 if (includefile(cwd(dir), file, filelen)) 765 goto its_done; 766 break; 767 default: 768 goto bad_include; 769 } 770 771 n = dirinclude.n; 772 for (bp = dirinclude.s; n--; ++bp) { 773 if (includefile(*bp, file, filelen)) 774 goto its_done; 775 } 776 cpperror("included file '%s' not found", file); 777 778 its_done: 779 return; 780 781 trailing_characters: 782 cpperror("trailing characters after preprocessor directive"); 783 return; 784 785 too_long: 786 cpperror("too long file name in #include"); 787 return; 788 789 bad_include: 790 cpperror("#include expects \"FILENAME\" or <FILENAME>"); 791 return; 792 } 793 794 static void 795 line(void) 796 { 797 long n; 798 char *endp, *fname; 799 800 if (cppoff) 801 return; 802 803 disexpand = 0; 804 next(); 805 n = strtol(yytext, &endp, 10); 806 if (n <= 0 || n > USHRT_MAX || *endp != '\0') { 807 cpperror("first parameter of #line is not a positive integer"); 808 return; 809 } 810 811 next(); 812 if (yytoken == '\n') { 813 fname = NULL; 814 } else { 815 if (*yytext != '\"' || yylen == 1) { 816 cpperror("second parameter of #line is not a valid filename"); 817 return; 818 } 819 fname = yylval.sym->u.s; 820 } 821 setloc(fname, n - 1); 822 if (yytoken != '\n') 823 next(); 824 } 825 826 static void 827 pragma(void) 828 { 829 if (cppoff) 830 return; 831 next(); 832 warn("ignoring pragma '%s'", yytext); 833 *input->p = '\0'; 834 next(); 835 } 836 837 static void 838 usererr(void) 839 { 840 if (cppoff) 841 return; 842 cpperror("#error %s", input->p); 843 exit(EXIT_FAILURE); 844 next(); 845 } 846 847 848 Node * 849 defined(void) 850 { 851 Symbol *sym; 852 int paren; 853 854 disexpand = 1; 855 next(); 856 paren = accept('('); 857 if (yytoken != IDEN && yytoken != TYPEIDEN) 858 cpperror("operator 'defined' requires an identifier"); 859 if (yytoken == TYPEIDEN || !(yylval.sym->flags & SDECLARED)) 860 sym = zero; 861 else 862 sym = one; 863 disexpand = 0; 864 next(); 865 if (paren) 866 expect(')'); 867 return constnode(sym); 868 } 869 870 static void 871 ifclause(int negate, int isifdef) 872 { 873 Symbol *sym; 874 unsigned n; 875 int enabled, done; 876 Node *expr; 877 878 if (cppctx == NR_COND-1) 879 error("too many nesting levels of conditional inclusion"); 880 n = cppctx++; 881 DBG("CPP ifclause updates cppctx=%d", cppctx); 882 883 if (n > 0 && !ifstate[n-1].enabled) { 884 done = 1; 885 enabled = 0; 886 goto disabled; 887 } 888 889 namespace = NS_CPP; 890 next(); 891 892 if (isifdef) { 893 if (yytoken != IDEN) { 894 cpperror("no macro name given in #%s directive", 895 (negate) ? "ifndef" : "ifdef"); 896 return; 897 } 898 sym = yylval.sym; 899 next(); 900 enabled = (sym->flags & SDECLARED) != 0; 901 if (!enabled) 902 killsym(sym); 903 } else { 904 /* TODO: catch recovery here */ 905 if ((expr = constexpr()) == NULL) { 906 cpperror("parameter of #if is not an integer constant expression"); 907 return; 908 } 909 DBG("CPP if expr=%d", expr->sym->u.i); 910 enabled = expr->sym->u.i != 0; 911 freetree(expr); 912 } 913 914 if (negate) 915 enabled = !enabled; 916 done = enabled; 917 918 disabled: 919 cppoff = !enabled; 920 DBG("CPP if result=%d", enabled); 921 ifstate[n].done = done; 922 ifstate[n].enabled = enabled; 923 ifstate[n].iselse = 0; 924 } 925 926 static void 927 cppif(void) 928 { 929 DBG("CPP line=%u if cppctx=%d", lineno, cppctx); 930 disexpand = 0; 931 ifclause(0, 0); 932 } 933 934 static void 935 ifdef(void) 936 { 937 DBG("CPP line=%u ifdef cppctx=%d", lineno, cppctx); 938 ifclause(0, 1); 939 } 940 941 static void 942 ifndef(void) 943 { 944 DBG("CPP line=%u ifndef cppctx=%d", lineno, cppctx); 945 ifclause(1, 1); 946 } 947 948 static void 949 cppelse(void) 950 { 951 DBG("CPP line=%u else cppctx=%d", lineno, cppctx); 952 953 if (cppctx == 0 || ifstate[cppctx-1].iselse) { 954 cpperror("#else without #ifdef/ifndef"); 955 return; 956 } 957 958 /* 959 * If we are disabled by a upper ifdef then ifclause() already 960 * marked us as disabled and done. So if we are done then we 961 * disable cpp because or ifclause was true, or it was disabled 962 * by the upper. If we are not done, then it is our turn. 963 */ 964 if (ifstate[cppctx-1].done) { 965 ifstate[cppctx-1].enabled = 0; 966 cppoff = 1; 967 } else { 968 ifstate[cppctx-1].done = 1; 969 ifstate[cppctx-1].enabled = 1; 970 cppoff = 0; 971 } 972 ifstate[cppctx-1].iselse = 1; 973 974 next(); 975 } 976 977 static void 978 elif(void) 979 { 980 DBG("CPP line=%u elif cppctx=%d", lineno, cppctx); 981 982 if (cppctx == 0 || ifstate[cppctx-1].iselse) { 983 cpperror("#elif without #ifdef/ifndef"); 984 return; 985 } 986 987 /* 988 * If we are disabled by a upper ifdef then ifclause() already 989 * marked us as disabled and done. So if we are done then we 990 * disable cpp because or ifclause was true, or it was disabled 991 * by the upper. If we are not done, then we have to evaluate 992 * the if condition. 993 */ 994 if (ifstate[cppctx-1].done) { 995 ifstate[cppctx-1].enabled = 0; 996 cppoff = 1; 997 } else { 998 --cppctx; 999 DBG("elif updates cppctx=%d", cppctx); 1000 cppif(); 1001 } 1002 } 1003 1004 static void 1005 endif(void) 1006 { 1007 DBG("CPP line=%u endif cppctx=%d", lineno, cppctx); 1008 1009 if (cppctx == 0) 1010 error("#endif without #if"); 1011 1012 if (cppctx > 1) 1013 cppoff = !ifstate[cppctx - 2].enabled; 1014 else 1015 cppoff = 0; 1016 1017 --cppctx; 1018 DBG("CPP endif updates cppctx=%d", cppctx); 1019 next(); 1020 } 1021 1022 static void 1023 undef(void) 1024 { 1025 if (cppoff) 1026 return; 1027 1028 namespace = NS_CPP; 1029 next(); 1030 if (yytoken != IDEN) { 1031 error("no macro name given in #undef directive"); 1032 return; 1033 } 1034 killsym(yylval.sym); 1035 next(); 1036 } 1037 1038 int 1039 cpp(void) 1040 { 1041 static struct { 1042 unsigned char token; 1043 void (*fun)(void); 1044 } *bp, clauses [] = { 1045 {DEFINE, define}, 1046 {INCLUDE, include}, 1047 {LINE, line}, 1048 {IFDEF, ifdef}, 1049 {IF, cppif}, 1050 {ELIF, elif}, 1051 {IFNDEF, ifndef}, 1052 {ELSE, cppelse}, 1053 {ENDIF, endif}, 1054 {UNDEF, undef}, 1055 {PRAGMA, pragma}, 1056 {ERROR, usererr}, 1057 {0, NULL} 1058 }; 1059 int ns; 1060 char *p; 1061 1062 for (p = input->p; isspace(*p); ++p) 1063 ; 1064 1065 if (*p != '#') { 1066 if (cppoff) 1067 *input->p = '\0'; 1068 return cppoff; 1069 } 1070 input->p = p+1; 1071 1072 disexpand = 1; 1073 lexmode = CPPMODE; 1074 ns = namespace; 1075 namespace = NS_CPPCLAUSES; 1076 next(); 1077 namespace = NS_IDEN; 1078 1079 if (yytoken == '\n') 1080 goto ret; 1081 1082 for (bp = clauses; bp->token && bp->token != yytoken; ++bp) 1083 ; 1084 if (!bp->token) { 1085 errorp("incorrect preprocessor directive '%s'", yytext); 1086 goto ret; 1087 } 1088 1089 DBG("CPP %s", yytext); 1090 1091 /* 1092 * create a new context to avoid polish the current context, 1093 * and to get all the symbols freed at the end 1094 */ 1095 pushctx(); 1096 (*bp->fun)(); 1097 popctx(); 1098 1099 /* 1100 * #include changes the content of input->line, so the correctness 1101 * of the line must be checked in the own include(), and we have 1102 * to skip this tests. For the same reason include() is the only 1103 * function which does not prepare the next token 1104 */ 1105 if (bp->token == INCLUDE) 1106 goto ret; 1107 1108 if (yytoken != '\n' && yytoken != EOFTOK && !cppoff) 1109 cpperror("trailing characters after preprocessor directive"); 1110 1111 ret: 1112 disescape = 0; 1113 disexpand = 0; 1114 lexmode = CCMODE; 1115 namespace = ns; 1116 1117 /* 1118 * at this point we know that the cpp line is processed, and any error 1119 * is generated but as next is called we cannot be sure that input is 1120 * valid anymore, but in case of begin valid we want to discard any 1121 * pending input in the current line 1122 */ 1123 if (input) 1124 *input->p = '\0'; 1125 1126 return 1; 1127 } 1128 1129 void 1130 ppragmaln(void) 1131 { 1132 static char file[FILENAME_MAX]; 1133 static unsigned nline; 1134 char *s; 1135 1136 putchar('\n'); 1137 if (strcmp(file, filenam)) { 1138 strcpy(file, filenam); 1139 s = "#line %u \"%s\"\n"; 1140 } else if (nline+1 != lineno) { 1141 s = "#line %u\n"; 1142 } else { 1143 s = ""; 1144 } 1145 nline = lineno; 1146 printf(s, nline, file); 1147 } 1148 1149 void 1150 outcpp(void) 1151 { 1152 int c; 1153 char *s, *t; 1154 1155 for (next(); yytoken != EOFTOK; next()) { 1156 if (onlyheader) 1157 continue; 1158 if (yytoken != STRING) { 1159 printf("%s ", yytext); 1160 continue; 1161 } 1162 for (s = yytext; (c = *s) != '\0'; ++s) { 1163 switch (c) { 1164 case '\n': 1165 t = "\\n"; 1166 goto print_str; 1167 case '\v': 1168 t = "\\v"; 1169 goto print_str; 1170 case '\b': 1171 t = "\\b"; 1172 goto print_str; 1173 case '\t': 1174 t = "\\t"; 1175 goto print_str; 1176 case '\a': 1177 t = "\\a"; 1178 goto print_str; 1179 case '\f': 1180 t = "\\f"; 1181 goto print_str; 1182 case '\r': 1183 t = "\\r"; 1184 goto print_str; 1185 case '"': 1186 if (s == yytext || s[1] == '\0') 1187 goto print_chr; 1188 t = "\\\""; 1189 goto print_str; 1190 case '\'': 1191 t = "\\'"; 1192 goto print_str; 1193 case '\?': 1194 t = "\\\?"; 1195 goto print_str; 1196 case '\\': 1197 putchar('\\'); 1198 default: 1199 print_chr: 1200 if (!isprint(c)) 1201 printf("\\x%x", c); 1202 else 1203 putchar(c); 1204 break; 1205 print_str: 1206 fputs(t, stdout); 1207 break; 1208 } 1209 } 1210 putchar(' '); 1211 } 1212 putchar('\n'); 1213 }