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