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