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