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