github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/asm/lexbody.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/asm/lexbody.go 2 3 // Inferno utils/cc/lexbody 4 // http://code.Google.Com/p/inferno-os/source/browse/utils/cc/lexbody 5 // 6 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 7 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.Net) 8 // Portions Copyright © 1997-1999 Vita Nuova Limited 9 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.Vitanuova.Com) 10 // Portions Copyright © 2004,2006 Bruce Ellis 11 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.Net) 12 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 13 // Portions Copyright © 2009 The Go Authors. All rights reserved. 14 // 15 // Permission is hereby granted, free of charge, to any person obtaining a copy 16 // of this software and associated documentation files (the "Software"), to deal 17 // in the Software without restriction, including without limitation the rights 18 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 // copies of the Software, and to permit persons to whom the Software is 20 // furnished to do so, subject to the following conditions: 21 // 22 // The above copyright notice and this permission notice shall be included in 23 // all copies or substantial portions of the Software. 24 // 25 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 31 // THE SOFTWARE. 32 33 package asm 34 35 import ( 36 "bytes" 37 "fmt" 38 "os" 39 "strconv" 40 "strings" 41 "unicode/utf8" 42 43 "rsc.io/tmp/bootstrap/internal/obj" 44 ) 45 46 /* 47 * common code for all the assemblers 48 */ 49 func pragpack() { 50 for getnsc() != '\n' { 51 } 52 } 53 54 func pragvararg() { 55 for getnsc() != '\n' { 56 } 57 } 58 59 func pragcgo(name string) { 60 for getnsc() != '\n' { 61 } 62 } 63 64 func pragfpround() { 65 for getnsc() != '\n' { 66 } 67 } 68 69 func pragtextflag() { 70 for getnsc() != '\n' { 71 } 72 } 73 74 func pragdataflag() { 75 for getnsc() != '\n' { 76 } 77 } 78 79 func pragprofile() { 80 for getnsc() != '\n' { 81 } 82 } 83 84 func pragincomplete() { 85 for getnsc() != '\n' { 86 } 87 } 88 89 func setinclude(p string) { 90 if p == "" { 91 return 92 } 93 for i := 1; i < len(include); i++ { 94 if p == include[i] { 95 return 96 } 97 } 98 99 include = append(include, p) 100 } 101 102 func errorexit() { 103 obj.Bflush(&bstdout) 104 if outfile != "" { 105 os.Remove(outfile) 106 } 107 os.Exit(2) 108 } 109 110 func pushio() { 111 i := iostack 112 if i == nil { 113 Yyerror("botch in pushio") 114 errorexit() 115 } 116 117 i.P = fi.P 118 } 119 120 func newio() { 121 var pushdepth int = 0 122 123 i := iofree 124 if i == nil { 125 pushdepth++ 126 if pushdepth > 1000 { 127 Yyerror("macro/io expansion too deep") 128 errorexit() 129 } 130 i = new(Io) 131 } else { 132 iofree = i.Link 133 } 134 i.F = nil 135 i.P = nil 136 ionext = i 137 } 138 139 func newfile(s string, f *os.File) { 140 i := ionext 141 i.Link = iostack 142 iostack = i 143 i.F = f 144 if f == nil { 145 var err error 146 i.F, err = os.Open(s) 147 if err != nil { 148 Yyerror("%ca: %v", Thechar, err) 149 errorexit() 150 } 151 } 152 153 fi.P = nil 154 obj.Linklinehist(Ctxt, int(Lineno), s, 0) 155 } 156 157 var thetext *obj.LSym 158 159 func Settext(s *obj.LSym) { 160 thetext = s 161 } 162 163 func LabelLookup(s *Sym) *Sym { 164 if thetext == nil { 165 s.Labelname = s.Name 166 return s 167 } 168 169 p := string(fmt.Sprintf("%s.%s", thetext.Name, s.Name)) 170 lab := Lookup(p) 171 172 lab.Labelname = s.Name 173 return lab 174 } 175 176 func Lookup(symb string) *Sym { 177 // turn leading · into ""· 178 if strings.HasPrefix(symb, "·") { 179 symb = `""` + symb 180 } 181 182 // turn · (U+00B7) into . 183 // turn ∕ (U+2215) into / 184 symb = strings.Replace(symb, "·", ".", -1) 185 symb = strings.Replace(symb, "∕", "/", -1) 186 187 s := hash[symb] 188 if s != nil { 189 return s 190 } 191 192 s = new(Sym) 193 s.Name = symb 194 syminit(s) 195 hash[symb] = s 196 return s 197 } 198 199 func isalnum(c int) bool { 200 return isalpha(c) || isdigit(c) 201 } 202 203 func isalpha(c int) bool { 204 return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' 205 } 206 207 func isspace(c int) bool { 208 return c == ' ' || c == '\t' || c == '\r' || c == '\n' 209 } 210 211 func ISALPHA(c int) bool { 212 if isalpha(c) { 213 return true 214 } 215 if c >= utf8.RuneSelf { 216 return true 217 } 218 return false 219 } 220 221 var yybuf bytes.Buffer 222 223 func (yyImpl) Error(s string) { 224 Yyerror("%s", s) 225 } 226 227 type Yylval struct { 228 Sym *Sym 229 Lval int64 230 Sval string 231 Dval float64 232 } 233 234 func Yylex(yylval *Yylval) int { 235 var c1 int 236 var s *Sym 237 238 c := peekc 239 if c != IGN { 240 peekc = IGN 241 goto l1 242 } 243 244 l0: 245 c = GETC() 246 247 l1: 248 if c == EOF { 249 peekc = EOF 250 return -1 251 } 252 253 if isspace(c) { 254 if c == '\n' { 255 Lineno++ 256 return ';' 257 } 258 259 goto l0 260 } 261 262 if ISALPHA(c) { 263 yybuf.Reset() 264 goto aloop 265 } 266 if isdigit(c) { 267 yybuf.Reset() 268 if c != '0' { 269 goto dc 270 } 271 yybuf.WriteByte(byte(c)) 272 c = GETC() 273 c1 = 3 274 if c == 'x' || c == 'X' { 275 c1 = 4 276 c = GETC() 277 } else if c < '0' || c > '7' { 278 goto dc 279 } 280 yylval.Lval = 0 281 for { 282 if c >= '0' && c <= '9' { 283 if c > '7' && c1 == 3 { 284 break 285 } 286 yylval.Lval = int64(uint64(yylval.Lval) << uint(c1)) 287 yylval.Lval += int64(c) - '0' 288 c = GETC() 289 continue 290 } 291 292 if c1 == 3 { 293 break 294 } 295 if c >= 'A' && c <= 'F' { 296 c += 'a' - 'A' 297 } 298 if c >= 'a' && c <= 'f' { 299 yylval.Lval = int64(uint64(yylval.Lval) << uint(c1)) 300 yylval.Lval += int64(c) - 'a' + 10 301 c = GETC() 302 continue 303 } 304 305 break 306 } 307 308 goto ncu 309 } 310 switch c { 311 case '\n': 312 Lineno++ 313 return ';' 314 315 case '#': 316 domacro() 317 goto l0 318 319 case '.': 320 c = GETC() 321 if ISALPHA(c) { 322 yybuf.Reset() 323 yybuf.WriteByte('.') 324 goto aloop 325 } 326 327 if isdigit(c) { 328 yybuf.Reset() 329 yybuf.WriteByte('.') 330 goto casedot 331 } 332 333 peekc = c 334 return '.' 335 336 case '_', 337 '@': 338 yybuf.Reset() 339 goto aloop 340 341 case '"': 342 var buf bytes.Buffer 343 c1 = 0 344 for { 345 c = escchar('"') 346 if c == EOF { 347 break 348 } 349 buf.WriteByte(byte(c)) 350 } 351 yylval.Sval = buf.String() 352 return LSCONST 353 354 case '\'': 355 c = escchar('\'') 356 if c == EOF { 357 c = '\'' 358 } 359 if escchar('\'') != EOF { 360 Yyerror("missing '") 361 } 362 yylval.Lval = int64(c) 363 return LCONST 364 365 case '/': 366 c1 = GETC() 367 if c1 == '/' { 368 for { 369 c = GETC() 370 if c == '\n' { 371 goto l1 372 } 373 if c == EOF { 374 Yyerror("eof in comment") 375 errorexit() 376 } 377 } 378 } 379 380 if c1 == '*' { 381 for { 382 c = GETC() 383 for c == '*' { 384 c = GETC() 385 if c == '/' { 386 goto l0 387 } 388 } 389 390 if c == EOF { 391 Yyerror("eof in comment") 392 errorexit() 393 } 394 395 if c == '\n' { 396 Lineno++ 397 } 398 } 399 } 400 401 default: 402 return int(c) 403 } 404 405 peekc = c1 406 return int(c) 407 408 casedot: 409 for { 410 yybuf.WriteByte(byte(c)) 411 c = GETC() 412 if !(isdigit(c)) { 413 break 414 } 415 } 416 417 if c == 'e' || c == 'E' { 418 goto casee 419 } 420 goto caseout 421 422 casee: 423 yybuf.WriteByte('e') 424 c = GETC() 425 if c == '+' || c == '-' { 426 yybuf.WriteByte(byte(c)) 427 c = GETC() 428 } 429 430 for isdigit(c) { 431 yybuf.WriteByte(byte(c)) 432 c = GETC() 433 } 434 435 caseout: 436 peekc = c 437 if FPCHIP != 0 /*TypeKind(100016)*/ { 438 last = yybuf.String() 439 yylval.Dval = atof(last) 440 return LFCONST 441 } 442 443 Yyerror("assembler cannot interpret fp constants") 444 yylval.Lval = 1 445 return LCONST 446 447 aloop: 448 yybuf.WriteByte(byte(c)) 449 c = GETC() 450 if ISALPHA(c) || isdigit(c) || c == '_' || c == '$' { 451 goto aloop 452 } 453 peekc = c 454 last = yybuf.String() 455 s = Lookup(last) 456 if s.Macro != nil { 457 newio() 458 ionext.P = macexpand(s) 459 pushio() 460 ionext.Link = iostack 461 iostack = ionext 462 fi.P = ionext.P 463 if peekc != IGN { 464 fi.P = append(fi.P, byte(peekc)) 465 peekc = IGN 466 } 467 468 goto l0 469 } 470 471 if s.Type == 0 { 472 s.Type = LNAME 473 } 474 if s.Type == LNAME || s.Type == LVAR || s.Type == LLAB { 475 yylval.Sym = s 476 yylval.Sval = last 477 return int(s.Type) 478 } 479 480 yylval.Lval = s.Value 481 yylval.Sval = last 482 return int(s.Type) 483 484 dc: 485 for { 486 if !(isdigit(c)) { 487 break 488 } 489 yybuf.WriteByte(byte(c)) 490 c = GETC() 491 } 492 493 if c == '.' { 494 goto casedot 495 } 496 if c == 'e' || c == 'E' { 497 goto casee 498 } 499 last = yybuf.String() 500 yylval.Lval = strtoll(last, nil, 10) 501 502 ncu: 503 for c == 'U' || c == 'u' || c == 'l' || c == 'L' { 504 c = GETC() 505 } 506 peekc = c 507 return LCONST 508 } 509 510 func getc() int { 511 c := peekc 512 if c != IGN { 513 peekc = IGN 514 if c == '\n' { 515 Lineno++ 516 } 517 return c 518 } 519 520 c = GETC() 521 if c == '\n' { 522 Lineno++ 523 } 524 if c == EOF { 525 Yyerror("End of file") 526 errorexit() 527 } 528 529 return c 530 } 531 532 func getnsc() int { 533 var c int 534 535 for { 536 c = getc() 537 if !isspace(c) || c == '\n' { 538 return c 539 } 540 } 541 } 542 543 func unget(c int) { 544 peekc = c 545 if c == '\n' { 546 Lineno-- 547 } 548 } 549 550 func escchar(e int) int { 551 var l int 552 553 loop: 554 c := getc() 555 if c == '\n' { 556 Yyerror("newline in string") 557 return EOF 558 } 559 560 if c != '\\' { 561 if c == e { 562 return EOF 563 } 564 return c 565 } 566 567 c = getc() 568 if c >= '0' && c <= '7' { 569 l = c - '0' 570 c = getc() 571 if c >= '0' && c <= '7' { 572 l = l*8 + c - '0' 573 c = getc() 574 if c >= '0' && c <= '7' { 575 l = l*8 + c - '0' 576 return l 577 } 578 } 579 580 peekc = c 581 unget(c) 582 return l 583 } 584 585 switch c { 586 case '\n': 587 goto loop 588 case 'n': 589 return '\n' 590 case 't': 591 return '\t' 592 case 'b': 593 return '\b' 594 case 'r': 595 return '\r' 596 case 'f': 597 return '\f' 598 case 'a': 599 return 0x07 600 case 'v': 601 return 0x0b 602 case 'z': 603 return 0x00 604 } 605 606 return c 607 } 608 609 func pinit(f string) { 610 Lineno = 1 611 newio() 612 newfile(f, nil) 613 PC = 0 614 peekc = IGN 615 sym = 1 616 for _, s := range hash { 617 s.Macro = nil 618 } 619 } 620 621 func filbuf() int { 622 var n int 623 624 loop: 625 i := iostack 626 if i == nil { 627 return EOF 628 } 629 if i.F == nil { 630 goto pop 631 } 632 n, _ = i.F.Read(i.B[:]) 633 if n == 0 { 634 i.F.Close() 635 obj.Linklinehist(Ctxt, int(Lineno), "<pop>", 0) 636 goto pop 637 } 638 fi.P = i.B[1:n] 639 return int(i.B[0]) & 0xff 640 641 pop: 642 iostack = i.Link 643 i.Link = iofree 644 iofree = i 645 i = iostack 646 if i == nil { 647 return EOF 648 } 649 fi.P = i.P 650 if len(fi.P) == 0 { 651 goto loop 652 } 653 tmp8 := fi.P 654 fi.P = fi.P[1:] 655 return int(tmp8[0]) & 0xff 656 } 657 658 var last string 659 660 func Yyerror(a string, args ...interface{}) { 661 /* 662 * hack to intercept message from yaccpar 663 */ 664 if a == "syntax error" || len(args) == 1 && a == "%s" && args[0] == "syntax error" { 665 Yyerror("syntax error, last name: %s", last) 666 return 667 } 668 669 prfile(Lineno) 670 fmt.Printf("%s\n", fmt.Sprintf(a, args...)) 671 nerrors++ 672 if nerrors > 10 { 673 fmt.Printf("too many errors\n") 674 errorexit() 675 } 676 } 677 678 func prfile(l int32) { 679 obj.Linkprfile(Ctxt, int(l)) 680 } 681 682 func GETC() int { 683 if len(fi.P) == 0 { 684 return filbuf() 685 } 686 c := int(fi.P[0]) 687 fi.P = fi.P[1:] 688 return c 689 } 690 691 func isdigit(c int) bool { 692 return '0' <= c && c <= '9' 693 } 694 695 func strtoll(s string, p *byte, base int) int64 { 696 if p != nil { 697 panic("strtoll") 698 } 699 n, err := strconv.ParseInt(s, base, 64) 700 if err != nil { 701 return 0 702 } 703 return n 704 } 705 706 func atof(s string) float64 { 707 f, err := strconv.ParseFloat(s, 64) 708 if err != nil { 709 return 0 710 } 711 return f 712 }