1 #include "cc.h" 2 #include "y.tab.h" 3 4 #ifndef CPP 5 #define CPP "/bin/cpp" 6 #endif 7 8 /* 9 * known debug flags 10 * -a acid declaration output 11 * -A !B 12 * -B non ANSI 13 * -d print declarations 14 * -D name define 15 * -F format specification check 16 * -i print initialization 17 * -I path include 18 * -l generate little-endian code 19 * -L print every NAME symbol 20 * -M constant multiplication 21 * -m print add/sub/mul trees 22 * -n print acid to file (%.c=%.acid) (with -a or -aa) 23 * -o file output file 24 * -p use standard cpp ANSI preprocessor (not on windows) 25 * -r print registerization 26 * -s print structure offsets (with -a or -aa) 27 * -S print assembly 28 * -t print type trees 29 * -V enable void* conversion warnings 30 * -v verbose printing 31 * -w print warnings 32 * -X abort on error 33 * -. Inhibit search for includes in source directory 34 */ 35 36 void 37 main(int argc, char *argv[]) 38 { 39 char *defs[50], *p; 40 int nproc, nout, status, i, c, ndef; 41 42 memset(debug, 0, sizeof(debug)); 43 tinit(); 44 cinit(); 45 ginit(); 46 arginit(); 47 48 profileflg = 1; /* #pragma can turn it off */ 49 tufield = simplet((1L<<tfield->etype) | BUNSIGNED); 50 ndef = 0; 51 outfile = 0; 52 include[ninclude++] = "."; 53 ARGBEGIN { 54 default: 55 c = ARGC(); 56 if(c >= 0 && c < sizeof(debug)) 57 debug[c]++; 58 break; 59 60 case 'l': /* for little-endian mips */ 61 if(thechar != 'v'){ 62 print("can only use -l with vc"); 63 errorexit(); 64 } 65 thechar = '0'; 66 thestring = "spim"; 67 break; 68 69 case 'o': 70 outfile = ARGF(); 71 break; 72 73 case 'D': 74 p = ARGF(); 75 if(p) { 76 defs[ndef++] = p; 77 dodefine(p); 78 } 79 break; 80 81 case 'I': 82 p = ARGF(); 83 setinclude(p); 84 break; 85 } ARGEND 86 if(argc < 1 && outfile == 0) { 87 print("usage: %cc [-options] files\n", thechar); 88 errorexit(); 89 } 90 if(argc > 1 && systemtype(Windows)){ 91 print("can't compile multiple files on windows\n"); 92 errorexit(); 93 } 94 if(argc > 1 && !systemtype(Windows)) { 95 nproc = 1; 96 /* 97 * if we're writing acid to standard output, don't compile 98 * concurrently, to avoid interleaving output. 99 */ 100 if(((!debug['a'] && !debug['Z']) || debug['n']) && 101 (p = getenv("NPROC")) != nil) 102 nproc = atol(p); /* */ 103 c = 0; 104 nout = 0; 105 for(;;) { 106 while(nout < nproc && argc > 0) { 107 i = myfork(); 108 if(i < 0) { 109 i = mywait(&status); 110 if(i < 0) { 111 print("cannot create a process\n"); 112 errorexit(); 113 } 114 if(status) 115 c++; 116 nout--; 117 continue; 118 } 119 if(i == 0) { 120 fprint(2, "%s:\n", *argv); 121 if (compile(*argv, defs, ndef)) 122 errorexit(); 123 exits(0); 124 } 125 nout++; 126 argc--; 127 argv++; 128 } 129 i = mywait(&status); 130 if(i < 0) { 131 if(c) 132 errorexit(); 133 exits(0); 134 } 135 if(status) 136 c++; 137 nout--; 138 } 139 } 140 141 if(argc == 0) 142 c = compile("stdin", defs, ndef); 143 else 144 c = compile(argv[0], defs, ndef); 145 146 if(c) 147 errorexit(); 148 exits(0); 149 } 150 151 int 152 compile(char *file, char **defs, int ndef) 153 { 154 char ofile[400], incfile[20]; 155 char *p, *av[100], opt[256]; 156 int i, c, fd[2]; 157 static int first = 1; 158 159 strcpy(ofile, file); 160 p = utfrrune(ofile, pathchar()); 161 if(p) { 162 *p++ = 0; 163 if(!debug['.']) 164 include[0] = strdup(ofile); 165 } else 166 p = ofile; 167 168 if(outfile == 0) { 169 outfile = p; 170 if(outfile) { 171 if(p = utfrrune(outfile, '.')) 172 if(p[1] == 'c' && p[2] == 0) 173 p[0] = 0; 174 p = utfrune(outfile, 0); 175 if(debug['a'] && debug['n']) 176 strcat(p, ".acid"); 177 else if(debug['Z'] && debug['n']) 178 strcat(p, "_pickle.c"); 179 else { 180 p[0] = '.'; 181 p[1] = thechar; 182 p[2] = 0; 183 } 184 } else 185 outfile = "/dev/null"; 186 } 187 188 if(p = getenv("INCLUDE")) { 189 setinclude(p); 190 } else { 191 if(systemtype(Plan9)) { 192 sprint(incfile, "/%s/include", thestring); 193 setinclude(strdup(incfile)); 194 setinclude("/sys/include"); 195 } 196 } 197 if (first) 198 Binit(&diagbuf, 1, OWRITE); 199 /* 200 * if we're writing acid to standard output, don't keep scratching 201 * outbuf. 202 */ 203 if((debug['a'] || debug['Z']) && !debug['n']) { 204 if (first) { 205 outfile = 0; 206 Binit(&outbuf, mydup(1, -1), OWRITE); 207 mydup(2, 1); 208 } 209 } else { 210 c = mycreat(outfile, 0664); 211 if(c < 0) { 212 diag(Z, "cannot open %s - %r", outfile); 213 outfile = 0; 214 errorexit(); 215 } 216 Binit(&outbuf, c, OWRITE); 217 } 218 newio(); 219 first = 0; 220 221 /* Use an ANSI preprocessor */ 222 if(debug['p']) { 223 if(systemtype(Windows)) { 224 diag(Z, "-p option not supported on windows"); 225 errorexit(); 226 } 227 if(myaccess(file) < 0) { 228 diag(Z, "%s does not exist", file); 229 errorexit(); 230 } 231 if(mypipe(fd) < 0) { 232 diag(Z, "pipe failed"); 233 errorexit(); 234 } 235 switch(myfork()) { 236 case -1: 237 diag(Z, "fork failed"); 238 errorexit(); 239 case 0: 240 close(fd[0]); 241 mydup(fd[1], 1); 242 close(fd[1]); 243 av[0] = CPP; 244 i = 1; 245 if(debug['.']){ 246 sprint(opt, "-."); 247 av[i++] = strdup(opt); 248 } 249 if(debug['+']) { 250 sprint(opt, "-+"); 251 av[i++] = strdup(opt); 252 } 253 for(c = 0; c < ndef; c++) { 254 sprint(opt, "-D%s", defs[c]); 255 av[i++] = strdup(opt); 256 } 257 for(c = 0; c < ninclude; c++) { 258 sprint(opt, "-I%s", include[c]); 259 av[i++] = strdup(opt); 260 } 261 if(strcmp(file, "stdin") != 0) 262 av[i++] = file; 263 av[i] = 0; 264 if(debug['p'] > 1) { 265 for(c = 0; c < i; c++) 266 fprint(2, "%s ", av[c]); 267 fprint(2, "\n"); 268 } 269 myexec(av[0], av); 270 fprint(2, "can't exec C preprocessor %s: %r\n", CPP); 271 errorexit(); 272 default: 273 close(fd[1]); 274 newfile(file, fd[0]); 275 break; 276 } 277 } else { 278 if(strcmp(file, "stdin") == 0) 279 newfile(file, 0); 280 else 281 newfile(file, -1); 282 } 283 yyparse(); 284 if(!debug['a'] && !debug['Z']) 285 gclean(); 286 return nerrors; 287 } 288 289 void 290 errorexit(void) 291 { 292 if(outfile) 293 remove(outfile); 294 exits("error"); 295 } 296 297 void 298 pushio(void) 299 { 300 Io *i; 301 302 i = iostack; 303 if(i == I) { 304 yyerror("botch in pushio"); 305 errorexit(); 306 } 307 i->p = fi.p; 308 i->c = fi.c; 309 } 310 311 void 312 newio(void) 313 { 314 Io *i; 315 static int pushdepth = 0; 316 317 i = iofree; 318 if(i == I) { 319 pushdepth++; 320 if(pushdepth > 1000) { 321 yyerror("macro/io expansion too deep"); 322 errorexit(); 323 } 324 i = alloc(sizeof(*i)); 325 } else 326 iofree = i->link; 327 i->c = 0; 328 i->f = -1; 329 ionext = i; 330 } 331 332 void 333 newfile(char *s, int f) 334 { 335 Io *i; 336 337 if(debug['e']) 338 print("%L: %s\n", lineno, s); 339 340 i = ionext; 341 i->link = iostack; 342 iostack = i; 343 i->f = f; 344 if(f < 0) 345 i->f = open(s, 0); 346 if(i->f < 0) { 347 yyerror("%cc: %r: %s", thechar, s); 348 errorexit(); 349 } 350 fi.c = 0; 351 linehist(s, 0); 352 } 353 354 Sym* 355 slookup(char *s) 356 { 357 358 strcpy(symb, s); 359 return lookup(); 360 } 361 362 Sym* 363 lookup(void) 364 { 365 Sym *s; 366 ulong h; 367 char *p; 368 int c, n; 369 370 h = 0; 371 for(p=symb; *p;) { 372 h = h * 3; 373 h += *p++; 374 } 375 n = (p - symb) + 1; 376 if((long)h < 0) 377 h = ~h; 378 h %= NHASH; 379 c = symb[0]; 380 for(s = hash[h]; s != S; s = s->link) { 381 if(s->name[0] != c) 382 continue; 383 if(strcmp(s->name, symb) == 0) 384 return s; 385 } 386 s = alloc(sizeof(*s)); 387 s->name = alloc(n); 388 memmove(s->name, symb, n); 389 390 strcpy(s->name, symb); 391 s->link = hash[h]; 392 hash[h] = s; 393 syminit(s); 394 395 return s; 396 } 397 398 void 399 syminit(Sym *s) 400 { 401 s->lexical = LNAME; 402 s->block = 0; 403 s->offset = 0; 404 s->type = T; 405 s->suetag = T; 406 s->class = CXXX; 407 s->aused = 0; 408 s->sig = SIGNONE; 409 } 410 411 #define EOF (-1) 412 #define IGN (-2) 413 #define ESC (1<<20) 414 #define GETC() ((--fi.c < 0)? filbuf(): (*fi.p++ & 0xff)) 415 416 enum 417 { 418 Numdec = 1<<0, 419 Numlong = 1<<1, 420 Numuns = 1<<2, 421 Numvlong = 1<<3, 422 Numflt = 1<<4, 423 }; 424 425 long 426 yylex(void) 427 { 428 vlong vv; 429 long c, c1, t; 430 char *cp; 431 Rune rune; 432 Sym *s; 433 434 if(peekc != IGN) { 435 c = peekc; 436 peekc = IGN; 437 goto l1; 438 } 439 l0: 440 c = GETC(); 441 442 l1: 443 if(c >= Runeself) { 444 /* 445 * extension -- 446 * all multibyte runes are alpha 447 */ 448 cp = symb; 449 goto talph; 450 } 451 if(isspace(c)) { 452 if(c == '\n') 453 lineno++; 454 goto l0; 455 } 456 if(isalpha(c)) { 457 cp = symb; 458 if(c != 'L') 459 goto talph; 460 *cp++ = c; 461 c = GETC(); 462 if(c == '\'') { 463 /* L'x' */ 464 c = escchar('\'', 1, 0); 465 if(c == EOF) 466 c = '\''; 467 c1 = escchar('\'', 1, 0); 468 if(c1 != EOF) { 469 yyerror("missing '"); 470 peekc = c1; 471 } 472 yylval.vval = convvtox(c, TUSHORT); 473 return LUCONST; 474 } 475 if(c == '"') { 476 goto caselq; 477 } 478 goto talph; 479 } 480 if(isdigit(c)) 481 goto tnum; 482 switch(c) 483 { 484 485 case EOF: 486 peekc = EOF; 487 return -1; 488 489 case '_': 490 cp = symb; 491 goto talph; 492 493 case '#': 494 domacro(); 495 goto l0; 496 497 case '.': 498 c1 = GETC(); 499 if(isdigit(c1)) { 500 cp = symb; 501 *cp++ = c; 502 c = c1; 503 c1 = 0; 504 goto casedot; 505 } 506 break; 507 508 case '"': 509 strcpy(symb, "\"<string>\""); 510 cp = alloc(0); 511 c1 = 0; 512 513 /* "..." */ 514 for(;;) { 515 c = escchar('"', 0, 1); 516 if(c == EOF) 517 break; 518 if(c & ESC) { 519 cp = allocn(cp, c1, 1); 520 cp[c1++] = c; 521 } else { 522 rune = c; 523 c = runelen(rune); 524 cp = allocn(cp, c1, c); 525 runetochar(cp+c1, &rune); 526 c1 += c; 527 } 528 } 529 yylval.sval.l = c1; 530 do { 531 cp = allocn(cp, c1, 1); 532 cp[c1++] = 0; 533 } while(c1 & MAXALIGN); 534 yylval.sval.s = cp; 535 return LSTRING; 536 537 caselq: 538 /* L"..." */ 539 strcpy(symb, "\"L<string>\""); 540 cp = alloc(0); 541 c1 = 0; 542 for(;;) { 543 c = escchar('"', 1, 0); 544 if(c == EOF) 545 break; 546 cp = allocn(cp, c1, sizeof(ushort)); 547 *(ushort*)(cp + c1) = c; 548 c1 += sizeof(ushort); 549 } 550 yylval.sval.l = c1; 551 do { 552 cp = allocn(cp, c1, sizeof(ushort)); 553 *(ushort*)(cp + c1) = 0; 554 c1 += sizeof(ushort); 555 } while(c1 & MAXALIGN); 556 yylval.sval.s = cp; 557 return LLSTRING; 558 559 case '\'': 560 /* '.' */ 561 c = escchar('\'', 0, 0); 562 if(c == EOF) 563 c = '\''; 564 c1 = escchar('\'', 0, 0); 565 if(c1 != EOF) { 566 yyerror("missing '"); 567 peekc = c1; 568 } 569 vv = c; 570 yylval.vval = convvtox(vv, TUCHAR); 571 if(yylval.vval != vv) 572 yyerror("overflow in character constant: 0x%lx", c); 573 else 574 if(c & 0x80){ 575 nearln = lineno; 576 warn(Z, "sign-extended character constant"); 577 } 578 yylval.vval = convvtox(vv, TCHAR); 579 return LCONST; 580 581 case '/': 582 c1 = GETC(); 583 if(c1 == '*') { 584 for(;;) { 585 c = getr(); 586 while(c == '*') { 587 c = getr(); 588 if(c == '/') 589 goto l0; 590 } 591 if(c == EOF) { 592 yyerror("eof in comment"); 593 errorexit(); 594 } 595 } 596 } 597 if(c1 == '/') { 598 for(;;) { 599 c = getr(); 600 if(c == '\n') 601 goto l0; 602 if(c == EOF) { 603 yyerror("eof in comment"); 604 errorexit(); 605 } 606 } 607 } 608 if(c1 == '=') 609 return LDVE; 610 break; 611 612 case '*': 613 c1 = GETC(); 614 if(c1 == '=') 615 return LMLE; 616 break; 617 618 case '%': 619 c1 = GETC(); 620 if(c1 == '=') 621 return LMDE; 622 break; 623 624 case '+': 625 c1 = GETC(); 626 if(c1 == '+') 627 return LPP; 628 if(c1 == '=') 629 return LPE; 630 break; 631 632 case '-': 633 c1 = GETC(); 634 if(c1 == '-') 635 return LMM; 636 if(c1 == '=') 637 return LME; 638 if(c1 == '>') 639 return LMG; 640 break; 641 642 case '>': 643 c1 = GETC(); 644 if(c1 == '>') { 645 c = LRSH; 646 c1 = GETC(); 647 if(c1 == '=') 648 return LRSHE; 649 break; 650 } 651 if(c1 == '=') 652 return LGE; 653 break; 654 655 case '<': 656 c1 = GETC(); 657 if(c1 == '<') { 658 c = LLSH; 659 c1 = GETC(); 660 if(c1 == '=') 661 return LLSHE; 662 break; 663 } 664 if(c1 == '=') 665 return LLE; 666 break; 667 668 case '=': 669 c1 = GETC(); 670 if(c1 == '=') 671 return LEQ; 672 break; 673 674 case '!': 675 c1 = GETC(); 676 if(c1 == '=') 677 return LNE; 678 break; 679 680 case '&': 681 c1 = GETC(); 682 if(c1 == '&') 683 return LANDAND; 684 if(c1 == '=') 685 return LANDE; 686 break; 687 688 case '|': 689 c1 = GETC(); 690 if(c1 == '|') 691 return LOROR; 692 if(c1 == '=') 693 return LORE; 694 break; 695 696 case '^': 697 c1 = GETC(); 698 if(c1 == '=') 699 return LXORE; 700 break; 701 702 default: 703 return c; 704 } 705 peekc = c1; 706 return c; 707 708 talph: 709 /* 710 * cp is set to symb and some 711 * prefix has been stored 712 */ 713 for(;;) { 714 if(c >= Runeself) { 715 for(c1=0;;) { 716 cp[c1++] = c; 717 if(fullrune(cp, c1)) 718 break; 719 c = GETC(); 720 } 721 cp += c1; 722 c = GETC(); 723 continue; 724 } 725 if(!isalnum(c) && c != '_') 726 break; 727 *cp++ = c; 728 c = GETC(); 729 } 730 *cp = 0; 731 if(debug['L']) 732 print("%L: %s\n", lineno, symb); 733 peekc = c; 734 s = lookup(); 735 if(s->macro) { 736 newio(); 737 cp = ionext->b; 738 macexpand(s, cp); 739 pushio(); 740 ionext->link = iostack; 741 iostack = ionext; 742 fi.p = cp; 743 fi.c = strlen(cp); 744 if(peekc != IGN) { 745 cp[fi.c++] = peekc; 746 cp[fi.c] = 0; 747 peekc = IGN; 748 } 749 goto l0; 750 } 751 yylval.sym = s; 752 if(s->class == CTYPEDEF || s->class == CTYPESTR) 753 return LTYPE; 754 return s->lexical; 755 756 tnum: 757 c1 = 0; 758 cp = symb; 759 if(c != '0') { 760 c1 |= Numdec; 761 for(;;) { 762 *cp++ = c; 763 c = GETC(); 764 if(isdigit(c)) 765 continue; 766 goto dc; 767 } 768 } 769 *cp++ = c; 770 c = GETC(); 771 if(c == 'x' || c == 'X') 772 for(;;) { 773 *cp++ = c; 774 c = GETC(); 775 if(isdigit(c)) 776 continue; 777 if(c >= 'a' && c <= 'f') 778 continue; 779 if(c >= 'A' && c <= 'F') 780 continue; 781 if(cp == symb+2) 782 yyerror("malformed hex constant"); 783 goto ncu; 784 } 785 if(c < '0' || c > '7') 786 goto dc; 787 for(;;) { 788 if(c >= '0' && c <= '7') { 789 *cp++ = c; 790 c = GETC(); 791 continue; 792 } 793 goto ncu; 794 } 795 796 dc: 797 if(c == '.') 798 goto casedot; 799 if(c == 'e' || c == 'E') 800 goto casee; 801 802 ncu: 803 if((c == 'U' || c == 'u') && !(c1 & Numuns)) { 804 c = GETC(); 805 c1 |= Numuns; 806 goto ncu; 807 } 808 if((c == 'L' || c == 'l') && !(c1 & Numvlong)) { 809 c = GETC(); 810 if(c1 & Numlong) 811 c1 |= Numvlong; 812 c1 |= Numlong; 813 goto ncu; 814 } 815 *cp = 0; 816 peekc = c; 817 if(mpatov(symb, &yylval.vval)) 818 yyerror("overflow in constant"); 819 820 vv = yylval.vval; 821 if(c1 & Numvlong) { 822 if((c1 & Numuns) || convvtox(vv, TVLONG) < 0) { 823 c = LUVLCONST; 824 t = TUVLONG; 825 goto nret; 826 } 827 c = LVLCONST; 828 t = TVLONG; 829 goto nret; 830 } 831 if(c1 & Numlong) { 832 if((c1 & Numuns) || convvtox(vv, TLONG) < 0) { 833 c = LULCONST; 834 t = TULONG; 835 goto nret; 836 } 837 c = LLCONST; 838 t = TLONG; 839 goto nret; 840 } 841 if((c1 & Numuns) || convvtox(vv, TINT) < 0) { 842 c = LUCONST; 843 t = TUINT; 844 goto nret; 845 } 846 c = LCONST; 847 t = TINT; 848 goto nret; 849 850 nret: 851 yylval.vval = convvtox(vv, t); 852 if(yylval.vval != vv){ 853 nearln = lineno; 854 warn(Z, "truncated constant: %T %s", types[t], symb); 855 } 856 return c; 857 858 casedot: 859 for(;;) { 860 *cp++ = c; 861 c = GETC(); 862 if(!isdigit(c)) 863 break; 864 } 865 if(c != 'e' && c != 'E') 866 goto caseout; 867 868 casee: 869 *cp++ = 'e'; 870 c = GETC(); 871 if(c == '+' || c == '-') { 872 *cp++ = c; 873 c = GETC(); 874 } 875 if(!isdigit(c)) 876 yyerror("malformed fp constant exponent"); 877 while(isdigit(c)) { 878 *cp++ = c; 879 c = GETC(); 880 } 881 882 caseout: 883 if(c == 'L' || c == 'l') { 884 c = GETC(); 885 c1 |= Numlong; 886 } else 887 if(c == 'F' || c == 'f') { 888 c = GETC(); 889 c1 |= Numflt; 890 } 891 *cp = 0; 892 peekc = c; 893 if(mpatof(symb, &yylval.dval)) { 894 yyerror("overflow in float constant"); 895 yylval.dval = 0; 896 } 897 if(c1 & Numflt) 898 return LFCONST; 899 return LDCONST; 900 } 901 902 /* 903 * convert a string, s, to vlong in *v 904 * return conversion overflow. 905 * required syntax is [0[x]]d* 906 */ 907 int 908 mpatov(char *s, vlong *v) 909 { 910 vlong n, nn; 911 int c; 912 913 n = 0; 914 c = *s; 915 if(c == '0') 916 goto oct; 917 while(c = *s++) { 918 if(c >= '0' && c <= '9') 919 nn = n*10 + c-'0'; 920 else 921 goto bad; 922 if(n < 0 && nn >= 0) 923 goto bad; 924 n = nn; 925 } 926 goto out; 927 928 oct: 929 s++; 930 c = *s; 931 if(c == 'x' || c == 'X') 932 goto hex; 933 while(c = *s++) { 934 if(c >= '0' || c <= '7') 935 nn = n*8 + c-'0'; 936 else 937 goto bad; 938 if(n < 0 && nn >= 0) 939 goto bad; 940 n = nn; 941 } 942 goto out; 943 944 hex: 945 s++; 946 while(c = *s++) { 947 if(c >= '0' && c <= '9') 948 c += 0-'0'; 949 else 950 if(c >= 'a' && c <= 'f') 951 c += 10-'a'; 952 else 953 if(c >= 'A' && c <= 'F') 954 c += 10-'A'; 955 else 956 goto bad; 957 nn = n*16 + c; 958 if(n < 0 && nn >= 0) 959 goto bad; 960 n = nn; 961 } 962 out: 963 *v = n; 964 return 0; 965 966 bad: 967 *v = ~0; 968 return 1; 969 } 970 971 int 972 getc(void) 973 { 974 int c; 975 976 if(peekc != IGN) { 977 c = peekc; 978 peekc = IGN; 979 } else 980 c = GETC(); 981 if(c == '\n') 982 lineno++; 983 if(c == EOF) { 984 yyerror("End of file"); 985 errorexit(); 986 } 987 return c; 988 } 989 990 long 991 getr(void) 992 { 993 int c, i; 994 char str[UTFmax+1]; 995 Rune rune; 996 997 998 c = getc(); 999 if(c < Runeself) 1000 return c; 1001 i = 0; 1002 str[i++] = c; 1003 1004 loop: 1005 c = getc(); 1006 str[i++] = c; 1007 if(!fullrune(str, i)) 1008 goto loop; 1009 c = chartorune(&rune, str); 1010 if(rune == Runeerror && c == 1) { 1011 nearln = lineno; 1012 diag(Z, "illegal rune in string"); 1013 for(c=0; c<i; c++) 1014 print(" %.2x", *(uchar*)(str+c)); 1015 print("\n"); 1016 } 1017 return rune; 1018 } 1019 1020 int 1021 getnsc(void) 1022 { 1023 int c; 1024 1025 if(peekc != IGN) { 1026 c = peekc; 1027 peekc = IGN; 1028 } else 1029 c = GETC(); 1030 for(;;) { 1031 if(!isspace(c)) 1032 return c; 1033 if(c == '\n') { 1034 lineno++; 1035 return c; 1036 } 1037 c = GETC(); 1038 } 1039 } 1040 1041 void 1042 unget(int c) 1043 { 1044 1045 peekc = c; 1046 if(c == '\n') 1047 lineno--; 1048 } 1049 1050 long 1051 escchar(long e, int longflg, int escflg) 1052 { 1053 long c, l; 1054 int i; 1055 1056 loop: 1057 c = getr(); 1058 if(c == '\n') { 1059 yyerror("newline in string"); 1060 return EOF; 1061 } 1062 if(c != '\\') { 1063 if(c == e) 1064 c = EOF; 1065 return c; 1066 } 1067 c = getr(); 1068 if(c == 'x') { 1069 /* 1070 * note this is not ansi, 1071 * supposed to only accept 2 hex 1072 */ 1073 i = 2; 1074 if(longflg) 1075 i = 4; 1076 l = 0; 1077 for(; i>0; i--) { 1078 c = getc(); 1079 if(c >= '0' && c <= '9') { 1080 l = l*16 + c-'0'; 1081 continue; 1082 } 1083 if(c >= 'a' && c <= 'f') { 1084 l = l*16 + c-'a' + 10; 1085 continue; 1086 } 1087 if(c >= 'A' && c <= 'F') { 1088 l = l*16 + c-'A' + 10; 1089 continue; 1090 } 1091 unget(c); 1092 break; 1093 } 1094 if(escflg) 1095 l |= ESC; 1096 return l; 1097 } 1098 if(c >= '0' && c <= '7') { 1099 /* 1100 * note this is not ansi, 1101 * supposed to only accept 3 oct 1102 */ 1103 i = 2; 1104 if(longflg) 1105 i = 5; 1106 l = c - '0'; 1107 for(; i>0; i--) { 1108 c = getc(); 1109 if(c >= '0' && c <= '7') { 1110 l = l*8 + c-'0'; 1111 continue; 1112 } 1113 unget(c); 1114 } 1115 if(escflg) 1116 l |= ESC; 1117 return l; 1118 } 1119 switch(c) 1120 { 1121 case '\n': goto loop; 1122 case 'n': return '\n'; 1123 case 't': return '\t'; 1124 case 'b': return '\b'; 1125 case 'r': return '\r'; 1126 case 'f': return '\f'; 1127 case 'a': return '\a'; 1128 case 'v': return '\v'; 1129 } 1130 return c; 1131 } 1132 1133 struct 1134 { 1135 char *name; 1136 ushort lexical; 1137 ushort type; 1138 } itab[] = 1139 { 1140 "auto", LAUTO, 0, 1141 "break", LBREAK, 0, 1142 "case", LCASE, 0, 1143 "char", LCHAR, TCHAR, 1144 "const", LCONSTNT, 0, 1145 "continue", LCONTINUE, 0, 1146 "default", LDEFAULT, 0, 1147 "do", LDO, 0, 1148 "double", LDOUBLE, TDOUBLE, 1149 "else", LELSE, 0, 1150 "enum", LENUM, 0, 1151 "extern", LEXTERN, 0, 1152 "float", LFLOAT, TFLOAT, 1153 "for", LFOR, 0, 1154 "goto", LGOTO, 0, 1155 "if", LIF, 0, 1156 "inline", LINLINE, 0, 1157 "int", LINT, TINT, 1158 "long", LLONG, TLONG, 1159 "register", LREGISTER, 0, 1160 "restrict", LRESTRICT, 0, 1161 "return", LRETURN, 0, 1162 "SET", LSET, 0, 1163 "short", LSHORT, TSHORT, 1164 "signed", LSIGNED, 0, 1165 "signof", LSIGNOF, 0, 1166 "sizeof", LSIZEOF, 0, 1167 "static", LSTATIC, 0, 1168 "struct", LSTRUCT, 0, 1169 "switch", LSWITCH, 0, 1170 "typedef", LTYPEDEF, 0, 1171 "typestr", LTYPESTR, 0, 1172 "union", LUNION, 0, 1173 "unsigned", LUNSIGNED, 0, 1174 "USED", LUSED, 0, 1175 "void", LVOID, TVOID, 1176 "volatile", LVOLATILE, 0, 1177 "while", LWHILE, 0, 1178 0 1179 }; 1180 1181 void 1182 cinit(void) 1183 { 1184 Sym *s; 1185 int i; 1186 Type *t; 1187 1188 nerrors = 0; 1189 lineno = 1; 1190 iostack = I; 1191 iofree = I; 1192 peekc = IGN; 1193 nhunk = 0; 1194 1195 types[TXXX] = T; 1196 types[TCHAR] = typ(TCHAR, T); 1197 types[TUCHAR] = typ(TUCHAR, T); 1198 types[TSHORT] = typ(TSHORT, T); 1199 types[TUSHORT] = typ(TUSHORT, T); 1200 types[TINT] = typ(TINT, T); 1201 types[TUINT] = typ(TUINT, T); 1202 types[TLONG] = typ(TLONG, T); 1203 types[TULONG] = typ(TULONG, T); 1204 types[TVLONG] = typ(TVLONG, T); 1205 types[TUVLONG] = typ(TUVLONG, T); 1206 types[TFLOAT] = typ(TFLOAT, T); 1207 types[TDOUBLE] = typ(TDOUBLE, T); 1208 types[TVOID] = typ(TVOID, T); 1209 types[TENUM] = typ(TENUM, T); 1210 types[TFUNC] = typ(TFUNC, types[TINT]); 1211 types[TIND] = typ(TIND, types[TVOID]); 1212 1213 for(i=0; i<NHASH; i++) 1214 hash[i] = S; 1215 for(i=0; itab[i].name; i++) { 1216 s = slookup(itab[i].name); 1217 s->lexical = itab[i].lexical; 1218 if(itab[i].type != 0) 1219 s->type = types[itab[i].type]; 1220 } 1221 blockno = 0; 1222 autobn = 0; 1223 autoffset = 0; 1224 1225 t = typ(TARRAY, types[TCHAR]); 1226 t->width = 0; 1227 symstring = slookup(".string"); 1228 symstring->class = CSTATIC; 1229 symstring->type = t; 1230 1231 t = typ(TARRAY, types[TCHAR]); 1232 t->width = 0; 1233 1234 nodproto = new(OPROTO, Z, Z); 1235 dclstack = D; 1236 1237 pathname = allocn(pathname, 0, 100); 1238 if(mygetwd(pathname, 99) == 0) { 1239 pathname = allocn(pathname, 100, 900); 1240 if(mygetwd(pathname, 999) == 0) 1241 strcpy(pathname, "/???"); 1242 } 1243 1244 fmtinstall('O', Oconv); 1245 fmtinstall('T', Tconv); 1246 fmtinstall('F', FNconv); 1247 fmtinstall('L', Lconv); 1248 fmtinstall('Q', Qconv); 1249 fmtinstall('|', VBconv); 1250 } 1251 1252 int 1253 filbuf(void) 1254 { 1255 Io *i; 1256 1257 loop: 1258 i = iostack; 1259 if(i == I) 1260 return EOF; 1261 if(i->f < 0) 1262 goto pop; 1263 fi.c = read(i->f, i->b, BUFSIZ) - 1; 1264 if(fi.c < 0) { 1265 close(i->f); 1266 linehist(0, 0); 1267 goto pop; 1268 } 1269 fi.p = i->b + 1; 1270 return i->b[0] & 0xff; 1271 1272 pop: 1273 iostack = i->link; 1274 i->link = iofree; 1275 iofree = i; 1276 i = iostack; 1277 if(i == I) 1278 return EOF; 1279 fi.p = i->p; 1280 fi.c = i->c; 1281 if(--fi.c < 0) 1282 goto loop; 1283 return *fi.p++ & 0xff; 1284 } 1285 1286 int 1287 Oconv(Fmt *fp) 1288 { 1289 int a; 1290 1291 a = va_arg(fp->args, int); 1292 if(a < OXXX || a > OEND) 1293 return fmtprint(fp, "***badO %d***", a); 1294 1295 return fmtstrcpy(fp, onames[a]); 1296 } 1297 1298 int 1299 Lconv(Fmt *fp) 1300 { 1301 char str[STRINGSZ], s[STRINGSZ]; 1302 Hist *h; 1303 struct 1304 { 1305 Hist* incl; /* start of this include file */ 1306 long idel; /* delta line number to apply to include */ 1307 Hist* line; /* start of this #line directive */ 1308 long ldel; /* delta line number to apply to #line */ 1309 } a[HISTSZ]; 1310 long l, d; 1311 int i, n; 1312 1313 l = va_arg(fp->args, long); 1314 n = 0; 1315 for(h = hist; h != H; h = h->link) { 1316 if(l < h->line) 1317 break; 1318 if(h->name) { 1319 if(h->offset != 0) { /* #line directive, not #pragma */ 1320 if(n > 0 && n < HISTSZ && h->offset >= 0) { 1321 a[n-1].line = h; 1322 a[n-1].ldel = h->line - h->offset + 1; 1323 } 1324 } else { 1325 if(n < HISTSZ) { /* beginning of file */ 1326 a[n].incl = h; 1327 a[n].idel = h->line; 1328 a[n].line = 0; 1329 } 1330 n++; 1331 } 1332 continue; 1333 } 1334 n--; 1335 if(n > 0 && n < HISTSZ) { 1336 d = h->line - a[n].incl->line; 1337 a[n-1].ldel += d; 1338 a[n-1].idel += d; 1339 } 1340 } 1341 if(n > HISTSZ) 1342 n = HISTSZ; 1343 str[0] = 0; 1344 for(i=n-1; i>=0; i--) { 1345 if(i != n-1) { 1346 if(fp->flags & ~(FmtWidth|FmtPrec)) /* BUG ROB - was f3 */ 1347 break; 1348 strcat(str, " "); 1349 } 1350 if(a[i].line) 1351 snprint(s, STRINGSZ, "%s:%ld[%s:%ld]", 1352 a[i].line->name, l-a[i].ldel+1, 1353 a[i].incl->name, l-a[i].idel+1); 1354 else 1355 snprint(s, STRINGSZ, "%s:%ld", 1356 a[i].incl->name, l-a[i].idel+1); 1357 if(strlen(s)+strlen(str) >= STRINGSZ-10) 1358 break; 1359 strcat(str, s); 1360 l = a[i].incl->line - 1; /* now print out start of this file */ 1361 } 1362 if(n == 0) 1363 strcat(str, "<eof>"); 1364 return fmtstrcpy(fp, str); 1365 } 1366 1367 int 1368 Tconv(Fmt *fp) 1369 { 1370 char str[STRINGSZ+20], s[STRINGSZ+20]; 1371 Type *t, *t1; 1372 int et; 1373 long n; 1374 1375 str[0] = 0; 1376 for(t = va_arg(fp->args, Type*); t != T; t = t->link) { 1377 et = t->etype; 1378 if(str[0]) 1379 strcat(str, " "); 1380 if(t->garb&~GINCOMPLETE) { 1381 sprint(s, "%s ", gnames[t->garb&~GINCOMPLETE]); 1382 if(strlen(str) + strlen(s) < STRINGSZ) 1383 strcat(str, s); 1384 } 1385 sprint(s, "%s", tnames[et]); 1386 if(strlen(str) + strlen(s) < STRINGSZ) 1387 strcat(str, s); 1388 if(et == TFUNC && (t1 = t->down)) { 1389 sprint(s, "(%T", t1); 1390 if(strlen(str) + strlen(s) < STRINGSZ) 1391 strcat(str, s); 1392 while(t1 = t1->down) { 1393 sprint(s, ", %T", t1); 1394 if(strlen(str) + strlen(s) < STRINGSZ) 1395 strcat(str, s); 1396 } 1397 if(strlen(str) + strlen(s) < STRINGSZ) 1398 strcat(str, ")"); 1399 } 1400 if(et == TARRAY) { 1401 n = t->width; 1402 if(t->link && t->link->width) 1403 n /= t->link->width; 1404 sprint(s, "[%ld]", n); 1405 if(strlen(str) + strlen(s) < STRINGSZ) 1406 strcat(str, s); 1407 } 1408 if(t->nbits) { 1409 sprint(s, " %d:%d", t->shift, t->nbits); 1410 if(strlen(str) + strlen(s) < STRINGSZ) 1411 strcat(str, s); 1412 } 1413 if(typesu[et]) { 1414 if(t->tag) { 1415 strcat(str, " "); 1416 if(strlen(str) + strlen(t->tag->name) < STRINGSZ) 1417 strcat(str, t->tag->name); 1418 } else 1419 strcat(str, " {}"); 1420 break; 1421 } 1422 } 1423 return fmtstrcpy(fp, str); 1424 } 1425 1426 int 1427 FNconv(Fmt *fp) 1428 { 1429 char *str; 1430 Node *n; 1431 1432 n = va_arg(fp->args, Node*); 1433 str = "<indirect>"; 1434 if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM)) 1435 str = n->sym->name; 1436 return fmtstrcpy(fp, str); 1437 } 1438 1439 int 1440 Qconv(Fmt *fp) 1441 { 1442 char str[STRINGSZ+20], *s; 1443 long b; 1444 int i; 1445 1446 str[0] = 0; 1447 for(b = va_arg(fp->args, long); b;) { 1448 i = bitno(b); 1449 if(str[0]) 1450 strcat(str, " "); 1451 s = qnames[i]; 1452 if(strlen(str) + strlen(s) >= STRINGSZ) 1453 break; 1454 strcat(str, s); 1455 b &= ~(1L << i); 1456 } 1457 return fmtstrcpy(fp, str); 1458 } 1459 1460 int 1461 VBconv(Fmt *fp) 1462 { 1463 char str[STRINGSZ]; 1464 int i, n, t, pc; 1465 1466 n = va_arg(fp->args, int); 1467 pc = 0; /* BUG: was printcol */ 1468 i = 0; 1469 while(pc < n) { 1470 t = (pc+4) & ~3; 1471 if(t <= n) { 1472 str[i++] = '\t'; 1473 pc = t; 1474 continue; 1475 } 1476 str[i++] = ' '; 1477 pc++; 1478 } 1479 str[i] = 0; 1480 1481 return fmtstrcpy(fp, str); 1482 } 1483 1484 /* 1485 * real allocs 1486 */ 1487 void* 1488 alloc(long n) 1489 { 1490 void *p; 1491 1492 while((uintptr)hunk & MAXALIGN) { 1493 hunk++; 1494 nhunk--; 1495 } 1496 while(nhunk < n) 1497 gethunk(); 1498 p = hunk; 1499 nhunk -= n; 1500 hunk += n; 1501 return p; 1502 } 1503 1504 void* 1505 allocn(void *p, long on, long n) 1506 { 1507 void *q; 1508 1509 q = (uchar*)p + on; 1510 if(q != hunk || nhunk < n) { 1511 while(nhunk < on+n) 1512 gethunk(); 1513 memmove(hunk, p, on); 1514 p = hunk; 1515 hunk += on; 1516 nhunk -= on; 1517 } 1518 hunk += n; 1519 nhunk -= n; 1520 return p; 1521 } 1522 1523 void 1524 setinclude(char *p) 1525 { 1526 int i; 1527 char *e; 1528 1529 while(*p != 0) { 1530 e = strchr(p, ' '); 1531 if(e != 0) 1532 *e = '\0'; 1533 1534 for(i=1; i < ninclude; i++) 1535 if(strcmp(p, include[i]) == 0) 1536 break; 1537 1538 if(i >= ninclude) 1539 include[ninclude++] = p; 1540 1541 if(ninclude > nelem(include)) { 1542 diag(Z, "ninclude too small %d", nelem(include)); 1543 exits("ninclude"); 1544 } 1545 1546 if(e == 0) 1547 break; 1548 p = e+1; 1549 } 1550 } 1551