github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/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 Sym* 224 lookup(void) 225 { 226 Sym *s; 227 uint32 h; 228 char *p; 229 int c, l; 230 char *r, *w; 231 232 if((uchar)symb[0] == 0xc2 && (uchar)symb[1] == 0xb7) { 233 // turn leading · into ""· 234 h = strlen(symb); 235 ensuresymb(h+2); 236 memmove(symb+2, symb, h+1); 237 symb[0] = '"'; 238 symb[1] = '"'; 239 } 240 241 for(r=w=symb; *r; r++) { 242 // turn · (U+00B7) into . 243 // turn ∕ (U+2215) into / 244 if((uchar)*r == 0xc2 && (uchar)*(r+1) == 0xb7) { 245 *w++ = '.'; 246 r++; 247 }else if((uchar)*r == 0xe2 && (uchar)*(r+1) == 0x88 && (uchar)*(r+2) == 0x95) { 248 *w++ = '/'; 249 r++; 250 r++; 251 }else 252 *w++ = *r; 253 } 254 *w = '\0'; 255 256 h = 0; 257 for(p=symb; c = *p; p++) 258 h = h+h+h + c; 259 l = (p - symb) + 1; 260 h &= 0xffffff; 261 h %= NHASH; 262 c = symb[0]; 263 for(s = hash[h]; s != S; s = s->link) { 264 if(s->name[0] != c) 265 continue; 266 if(strcmp(s->name, symb) == 0) 267 return s; 268 } 269 s = alloc(sizeof(*s)); 270 s->name = alloc(l); 271 memmove(s->name, symb, l); 272 273 s->link = hash[h]; 274 hash[h] = s; 275 syminit(s); 276 return s; 277 } 278 279 int 280 ISALPHA(int c) 281 { 282 if(isalpha(c)) 283 return 1; 284 if(c >= Runeself) 285 return 1; 286 return 0; 287 } 288 289 int32 290 yylex(void) 291 { 292 int c, c1; 293 char *cp; 294 Sym *s; 295 296 c = peekc; 297 if(c != IGN) { 298 peekc = IGN; 299 goto l1; 300 } 301 l0: 302 c = GETC(); 303 304 l1: 305 if(c == EOF) { 306 peekc = EOF; 307 return -1; 308 } 309 if(isspace(c)) { 310 if(c == '\n') { 311 lineno++; 312 return ';'; 313 } 314 goto l0; 315 } 316 if(ISALPHA(c)) 317 goto talph; 318 if(isdigit(c)) 319 goto tnum; 320 switch(c) 321 { 322 case '\n': 323 lineno++; 324 return ';'; 325 326 case '#': 327 domacro(); 328 goto l0; 329 330 case '.': 331 c = GETC(); 332 if(ISALPHA(c)) { 333 cp = symb; 334 *cp++ = '.'; 335 goto aloop; 336 } 337 if(isdigit(c)) { 338 cp = symb; 339 *cp++ = '.'; 340 goto casedot; 341 } 342 peekc = c; 343 return '.'; 344 345 talph: 346 case '_': 347 case '@': 348 cp = symb; 349 350 aloop: 351 *cp++ = c; 352 c = GETC(); 353 if(ISALPHA(c) || isdigit(c) || c == '_' || c == '$') 354 goto aloop; 355 *cp = 0; 356 peekc = c; 357 s = lookup(); 358 if(s->macro) { 359 newio(); 360 cp = ionext->b; 361 macexpand(s, cp); 362 pushio(); 363 ionext->link = iostack; 364 iostack = ionext; 365 fi.p = cp; 366 fi.c = strlen(cp); 367 if(peekc != IGN) { 368 cp[fi.c++] = peekc; 369 cp[fi.c] = 0; 370 peekc = IGN; 371 } 372 goto l0; 373 } 374 if(s->type == 0) 375 s->type = LNAME; 376 if(s->type == LNAME || 377 s->type == LVAR || 378 s->type == LLAB) { 379 yylval.sym = s; 380 return s->type; 381 } 382 yylval.lval = s->value; 383 return s->type; 384 385 tnum: 386 cp = symb; 387 if(c != '0') 388 goto dc; 389 *cp++ = c; 390 c = GETC(); 391 c1 = 3; 392 if(c == 'x' || c == 'X') { 393 c1 = 4; 394 c = GETC(); 395 } else 396 if(c < '0' || c > '7') 397 goto dc; 398 yylval.lval = 0; 399 for(;;) { 400 if(c >= '0' && c <= '9') { 401 if(c > '7' && c1 == 3) 402 break; 403 yylval.lval = (uvlong)yylval.lval << c1; 404 yylval.lval += c - '0'; 405 c = GETC(); 406 continue; 407 } 408 if(c1 == 3) 409 break; 410 if(c >= 'A' && c <= 'F') 411 c += 'a' - 'A'; 412 if(c >= 'a' && c <= 'f') { 413 yylval.lval = (uvlong)yylval.lval << c1; 414 yylval.lval += c - 'a' + 10; 415 c = GETC(); 416 continue; 417 } 418 break; 419 } 420 goto ncu; 421 422 dc: 423 for(;;) { 424 if(!isdigit(c)) 425 break; 426 *cp++ = c; 427 c = GETC(); 428 } 429 if(c == '.') 430 goto casedot; 431 if(c == 'e' || c == 'E') 432 goto casee; 433 *cp = 0; 434 if(sizeof(yylval.lval) == sizeof(vlong)) 435 yylval.lval = strtoll(symb, nil, 10); 436 else 437 yylval.lval = strtol(symb, nil, 10); 438 439 ncu: 440 while(c == 'U' || c == 'u' || c == 'l' || c == 'L') 441 c = GETC(); 442 peekc = c; 443 return LCONST; 444 445 casedot: 446 for(;;) { 447 *cp++ = c; 448 c = GETC(); 449 if(!isdigit(c)) 450 break; 451 } 452 if(c == 'e' || c == 'E') 453 goto casee; 454 goto caseout; 455 456 casee: 457 *cp++ = 'e'; 458 c = GETC(); 459 if(c == '+' || c == '-') { 460 *cp++ = c; 461 c = GETC(); 462 } 463 while(isdigit(c)) { 464 *cp++ = c; 465 c = GETC(); 466 } 467 468 caseout: 469 *cp = 0; 470 peekc = c; 471 if(FPCHIP) { 472 yylval.dval = atof(symb); 473 return LFCONST; 474 } 475 yyerror("assembler cannot interpret fp constants"); 476 yylval.lval = 1L; 477 return LCONST; 478 479 case '"': 480 memcpy(yylval.sval, nullgen.u.sval, sizeof(yylval.sval)); 481 cp = yylval.sval; 482 c1 = 0; 483 for(;;) { 484 c = escchar('"'); 485 if(c == EOF) 486 break; 487 if(c1 < sizeof(yylval.sval)) 488 *cp++ = c; 489 c1++; 490 } 491 if(c1 > sizeof(yylval.sval)) 492 yyerror("string constant too long"); 493 return LSCONST; 494 495 case '\'': 496 c = escchar('\''); 497 if(c == EOF) 498 c = '\''; 499 if(escchar('\'') != EOF) 500 yyerror("missing '"); 501 yylval.lval = c; 502 return LCONST; 503 504 case '/': 505 c1 = GETC(); 506 if(c1 == '/') { 507 for(;;) { 508 c = GETC(); 509 if(c == '\n') 510 goto l1; 511 if(c == EOF) { 512 yyerror("eof in comment"); 513 errorexit(); 514 } 515 } 516 } 517 if(c1 == '*') { 518 for(;;) { 519 c = GETC(); 520 while(c == '*') { 521 c = GETC(); 522 if(c == '/') 523 goto l0; 524 } 525 if(c == EOF) { 526 yyerror("eof in comment"); 527 errorexit(); 528 } 529 if(c == '\n') 530 lineno++; 531 } 532 } 533 break; 534 535 default: 536 return c; 537 } 538 peekc = c1; 539 return c; 540 } 541 542 int 543 getc(void) 544 { 545 int c; 546 547 c = peekc; 548 if(c != IGN) { 549 peekc = IGN; 550 return c; 551 } 552 c = GETC(); 553 if(c == '\n') 554 lineno++; 555 if(c == EOF) { 556 yyerror("End of file"); 557 errorexit(); 558 } 559 return c; 560 } 561 562 int 563 getnsc(void) 564 { 565 int c; 566 567 for(;;) { 568 c = getc(); 569 if(!isspace(c) || c == '\n') 570 return c; 571 } 572 } 573 574 void 575 unget(int c) 576 { 577 578 peekc = c; 579 if(c == '\n') 580 lineno--; 581 } 582 583 int 584 escchar(int e) 585 { 586 int c, l; 587 588 loop: 589 c = getc(); 590 if(c == '\n') { 591 yyerror("newline in string"); 592 return EOF; 593 } 594 if(c != '\\') { 595 if(c == e) 596 return EOF; 597 return c; 598 } 599 c = getc(); 600 if(c >= '0' && c <= '7') { 601 l = c - '0'; 602 c = getc(); 603 if(c >= '0' && c <= '7') { 604 l = l*8 + c-'0'; 605 c = getc(); 606 if(c >= '0' && c <= '7') { 607 l = l*8 + c-'0'; 608 return l; 609 } 610 } 611 peekc = c; 612 return l; 613 } 614 switch(c) 615 { 616 case '\n': goto loop; 617 case 'n': return '\n'; 618 case 't': return '\t'; 619 case 'b': return '\b'; 620 case 'r': return '\r'; 621 case 'f': return '\f'; 622 case 'a': return 0x07; 623 case 'v': return 0x0b; 624 case 'z': return 0x00; 625 } 626 return c; 627 } 628 629 void 630 pinit(char *f) 631 { 632 int i; 633 Sym *s; 634 635 lineno = 1; 636 newio(); 637 newfile(f, -1); 638 pc = 0; 639 peekc = IGN; 640 sym = 1; 641 for(i=0; i<NHASH; i++) 642 for(s = hash[i]; s != S; s = s->link) 643 s->macro = 0; 644 } 645 646 int 647 filbuf(void) 648 { 649 Io *i; 650 651 loop: 652 i = iostack; 653 if(i == I) 654 return EOF; 655 if(i->f < 0) 656 goto pop; 657 fi.c = read(i->f, i->b, BUFSIZ) - 1; 658 if(fi.c < 0) { 659 close(i->f); 660 linklinehist(ctxt, lineno, 0, 0); 661 goto pop; 662 } 663 fi.p = i->b + 1; 664 return i->b[0] & 0xff; 665 666 pop: 667 iostack = i->link; 668 i->link = iofree; 669 iofree = i; 670 i = iostack; 671 if(i == I) 672 return EOF; 673 fi.p = i->p; 674 fi.c = i->c; 675 if(--fi.c < 0) 676 goto loop; 677 return *fi.p++ & 0xff; 678 } 679 680 void 681 yyerror(char *a, ...) 682 { 683 char buf[200]; 684 va_list arg; 685 686 /* 687 * hack to intercept message from yaccpar 688 */ 689 if(strcmp(a, "syntax error") == 0) { 690 yyerror("syntax error, last name: %s", symb); 691 return; 692 } 693 prfile(lineno); 694 va_start(arg, a); 695 vseprint(buf, buf+sizeof(buf), a, arg); 696 va_end(arg); 697 print("%s\n", buf); 698 nerrors++; 699 if(nerrors > 10) { 700 print("too many errors\n"); 701 errorexit(); 702 } 703 } 704 705 void 706 prfile(int32 l) 707 { 708 linkprfile(ctxt, l); 709 }