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