github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/asm/macbody.go (about) 1 // Do not edit. Bootstrap copy of /Users/rsc/g/go/src/cmd/internal/asm/macbody.go 2 3 // Inferno utils/cc/macbody 4 // http://code.Google.Com/p/inferno-os/source/browse/utils/cc/macbody 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 "rsc.io/tmp/bootstrap/internal/obj" 38 "fmt" 39 "os" 40 "strings" 41 ) 42 43 const ( 44 VARMAC = 0x80 45 ) 46 47 func getnsn() int32 { 48 c := getnsc() 49 if c < '0' || c > '9' { 50 return -1 51 } 52 n := int32(0) 53 for c >= '0' && c <= '9' { 54 n = n*10 + int32(c) - '0' 55 c = getc() 56 } 57 58 unget(c) 59 return n 60 } 61 62 func getsym() *Sym { 63 c := getnsc() 64 if !isalpha(c) && c != '_' && c < 0x80 { 65 unget(c) 66 return nil 67 } 68 69 var buf bytes.Buffer 70 for { 71 buf.WriteByte(byte(c)) 72 c = getc() 73 if isalnum(c) || c == '_' || c >= 0x80 { 74 continue 75 } 76 unget(c) 77 break 78 } 79 last = buf.String() 80 return Lookup(last) 81 } 82 83 func getsymdots(dots *int) *Sym { 84 s := getsym() 85 if s != nil { 86 return s 87 } 88 89 c := getnsc() 90 if c != '.' { 91 unget(c) 92 return nil 93 } 94 95 if getc() != '.' || getc() != '.' { 96 Yyerror("bad dots in macro") 97 } 98 *dots = 1 99 return Lookup("__VA_ARGS__") 100 } 101 102 func getcom() int { 103 var c int 104 105 for { 106 c = getnsc() 107 if c != '/' { 108 break 109 } 110 c = getc() 111 if c == '/' { 112 for c != '\n' { 113 c = getc() 114 } 115 break 116 } 117 118 if c != '*' { 119 break 120 } 121 c = getc() 122 for { 123 if c == '*' { 124 c = getc() 125 if c != '/' { 126 continue 127 } 128 c = getc() 129 break 130 } 131 132 if c == '\n' { 133 Yyerror("comment across newline") 134 break 135 } 136 137 c = getc() 138 } 139 140 if c == '\n' { 141 break 142 } 143 } 144 145 return c 146 } 147 148 func dodefine(cp string) { 149 var s *Sym 150 151 if i := strings.Index(cp, "="); i >= 0 { 152 p := cp[i+1:] 153 cp = cp[:i] 154 s = Lookup(cp) 155 s.Macro = &Macro{Text: p} 156 } else { 157 s = Lookup(cp) 158 s.Macro = &Macro{Text: "1"} 159 } 160 161 if debug['m'] != 0 { 162 fmt.Printf("#define (-D) %s %s\n", s.Name, s.Macro.Text) 163 } 164 } 165 166 var mactab = []struct { 167 Macname string 168 Macf func() 169 }{ 170 {"ifdef", nil}, /* macif(0) */ 171 {"ifndef", nil}, /* macif(1) */ 172 {"else", nil}, /* macif(2) */ 173 {"line", maclin}, 174 {"define", macdef}, 175 {"include", macinc}, 176 {"undef", macund}, 177 {"pragma", macprag}, 178 {"endif", macend}, 179 } 180 181 func domacro() { 182 s := getsym() 183 if s == nil { 184 s = Lookup("endif") 185 } 186 for i := 0; i < len(mactab); i++ { 187 if s.Name == mactab[i].Macname { 188 if mactab[i].Macf != nil { 189 mactab[i].Macf() 190 } else { 191 macif(i) 192 } 193 return 194 } 195 } 196 197 Yyerror("unknown #: %s", s.Name) 198 macend() 199 } 200 201 func macund() { 202 s := getsym() 203 macend() 204 if s == nil { 205 Yyerror("syntax in #undef") 206 return 207 } 208 209 s.Macro = nil 210 } 211 212 const ( 213 NARG = 25 214 ) 215 216 func macdef() { 217 var args [NARG]string 218 var n int 219 var i int 220 var c int 221 var dots int 222 var ischr int 223 var base bytes.Buffer 224 225 s := getsym() 226 if s == nil { 227 goto bad 228 } 229 if s.Macro != nil { 230 Yyerror("macro redefined: %s", s.Name) 231 } 232 c = getc() 233 n = -1 234 dots = 0 235 if c == '(' { 236 n++ 237 c = getnsc() 238 if c != ')' { 239 unget(c) 240 var a *Sym 241 var c int 242 for { 243 a = getsymdots(&dots) 244 if a == nil { 245 goto bad 246 } 247 if n >= NARG { 248 Yyerror("too many arguments in #define: %s", s.Name) 249 goto bad 250 } 251 252 args[n] = a.Name 253 n++ 254 c = getnsc() 255 if c == ')' { 256 break 257 } 258 if c != ',' || dots != 0 { 259 goto bad 260 } 261 } 262 } 263 264 c = getc() 265 } 266 267 if isspace(c) { 268 if c != '\n' { 269 c = getnsc() 270 } 271 } 272 ischr = 0 273 for { 274 if isalpha(c) || c == '_' { 275 var buf bytes.Buffer 276 buf.WriteByte(byte(c)) 277 c = getc() 278 for isalnum(c) || c == '_' { 279 buf.WriteByte(byte(c)) 280 c = getc() 281 } 282 283 symb := buf.String() 284 for i = 0; i < n; i++ { 285 if symb == args[i] { 286 break 287 } 288 } 289 if i >= n { 290 base.WriteString(symb) 291 continue 292 } 293 294 base.WriteByte('#') 295 base.WriteByte(byte('a' + i)) 296 continue 297 } 298 299 if ischr != 0 { 300 if c == '\\' { 301 base.WriteByte(byte(c)) 302 c = getc() 303 } else if c == ischr { 304 ischr = 0 305 } 306 } else { 307 if c == '"' || c == '\'' { 308 base.WriteByte(byte(c)) 309 ischr = c 310 c = getc() 311 continue 312 } 313 314 if c == '/' { 315 c = getc() 316 if c == '/' { 317 c = getc() 318 for { 319 if c == '\n' { 320 break 321 } 322 c = getc() 323 } 324 325 continue 326 } 327 328 if c == '*' { 329 c = getc() 330 for { 331 if c == '*' { 332 c = getc() 333 if c != '/' { 334 continue 335 } 336 c = getc() 337 break 338 } 339 340 if c == '\n' { 341 Yyerror("comment and newline in define: %s", s.Name) 342 break 343 } 344 345 c = getc() 346 } 347 348 continue 349 } 350 351 base.WriteByte('/') 352 continue 353 } 354 } 355 356 if c == '\\' { 357 c = getc() 358 if c == '\n' { 359 c = getc() 360 continue 361 } else if c == '\r' { 362 c = getc() 363 if c == '\n' { 364 c = getc() 365 continue 366 } 367 } 368 369 base.WriteByte('\\') 370 continue 371 } 372 373 if c == '\n' { 374 break 375 } 376 if c == '#' { 377 if n > 0 { 378 base.WriteByte(byte(c)) 379 } 380 } 381 382 base.WriteByte(byte(c)) 383 c = GETC() 384 if c == '\n' { 385 Lineno++ 386 } 387 if c == -1 { 388 Yyerror("eof in a macro: %s", s.Name) 389 break 390 } 391 } 392 393 s.Macro = &Macro{ 394 Text: base.String(), 395 Narg: n + 1, 396 Dots: dots != 0, 397 } 398 if debug['m'] != 0 { 399 fmt.Printf("#define %s %s\n", s.Name, s.Macro.Text) 400 } 401 return 402 403 bad: 404 if s == nil { 405 Yyerror("syntax in #define") 406 } else { 407 Yyerror("syntax in #define: %s", s.Name) 408 } 409 macend() 410 } 411 412 func macexpand(s *Sym) []byte { 413 if s.Macro.Narg == 0 { 414 if debug['m'] != 0 { 415 fmt.Printf("#expand %s %s\n", s.Name, s.Macro.Text) 416 } 417 return []byte(s.Macro.Text) 418 } 419 420 nargs := s.Macro.Narg - 1 421 dots := s.Macro.Dots 422 423 c := getnsc() 424 var arg []string 425 var cp string 426 var out bytes.Buffer 427 if c != '(' { 428 goto bad 429 } 430 c = getc() 431 if c != ')' { 432 unget(c) 433 l := 0 434 var buf bytes.Buffer 435 var c int 436 for { 437 c = getc() 438 if c == '"' { 439 for { 440 buf.WriteByte(byte(c)) 441 c = getc() 442 if c == '\\' { 443 buf.WriteByte(byte(c)) 444 c = getc() 445 continue 446 } 447 448 if c == '\n' { 449 goto bad 450 } 451 if c == '"' { 452 break 453 } 454 } 455 } 456 457 if c == '\'' { 458 for { 459 buf.WriteByte(byte(c)) 460 c = getc() 461 if c == '\\' { 462 buf.WriteByte(byte(c)) 463 c = getc() 464 continue 465 } 466 467 if c == '\n' { 468 goto bad 469 } 470 if c == '\'' { 471 break 472 } 473 } 474 } 475 476 if c == '/' { 477 c = getc() 478 switch c { 479 case '*': 480 for { 481 c = getc() 482 if c == '*' { 483 c = getc() 484 if c == '/' { 485 break 486 } 487 } 488 } 489 490 buf.WriteByte(' ') 491 continue 492 493 case '/': 494 for { 495 c = getc() 496 if !(c != '\n') { 497 break 498 } 499 } 500 501 default: 502 unget(c) 503 c = '/' 504 } 505 } 506 507 if l == 0 { 508 if c == ',' { 509 if len(arg) == nargs-1 && dots { 510 buf.WriteByte(',') 511 continue 512 } 513 514 arg = append(arg, buf.String()) 515 buf.Reset() 516 continue 517 } 518 519 if c == ')' { 520 arg = append(arg, buf.String()) 521 break 522 } 523 } 524 525 if c == '\n' { 526 c = ' ' 527 } 528 buf.WriteByte(byte(c)) 529 if c == '(' { 530 l++ 531 } 532 if c == ')' { 533 l-- 534 } 535 } 536 } 537 538 if len(arg) != nargs { 539 Yyerror("argument mismatch expanding: %s", s.Name) 540 return nil 541 } 542 543 cp = s.Macro.Text 544 for i := 0; i < len(cp); i++ { 545 c = int(cp[i]) 546 if c == '\n' { 547 c = ' ' 548 } 549 if c != '#' { 550 out.WriteByte(byte(c)) 551 continue 552 } 553 554 i++ 555 if i >= len(cp) { 556 goto bad 557 } 558 c = int(cp[i]) 559 if c == '#' { 560 out.WriteByte(byte(c)) 561 continue 562 } 563 564 c -= 'a' 565 if c < 0 || c >= len(arg) { 566 continue 567 } 568 out.WriteString(arg[c]) 569 } 570 571 if debug['m'] != 0 { 572 fmt.Printf("#expand %s %s\n", s.Name, out.String()) 573 } 574 return out.Bytes() 575 576 bad: 577 Yyerror("syntax in macro expansion: %s", s.Name) 578 return nil 579 } 580 581 func macinc() { 582 var c int 583 var buf bytes.Buffer 584 var f *os.File 585 var hp string 586 var str string 587 var symb string 588 589 c0 := getnsc() 590 if c0 != '"' { 591 c = c0 592 if c0 != '<' { 593 goto bad 594 } 595 c0 = '>' 596 } 597 598 for { 599 c = getc() 600 if c == c0 { 601 break 602 } 603 if c == '\n' { 604 goto bad 605 } 606 buf.WriteByte(byte(c)) 607 } 608 str = buf.String() 609 610 c = getcom() 611 if c != '\n' { 612 goto bad 613 } 614 615 for i := 0; i < len(include); i++ { 616 if i == 0 && c0 == '>' { 617 continue 618 } 619 symb = include[i] 620 symb += "/" 621 if symb == "./" { 622 symb = "" 623 } 624 symb += str 625 var err error 626 f, err = os.Open(symb) 627 if err == nil { 628 break 629 } 630 } 631 632 if f == nil { 633 symb = str 634 } 635 hp = symb 636 newio() 637 pushio() 638 newfile(hp, f) 639 return 640 641 bad: 642 unget(c) 643 Yyerror("syntax in #include") 644 macend() 645 } 646 647 func maclin() { 648 var buf bytes.Buffer 649 var symb string 650 651 n := getnsn() 652 c := getc() 653 if n < 0 { 654 goto bad 655 } 656 for { 657 if c == ' ' || c == '\t' { 658 c = getc() 659 continue 660 } 661 662 if c == '"' { 663 break 664 } 665 if c == '\n' { 666 symb = "<noname>" 667 goto nn 668 } 669 670 goto bad 671 } 672 673 for { 674 c = getc() 675 if c == '"' { 676 break 677 } 678 buf.WriteByte(byte(c)) 679 } 680 symb = buf.String() 681 682 c = getcom() 683 if c != '\n' { 684 goto bad 685 } 686 687 nn: 688 obj.Linklinehist(Ctxt, int(Lineno), symb, int(n)) 689 return 690 691 bad: 692 unget(c) 693 Yyerror("syntax in #line") 694 macend() 695 } 696 697 func macif(f int) { 698 var c int 699 var l int 700 var bol int 701 var s *Sym 702 703 if f == 2 { 704 goto skip 705 } 706 s = getsym() 707 if s == nil { 708 goto bad 709 } 710 if getcom() != '\n' { 711 goto bad 712 } 713 if (s.Macro != nil) != (f != 0) { 714 return 715 } 716 717 skip: 718 bol = 1 719 l = 0 720 for { 721 c = getc() 722 if c != '#' { 723 if !isspace(c) { 724 bol = 0 725 } 726 if c == '\n' { 727 bol = 1 728 } 729 continue 730 } 731 732 if !(bol != 0) { 733 continue 734 } 735 s = getsym() 736 if s == nil { 737 continue 738 } 739 if s.Name == "endif" { 740 if l != 0 { 741 l-- 742 continue 743 } 744 745 macend() 746 return 747 } 748 749 if s.Name == "ifdef" || s.Name == "ifndef" { 750 l++ 751 continue 752 } 753 754 if l == 0 && f != 2 && s.Name == "else" { 755 macend() 756 return 757 } 758 } 759 760 bad: 761 Yyerror("syntax in #if(n)def") 762 macend() 763 } 764 765 func macprag() { 766 var c int 767 768 s := getsym() 769 770 if s != nil && s.Name == "lib" { 771 c0 := getnsc() 772 if c0 != '"' { 773 c = c0 774 if c0 != '<' { 775 goto bad 776 } 777 c0 = '>' 778 } 779 780 var buf bytes.Buffer 781 for { 782 c = getc() 783 if c == c0 { 784 break 785 } 786 if c == '\n' { 787 goto bad 788 } 789 buf.WriteByte(byte(c)) 790 } 791 symb := buf.String() 792 793 c = getcom() 794 if c != '\n' { 795 goto bad 796 } 797 798 /* 799 * put pragma-line in as a funny history 800 */ 801 obj.Linklinehist(Ctxt, int(Lineno), symb, -1) 802 return 803 } 804 if s != nil && s.Name == "pack" { 805 pragpack() 806 return 807 } 808 809 if s != nil && s.Name == "fpround" { 810 pragfpround() 811 return 812 } 813 814 if s != nil && s.Name == "textflag" { 815 pragtextflag() 816 return 817 } 818 819 if s != nil && s.Name == "dataflag" { 820 pragdataflag() 821 return 822 } 823 824 if s != nil && s.Name == "varargck" { 825 pragvararg() 826 return 827 } 828 829 if s != nil && s.Name == "incomplete" { 830 pragincomplete() 831 return 832 } 833 834 if s != nil && (strings.HasPrefix(s.Name, "cgo_") || strings.HasPrefix(s.Name, "dyn")) { 835 pragcgo(s.Name) 836 return 837 } 838 839 for getnsc() != '\n' { 840 } 841 return 842 843 bad: 844 unget(c) 845 Yyerror("syntax in #pragma lib") 846 macend() 847 } 848 849 func macend() { 850 var c int 851 852 for { 853 c = getnsc() 854 if c < 0 || c == '\n' { 855 return 856 } 857 } 858 }