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