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, dup(1, -1), OWRITE); 207 dup(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 yylval.dval = strtod(symb, nil); 894 if(isInf(yylval.dval, 1) || isInf(yylval.dval, -1)) { 895 yyerror("overflow in float constant"); 896 yylval.dval = 0; 897 } 898 if(c1 & Numflt) 899 return LFCONST; 900 return LDCONST; 901 } 902 903 /* 904 * convert a string, s, to vlong in *v 905 * return conversion overflow. 906 * required syntax is [0[x]]d* 907 */ 908 int 909 mpatov(char *s, vlong *v) 910 { 911 vlong n, nn; 912 int c; 913 914 n = 0; 915 c = *s; 916 if(c == '0') 917 goto oct; 918 while(c = *s++) { 919 if(c >= '0' && c <= '9') 920 nn = n*10 + c-'0'; 921 else 922 goto bad; 923 if(n < 0 && nn >= 0) 924 goto bad; 925 n = nn; 926 } 927 goto out; 928 929 oct: 930 s++; 931 c = *s; 932 if(c == 'x' || c == 'X') 933 goto hex; 934 while(c = *s++) { 935 if(c >= '0' || c <= '7') 936 nn = n*8 + c-'0'; 937 else 938 goto bad; 939 if(n < 0 && nn >= 0) 940 goto bad; 941 n = nn; 942 } 943 goto out; 944 945 hex: 946 s++; 947 while(c = *s++) { 948 if(c >= '0' && c <= '9') 949 c += 0-'0'; 950 else 951 if(c >= 'a' && c <= 'f') 952 c += 10-'a'; 953 else 954 if(c >= 'A' && c <= 'F') 955 c += 10-'A'; 956 else 957 goto bad; 958 nn = n*16 + c; 959 if(n < 0 && nn >= 0) 960 goto bad; 961 n = nn; 962 } 963 out: 964 *v = n; 965 return 0; 966 967 bad: 968 *v = ~0; 969 return 1; 970 } 971 972 int 973 getc(void) 974 { 975 int c; 976 977 if(peekc != IGN) { 978 c = peekc; 979 peekc = IGN; 980 } else 981 c = GETC(); 982 if(c == '\n') 983 lineno++; 984 if(c == EOF) { 985 yyerror("End of file"); 986 errorexit(); 987 } 988 return c; 989 } 990 991 long 992 getr(void) 993 { 994 int c, i; 995 char str[UTFmax+1]; 996 Rune rune; 997 998 999 c = getc(); 1000 if(c < Runeself) 1001 return c; 1002 i = 0; 1003 str[i++] = c; 1004 1005 loop: 1006 c = getc(); 1007 str[i++] = c; 1008 if(!fullrune(str, i)) 1009 goto loop; 1010 c = chartorune(&rune, str); 1011 if(rune == Runeerror && c == 1) { 1012 nearln = lineno; 1013 diag(Z, "illegal rune in string"); 1014 for(c=0; c<i; c++) 1015 print(" %.2x", *(uchar*)(str+c)); 1016 print("\n"); 1017 } 1018 return rune; 1019 } 1020 1021 int 1022 getnsc(void) 1023 { 1024 int c; 1025 1026 if(peekc != IGN) { 1027 c = peekc; 1028 peekc = IGN; 1029 } else 1030 c = GETC(); 1031 for(;;) { 1032 if(!isspace(c)) 1033 return c; 1034 if(c == '\n') { 1035 lineno++; 1036 return c; 1037 } 1038 c = GETC(); 1039 } 1040 } 1041 1042 void 1043 unget(int c) 1044 { 1045 1046 peekc = c; 1047 if(c == '\n') 1048 lineno--; 1049 } 1050 1051 long 1052 escchar(long e, int longflg, int escflg) 1053 { 1054 long c, l; 1055 int i; 1056 1057 loop: 1058 c = getr(); 1059 if(c == '\n') { 1060 yyerror("newline in string"); 1061 return EOF; 1062 } 1063 if(c != '\\') { 1064 if(c == e) 1065 c = EOF; 1066 return c; 1067 } 1068 c = getr(); 1069 if(c == 'x') { 1070 /* 1071 * note this is not ansi, 1072 * supposed to only accept 2 hex 1073 */ 1074 i = 2; 1075 if(longflg) 1076 i = 4; 1077 l = 0; 1078 for(; i>0; i--) { 1079 c = getc(); 1080 if(c >= '0' && c <= '9') { 1081 l = l*16 + c-'0'; 1082 continue; 1083 } 1084 if(c >= 'a' && c <= 'f') { 1085 l = l*16 + c-'a' + 10; 1086 continue; 1087 } 1088 if(c >= 'A' && c <= 'F') { 1089 l = l*16 + c-'A' + 10; 1090 continue; 1091 } 1092 unget(c); 1093 break; 1094 } 1095 if(escflg) 1096 l |= ESC; 1097 return l; 1098 } 1099 if(c >= '0' && c <= '7') { 1100 /* 1101 * note this is not ansi, 1102 * supposed to only accept 3 oct 1103 */ 1104 i = 2; 1105 if(longflg) 1106 i = 5; 1107 l = c - '0'; 1108 for(; i>0; i--) { 1109 c = getc(); 1110 if(c >= '0' && c <= '7') { 1111 l = l*8 + c-'0'; 1112 continue; 1113 } 1114 unget(c); 1115 } 1116 if(escflg) 1117 l |= ESC; 1118 return l; 1119 } 1120 switch(c) 1121 { 1122 case '\n': goto loop; 1123 case 'n': return '\n'; 1124 case 't': return '\t'; 1125 case 'b': return '\b'; 1126 case 'r': return '\r'; 1127 case 'f': return '\f'; 1128 case 'a': return '\a'; 1129 case 'v': return '\v'; 1130 } 1131 return c; 1132 } 1133 1134 struct 1135 { 1136 char *name; 1137 ushort lexical; 1138 ushort type; 1139 } itab[] = 1140 { 1141 "auto", LAUTO, 0, 1142 "break", LBREAK, 0, 1143 "case", LCASE, 0, 1144 "char", LCHAR, TCHAR, 1145 "const", LCONSTNT, 0, 1146 "continue", LCONTINUE, 0, 1147 "default", LDEFAULT, 0, 1148 "do", LDO, 0, 1149 "double", LDOUBLE, TDOUBLE, 1150 "else", LELSE, 0, 1151 "enum", LENUM, 0, 1152 "extern", LEXTERN, 0, 1153 "float", LFLOAT, TFLOAT, 1154 "for", LFOR, 0, 1155 "goto", LGOTO, 0, 1156 "if", LIF, 0, 1157 "inline", LINLINE, 0, 1158 "int", LINT, TINT, 1159 "long", LLONG, TLONG, 1160 "register", LREGISTER, 0, 1161 "restrict", LRESTRICT, 0, 1162 "return", LRETURN, 0, 1163 "SET", LSET, 0, 1164 "short", LSHORT, TSHORT, 1165 "signed", LSIGNED, 0, 1166 "signof", LSIGNOF, 0, 1167 "sizeof", LSIZEOF, 0, 1168 "static", LSTATIC, 0, 1169 "struct", LSTRUCT, 0, 1170 "switch", LSWITCH, 0, 1171 "typedef", LTYPEDEF, 0, 1172 "typestr", LTYPESTR, 0, 1173 "union", LUNION, 0, 1174 "unsigned", LUNSIGNED, 0, 1175 "USED", LUSED, 0, 1176 "void", LVOID, TVOID, 1177 "volatile", LVOLATILE, 0, 1178 "while", LWHILE, 0, 1179 0 1180 }; 1181 1182 void 1183 cinit(void) 1184 { 1185 Sym *s; 1186 int i; 1187 Type *t; 1188 1189 nerrors = 0; 1190 lineno = 1; 1191 iostack = I; 1192 iofree = I; 1193 peekc = IGN; 1194 nhunk = 0; 1195 1196 types[TXXX] = T; 1197 types[TCHAR] = typ(TCHAR, T); 1198 types[TUCHAR] = typ(TUCHAR, T); 1199 types[TSHORT] = typ(TSHORT, T); 1200 types[TUSHORT] = typ(TUSHORT, T); 1201 types[TINT] = typ(TINT, T); 1202 types[TUINT] = typ(TUINT, T); 1203 types[TLONG] = typ(TLONG, T); 1204 types[TULONG] = typ(TULONG, T); 1205 types[TVLONG] = typ(TVLONG, T); 1206 types[TUVLONG] = typ(TUVLONG, T); 1207 types[TFLOAT] = typ(TFLOAT, T); 1208 types[TDOUBLE] = typ(TDOUBLE, T); 1209 types[TVOID] = typ(TVOID, T); 1210 types[TENUM] = typ(TENUM, T); 1211 types[TFUNC] = typ(TFUNC, types[TINT]); 1212 types[TIND] = typ(TIND, types[TVOID]); 1213 1214 for(i=0; i<NHASH; i++) 1215 hash[i] = S; 1216 for(i=0; itab[i].name; i++) { 1217 s = slookup(itab[i].name); 1218 s->lexical = itab[i].lexical; 1219 if(itab[i].type != 0) 1220 s->type = types[itab[i].type]; 1221 } 1222 blockno = 0; 1223 autobn = 0; 1224 autoffset = 0; 1225 1226 t = typ(TARRAY, types[TCHAR]); 1227 t->width = 0; 1228 symstring = slookup(".string"); 1229 symstring->class = CSTATIC; 1230 symstring->type = t; 1231 1232 t = typ(TARRAY, types[TCHAR]); 1233 t->width = 0; 1234 1235 nodproto = new(OPROTO, Z, Z); 1236 dclstack = D; 1237 1238 pathname = allocn(pathname, 0, 100); 1239 if(mygetwd(pathname, 99) == 0) { 1240 pathname = allocn(pathname, 100, 900); 1241 if(mygetwd(pathname, 999) == 0) 1242 strcpy(pathname, "/???"); 1243 } 1244 1245 fmtinstall('O', Oconv); 1246 fmtinstall('T', Tconv); 1247 fmtinstall('F', FNconv); 1248 fmtinstall('L', Lconv); 1249 fmtinstall('Q', Qconv); 1250 fmtinstall('|', VBconv); 1251 } 1252 1253 int 1254 filbuf(void) 1255 { 1256 Io *i; 1257 1258 loop: 1259 i = iostack; 1260 if(i == I) 1261 return EOF; 1262 if(i->f < 0) 1263 goto pop; 1264 fi.c = read(i->f, i->b, BUFSIZ) - 1; 1265 if(fi.c < 0) { 1266 close(i->f); 1267 linehist(0, 0); 1268 goto pop; 1269 } 1270 fi.p = i->b + 1; 1271 return i->b[0] & 0xff; 1272 1273 pop: 1274 iostack = i->link; 1275 i->link = iofree; 1276 iofree = i; 1277 i = iostack; 1278 if(i == I) 1279 return EOF; 1280 fi.p = i->p; 1281 fi.c = i->c; 1282 if(--fi.c < 0) 1283 goto loop; 1284 return *fi.p++ & 0xff; 1285 } 1286 1287 int 1288 Oconv(Fmt *fp) 1289 { 1290 int a; 1291 1292 a = va_arg(fp->args, int); 1293 if(a < OXXX || a > OEND) 1294 return fmtprint(fp, "***badO %d***", a); 1295 1296 return fmtstrcpy(fp, onames[a]); 1297 } 1298 1299 int 1300 Lconv(Fmt *fp) 1301 { 1302 char str[STRINGSZ], s[STRINGSZ]; 1303 Hist *h; 1304 struct 1305 { 1306 Hist* incl; /* start of this include file */ 1307 long idel; /* delta line number to apply to include */ 1308 Hist* line; /* start of this #line directive */ 1309 long ldel; /* delta line number to apply to #line */ 1310 } a[HISTSZ]; 1311 long l, d; 1312 int i, n; 1313 1314 l = va_arg(fp->args, long); 1315 n = 0; 1316 for(h = hist; h != H; h = h->link) { 1317 if(l < h->line) 1318 break; 1319 if(h->name) { 1320 if(h->offset != 0) { /* #line directive, not #pragma */ 1321 if(n > 0 && n < HISTSZ && h->offset >= 0) { 1322 a[n-1].line = h; 1323 a[n-1].ldel = h->line - h->offset + 1; 1324 } 1325 } else { 1326 if(n < HISTSZ) { /* beginning of file */ 1327 a[n].incl = h; 1328 a[n].idel = h->line; 1329 a[n].line = 0; 1330 } 1331 n++; 1332 } 1333 continue; 1334 } 1335 n--; 1336 if(n > 0 && n < HISTSZ) { 1337 d = h->line - a[n].incl->line; 1338 a[n-1].ldel += d; 1339 a[n-1].idel += d; 1340 } 1341 } 1342 if(n > HISTSZ) 1343 n = HISTSZ; 1344 str[0] = 0; 1345 for(i=n-1; i>=0; i--) { 1346 if(i != n-1) { 1347 if(fp->flags & ~(FmtWidth|FmtPrec)) /* BUG ROB - was f3 */ 1348 break; 1349 strcat(str, " "); 1350 } 1351 if(a[i].line) 1352 snprint(s, STRINGSZ, "%s:%ld[%s:%ld]", 1353 a[i].line->name, l-a[i].ldel+1, 1354 a[i].incl->name, l-a[i].idel+1); 1355 else 1356 snprint(s, STRINGSZ, "%s:%ld", 1357 a[i].incl->name, l-a[i].idel+1); 1358 if(strlen(s)+strlen(str) >= STRINGSZ-10) 1359 break; 1360 strcat(str, s); 1361 l = a[i].incl->line - 1; /* now print out start of this file */ 1362 } 1363 if(n == 0) 1364 strcat(str, "<eof>"); 1365 return fmtstrcpy(fp, str); 1366 } 1367 1368 int 1369 Tconv(Fmt *fp) 1370 { 1371 char str[STRINGSZ+20], s[STRINGSZ+20]; 1372 Type *t, *t1; 1373 int et; 1374 long n; 1375 1376 str[0] = 0; 1377 for(t = va_arg(fp->args, Type*); t != T; t = t->link) { 1378 et = t->etype; 1379 if(str[0]) 1380 strcat(str, " "); 1381 if(t->garb&~GINCOMPLETE) { 1382 sprint(s, "%s ", gnames[t->garb&~GINCOMPLETE]); 1383 if(strlen(str) + strlen(s) < STRINGSZ) 1384 strcat(str, s); 1385 } 1386 sprint(s, "%s", tnames[et]); 1387 if(strlen(str) + strlen(s) < STRINGSZ) 1388 strcat(str, s); 1389 if(et == TFUNC && (t1 = t->down)) { 1390 sprint(s, "(%T", t1); 1391 if(strlen(str) + strlen(s) < STRINGSZ) 1392 strcat(str, s); 1393 while(t1 = t1->down) { 1394 sprint(s, ", %T", t1); 1395 if(strlen(str) + strlen(s) < STRINGSZ) 1396 strcat(str, s); 1397 } 1398 if(strlen(str) + strlen(s) < STRINGSZ) 1399 strcat(str, ")"); 1400 } 1401 if(et == TARRAY) { 1402 n = t->width; 1403 if(t->link && t->link->width) 1404 n /= t->link->width; 1405 sprint(s, "[%ld]", n); 1406 if(strlen(str) + strlen(s) < STRINGSZ) 1407 strcat(str, s); 1408 } 1409 if(t->nbits) { 1410 sprint(s, " %d:%d", t->shift, t->nbits); 1411 if(strlen(str) + strlen(s) < STRINGSZ) 1412 strcat(str, s); 1413 } 1414 if(typesu[et]) { 1415 if(t->tag) { 1416 strcat(str, " "); 1417 if(strlen(str) + strlen(t->tag->name) < STRINGSZ) 1418 strcat(str, t->tag->name); 1419 } else 1420 strcat(str, " {}"); 1421 break; 1422 } 1423 } 1424 return fmtstrcpy(fp, str); 1425 } 1426 1427 int 1428 FNconv(Fmt *fp) 1429 { 1430 char *str; 1431 Node *n; 1432 1433 n = va_arg(fp->args, Node*); 1434 str = "<indirect>"; 1435 if(n != Z && (n->op == ONAME || n->op == ODOT || n->op == OELEM)) 1436 str = n->sym->name; 1437 return fmtstrcpy(fp, str); 1438 } 1439 1440 int 1441 Qconv(Fmt *fp) 1442 { 1443 char str[STRINGSZ+20], *s; 1444 long b; 1445 int i; 1446 1447 str[0] = 0; 1448 for(b = va_arg(fp->args, long); b;) { 1449 i = bitno(b); 1450 if(str[0]) 1451 strcat(str, " "); 1452 s = qnames[i]; 1453 if(strlen(str) + strlen(s) >= STRINGSZ) 1454 break; 1455 strcat(str, s); 1456 b &= ~(1L << i); 1457 } 1458 return fmtstrcpy(fp, str); 1459 } 1460 1461 int 1462 VBconv(Fmt *fp) 1463 { 1464 char str[STRINGSZ]; 1465 int i, n, t, pc; 1466 1467 n = va_arg(fp->args, int); 1468 pc = 0; /* BUG: was printcol */ 1469 i = 0; 1470 while(pc < n) { 1471 t = (pc+4) & ~3; 1472 if(t <= n) { 1473 str[i++] = '\t'; 1474 pc = t; 1475 continue; 1476 } 1477 str[i++] = ' '; 1478 pc++; 1479 } 1480 str[i] = 0; 1481 1482 return fmtstrcpy(fp, str); 1483 } 1484 1485 /* 1486 * real allocs 1487 */ 1488 void* 1489 alloc(long n) 1490 { 1491 void *p; 1492 1493 while((uintptr)hunk & MAXALIGN) { 1494 hunk++; 1495 nhunk--; 1496 } 1497 while(nhunk < n) 1498 gethunk(); 1499 p = hunk; 1500 nhunk -= n; 1501 hunk += n; 1502 return p; 1503 } 1504 1505 void* 1506 allocn(void *p, long on, long n) 1507 { 1508 void *q; 1509 1510 q = (uchar*)p + on; 1511 if(q != hunk || nhunk < n) { 1512 while(nhunk < on+n) 1513 gethunk(); 1514 memmove(hunk, p, on); 1515 p = hunk; 1516 hunk += on; 1517 nhunk -= on; 1518 } 1519 hunk += n; 1520 nhunk -= n; 1521 return p; 1522 } 1523 1524 void 1525 setinclude(char *p) 1526 { 1527 int i; 1528 char *e; 1529 1530 while(*p != 0) { 1531 e = strchr(p, ' '); 1532 if(e != 0) 1533 *e = '\0'; 1534 1535 for(i=1; i < ninclude; i++) 1536 if(strcmp(p, include[i]) == 0) 1537 break; 1538 1539 if(i >= ninclude) 1540 include[ninclude++] = p; 1541 1542 if(ninclude > nelem(include)) { 1543 diag(Z, "ninclude too small %d", nelem(include)); 1544 exits("ninclude"); 1545 } 1546 1547 if(e == 0) 1548 break; 1549 p = e+1; 1550 } 1551 } 1552