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