github.com/yanyiwu/go@v0.0.0-20150106053140-03d6637dbb7f/src/cmd/cc/lexbody (about) 1 // Inferno utils/cc/lexbody 2 // http://code.google.com/p/inferno-os/source/browse/utils/cc/lexbody 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 /* 32 * common code for all the assemblers 33 */ 34 35 void 36 pragpack(void) 37 { 38 while(getnsc() != '\n') 39 ; 40 } 41 42 void 43 pragvararg(void) 44 { 45 while(getnsc() != '\n') 46 ; 47 } 48 49 void 50 pragcgo(char *name) 51 { 52 USED(name); 53 while(getnsc() != '\n') 54 ; 55 } 56 57 void 58 pragfpround(void) 59 { 60 while(getnsc() != '\n') 61 ; 62 } 63 64 void 65 pragtextflag(void) 66 { 67 while(getnsc() != '\n') 68 ; 69 } 70 71 void 72 pragdataflag(void) 73 { 74 while(getnsc() != '\n') 75 ; 76 } 77 78 void 79 pragprofile(void) 80 { 81 while(getnsc() != '\n') 82 ; 83 } 84 85 void 86 pragincomplete(void) 87 { 88 while(getnsc() != '\n') 89 ; 90 } 91 92 void* 93 alloc(int32 n) 94 { 95 void *p; 96 97 p = malloc(n); 98 if(p == nil) { 99 print("alloc out of mem\n"); 100 exits("alloc: out of mem"); 101 } 102 memset(p, 0, n); 103 return p; 104 } 105 106 void* 107 allocn(void *p, int32 n, int32 d) 108 { 109 if(p == nil) 110 return alloc(n+d); 111 p = realloc(p, n+d); 112 if(p == nil) { 113 print("allocn out of mem\n"); 114 exits("allocn: out of mem"); 115 } 116 if(d > 0) 117 memset((char*)p+n, 0, d); 118 return p; 119 } 120 121 void 122 ensuresymb(int32 n) 123 { 124 if(symb == nil) { 125 symb = alloc(NSYMB+1); 126 nsymb = NSYMB; 127 } 128 129 if(n > nsymb) { 130 symb = allocn(symb, nsymb, n+1-nsymb); 131 nsymb = n; 132 } 133 } 134 135 void 136 setinclude(char *p) 137 { 138 int i; 139 140 if(p == 0) 141 return; 142 for(i=1; i < ninclude; i++) 143 if(strcmp(p, include[i]) == 0) 144 return; 145 146 if(ninclude%8 == 0) 147 include = allocn(include, ninclude*sizeof(char *), 148 8*sizeof(char *)); 149 include[ninclude++] = p; 150 } 151 152 void 153 errorexit(void) 154 { 155 Bflush(&bstdout); 156 if(outfile) 157 remove(outfile); 158 exits("error"); 159 } 160 161 void 162 pushio(void) 163 { 164 Io *i; 165 166 i = iostack; 167 if(i == I) { 168 yyerror("botch in pushio"); 169 errorexit(); 170 } 171 i->p = fi.p; 172 i->c = fi.c; 173 } 174 175 void 176 newio(void) 177 { 178 Io *i; 179 static int pushdepth = 0; 180 181 i = iofree; 182 if(i == I) { 183 pushdepth++; 184 if(pushdepth > 1000) { 185 yyerror("macro/io expansion too deep"); 186 errorexit(); 187 } 188 i = alloc(sizeof(*i)); 189 } else 190 iofree = i->link; 191 i->c = 0; 192 i->f = -1; 193 ionext = i; 194 } 195 196 void 197 newfile(char *s, int f) 198 { 199 Io *i; 200 201 i = ionext; 202 i->link = iostack; 203 iostack = i; 204 i->f = f; 205 if(f < 0) 206 i->f = open(s, 0); 207 if(i->f < 0) { 208 yyerror("%ca: %r: %s", thechar, s); 209 errorexit(); 210 } 211 fi.c = 0; 212 linklinehist(ctxt, lineno, s, 0); 213 } 214 215 Sym* 216 slookup(char *s) 217 { 218 ensuresymb(strlen(s)); 219 strcpy(symb, s); 220 return lookup(); 221 } 222 223 LSym *thetext; 224 225 void 226 settext(LSym *s) 227 { 228 thetext = s; 229 } 230 231 Sym* 232 labellookup(Sym *s) 233 { 234 char *p; 235 Sym *lab; 236 237 if(thetext == nil) { 238 s->labelname = s->name; 239 return s; 240 } 241 p = smprint("%s.%s", thetext->name, s->name); 242 lab = slookup(p); 243 free(p); 244 lab->labelname = s->name; 245 return lab; 246 } 247 248 Sym* 249 lookup(void) 250 { 251 Sym *s; 252 uint32 h; 253 char *p; 254 int c, l; 255 char *r, *w; 256 257 if((uchar)symb[0] == 0xc2 && (uchar)symb[1] == 0xb7) { 258 // turn leading · into ""· 259 h = strlen(symb); 260 ensuresymb(h+2); 261 memmove(symb+2, symb, h+1); 262 symb[0] = '"'; 263 symb[1] = '"'; 264 } 265 266 for(r=w=symb; *r; r++) { 267 // turn · (U+00B7) into . 268 // turn ∕ (U+2215) into / 269 if((uchar)*r == 0xc2 && (uchar)*(r+1) == 0xb7) { 270 *w++ = '.'; 271 r++; 272 }else if((uchar)*r == 0xe2 && (uchar)*(r+1) == 0x88 && (uchar)*(r+2) == 0x95) { 273 *w++ = '/'; 274 r++; 275 r++; 276 }else 277 *w++ = *r; 278 } 279 *w = '\0'; 280 281 h = 0; 282 for(p=symb; c = *p; p++) 283 h = h+h+h + c; 284 l = (p - symb) + 1; 285 h &= 0xffffff; 286 h %= NHASH; 287 c = symb[0]; 288 for(s = hash[h]; s != S; s = s->link) { 289 if(s->name[0] != c) 290 continue; 291 if(strcmp(s->name, symb) == 0) 292 return s; 293 } 294 s = alloc(sizeof(*s)); 295 s->name = alloc(l); 296 memmove(s->name, symb, l); 297 298 s->link = hash[h]; 299 hash[h] = s; 300 syminit(s); 301 return s; 302 } 303 304 int 305 ISALPHA(int c) 306 { 307 if(isalpha(c)) 308 return 1; 309 if(c >= Runeself) 310 return 1; 311 return 0; 312 } 313 314 int32 315 yylex(void) 316 { 317 int c, c1; 318 char *cp; 319 Sym *s; 320 321 c = peekc; 322 if(c != IGN) { 323 peekc = IGN; 324 goto l1; 325 } 326 l0: 327 c = GETC(); 328 329 l1: 330 if(c == EOF) { 331 peekc = EOF; 332 return -1; 333 } 334 if(isspace(c)) { 335 if(c == '\n') { 336 lineno++; 337 return ';'; 338 } 339 goto l0; 340 } 341 if(ISALPHA(c)) 342 goto talph; 343 if(isdigit(c)) 344 goto tnum; 345 switch(c) 346 { 347 case '\n': 348 lineno++; 349 return ';'; 350 351 case '#': 352 domacro(); 353 goto l0; 354 355 case '.': 356 c = GETC(); 357 if(ISALPHA(c)) { 358 cp = symb; 359 *cp++ = '.'; 360 goto aloop; 361 } 362 if(isdigit(c)) { 363 cp = symb; 364 *cp++ = '.'; 365 goto casedot; 366 } 367 peekc = c; 368 return '.'; 369 370 talph: 371 case '_': 372 case '@': 373 cp = symb; 374 375 aloop: 376 *cp++ = c; 377 c = GETC(); 378 if(ISALPHA(c) || isdigit(c) || c == '_' || c == '$') 379 goto aloop; 380 *cp = 0; 381 peekc = c; 382 s = lookup(); 383 if(s->macro) { 384 newio(); 385 cp = ionext->b; 386 macexpand(s, cp); 387 pushio(); 388 ionext->link = iostack; 389 iostack = ionext; 390 fi.p = cp; 391 fi.c = strlen(cp); 392 if(peekc != IGN) { 393 cp[fi.c++] = peekc; 394 cp[fi.c] = 0; 395 peekc = IGN; 396 } 397 goto l0; 398 } 399 if(s->type == 0) 400 s->type = LNAME; 401 if(s->type == LNAME || 402 s->type == LVAR || 403 s->type == LLAB) { 404 yylval.sym = s; 405 return s->type; 406 } 407 yylval.lval = s->value; 408 return s->type; 409 410 tnum: 411 cp = symb; 412 if(c != '0') 413 goto dc; 414 *cp++ = c; 415 c = GETC(); 416 c1 = 3; 417 if(c == 'x' || c == 'X') { 418 c1 = 4; 419 c = GETC(); 420 } else 421 if(c < '0' || c > '7') 422 goto dc; 423 yylval.lval = 0; 424 for(;;) { 425 if(c >= '0' && c <= '9') { 426 if(c > '7' && c1 == 3) 427 break; 428 yylval.lval = (uvlong)yylval.lval << c1; 429 yylval.lval += c - '0'; 430 c = GETC(); 431 continue; 432 } 433 if(c1 == 3) 434 break; 435 if(c >= 'A' && c <= 'F') 436 c += 'a' - 'A'; 437 if(c >= 'a' && c <= 'f') { 438 yylval.lval = (uvlong)yylval.lval << c1; 439 yylval.lval += c - 'a' + 10; 440 c = GETC(); 441 continue; 442 } 443 break; 444 } 445 goto ncu; 446 447 dc: 448 for(;;) { 449 if(!isdigit(c)) 450 break; 451 *cp++ = c; 452 c = GETC(); 453 } 454 if(c == '.') 455 goto casedot; 456 if(c == 'e' || c == 'E') 457 goto casee; 458 *cp = 0; 459 if(sizeof(yylval.lval) == sizeof(vlong)) 460 yylval.lval = strtoll(symb, nil, 10); 461 else 462 yylval.lval = strtol(symb, nil, 10); 463 464 ncu: 465 while(c == 'U' || c == 'u' || c == 'l' || c == 'L') 466 c = GETC(); 467 peekc = c; 468 return LCONST; 469 470 casedot: 471 for(;;) { 472 *cp++ = c; 473 c = GETC(); 474 if(!isdigit(c)) 475 break; 476 } 477 if(c == 'e' || c == 'E') 478 goto casee; 479 goto caseout; 480 481 casee: 482 *cp++ = 'e'; 483 c = GETC(); 484 if(c == '+' || c == '-') { 485 *cp++ = c; 486 c = GETC(); 487 } 488 while(isdigit(c)) { 489 *cp++ = c; 490 c = GETC(); 491 } 492 493 caseout: 494 *cp = 0; 495 peekc = c; 496 if(FPCHIP) { 497 yylval.dval = atof(symb); 498 return LFCONST; 499 } 500 yyerror("assembler cannot interpret fp constants"); 501 yylval.lval = 1L; 502 return LCONST; 503 504 case '"': 505 memcpy(yylval.sval, nullgen.u.sval, sizeof(yylval.sval)); 506 cp = yylval.sval; 507 c1 = 0; 508 for(;;) { 509 c = escchar('"'); 510 if(c == EOF) 511 break; 512 if(c1 < sizeof(yylval.sval)) 513 *cp++ = c; 514 c1++; 515 } 516 if(c1 > sizeof(yylval.sval)) 517 yyerror("string constant too long"); 518 return LSCONST; 519 520 case '\'': 521 c = escchar('\''); 522 if(c == EOF) 523 c = '\''; 524 if(escchar('\'') != EOF) 525 yyerror("missing '"); 526 yylval.lval = c; 527 return LCONST; 528 529 case '/': 530 c1 = GETC(); 531 if(c1 == '/') { 532 for(;;) { 533 c = GETC(); 534 if(c == '\n') 535 goto l1; 536 if(c == EOF) { 537 yyerror("eof in comment"); 538 errorexit(); 539 } 540 } 541 } 542 if(c1 == '*') { 543 for(;;) { 544 c = GETC(); 545 while(c == '*') { 546 c = GETC(); 547 if(c == '/') 548 goto l0; 549 } 550 if(c == EOF) { 551 yyerror("eof in comment"); 552 errorexit(); 553 } 554 if(c == '\n') 555 lineno++; 556 } 557 } 558 break; 559 560 default: 561 return c; 562 } 563 peekc = c1; 564 return c; 565 } 566 567 int 568 getc(void) 569 { 570 int c; 571 572 c = peekc; 573 if(c != IGN) { 574 peekc = IGN; 575 return c; 576 } 577 c = GETC(); 578 if(c == '\n') 579 lineno++; 580 if(c == EOF) { 581 yyerror("End of file"); 582 errorexit(); 583 } 584 return c; 585 } 586 587 int 588 getnsc(void) 589 { 590 int c; 591 592 for(;;) { 593 c = getc(); 594 if(!isspace(c) || c == '\n') 595 return c; 596 } 597 } 598 599 void 600 unget(int c) 601 { 602 603 peekc = c; 604 if(c == '\n') 605 lineno--; 606 } 607 608 int 609 escchar(int e) 610 { 611 int c, l; 612 613 loop: 614 c = getc(); 615 if(c == '\n') { 616 yyerror("newline in string"); 617 return EOF; 618 } 619 if(c != '\\') { 620 if(c == e) 621 return EOF; 622 return c; 623 } 624 c = getc(); 625 if(c >= '0' && c <= '7') { 626 l = c - '0'; 627 c = getc(); 628 if(c >= '0' && c <= '7') { 629 l = l*8 + c-'0'; 630 c = getc(); 631 if(c >= '0' && c <= '7') { 632 l = l*8 + c-'0'; 633 return l; 634 } 635 } 636 peekc = c; 637 return l; 638 } 639 switch(c) 640 { 641 case '\n': goto loop; 642 case 'n': return '\n'; 643 case 't': return '\t'; 644 case 'b': return '\b'; 645 case 'r': return '\r'; 646 case 'f': return '\f'; 647 case 'a': return 0x07; 648 case 'v': return 0x0b; 649 case 'z': return 0x00; 650 } 651 return c; 652 } 653 654 void 655 pinit(char *f) 656 { 657 int i; 658 Sym *s; 659 660 lineno = 1; 661 newio(); 662 newfile(f, -1); 663 pc = 0; 664 peekc = IGN; 665 sym = 1; 666 for(i=0; i<NHASH; i++) 667 for(s = hash[i]; s != S; s = s->link) 668 s->macro = 0; 669 } 670 671 int 672 filbuf(void) 673 { 674 Io *i; 675 676 loop: 677 i = iostack; 678 if(i == I) 679 return EOF; 680 if(i->f < 0) 681 goto pop; 682 fi.c = read(i->f, i->b, BUFSIZ) - 1; 683 if(fi.c < 0) { 684 close(i->f); 685 linklinehist(ctxt, lineno, 0, 0); 686 goto pop; 687 } 688 fi.p = i->b + 1; 689 return i->b[0] & 0xff; 690 691 pop: 692 iostack = i->link; 693 i->link = iofree; 694 iofree = i; 695 i = iostack; 696 if(i == I) 697 return EOF; 698 fi.p = i->p; 699 fi.c = i->c; 700 if(--fi.c < 0) 701 goto loop; 702 return *fi.p++ & 0xff; 703 } 704 705 void 706 yyerror(char *a, ...) 707 { 708 char buf[200]; 709 va_list arg; 710 711 /* 712 * hack to intercept message from yaccpar 713 */ 714 if(strcmp(a, "syntax error") == 0) { 715 yyerror("syntax error, last name: %s", symb); 716 return; 717 } 718 prfile(lineno); 719 va_start(arg, a); 720 vseprint(buf, buf+sizeof(buf), a, arg); 721 va_end(arg); 722 print("%s\n", buf); 723 nerrors++; 724 if(nerrors > 10) { 725 print("too many errors\n"); 726 errorexit(); 727 } 728 } 729 730 void 731 prfile(int32 l) 732 { 733 linkprfile(ctxt, l); 734 }