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