1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:generate go tool yacc go.y 6 //go:generate go run mkbuiltin.go runtime unsafe 7 8 package gc 9 10 import ( 11 "bytes" 12 "cmd/internal/obj" 13 "flag" 14 "fmt" 15 "io" 16 "log" 17 "os" 18 "path" 19 "strconv" 20 "strings" 21 "unicode" 22 "unicode/utf8" 23 ) 24 25 var yyprev int 26 27 var yylast int 28 29 var imported_unsafe int 30 31 var ( 32 goos string 33 goarch string 34 goroot string 35 buildid string 36 ) 37 38 var ( 39 Debug_append int 40 Debug_panic int 41 Debug_slice int 42 Debug_wb int 43 ) 44 45 // Debug arguments. 46 // These can be specified with the -d flag, as in "-d nil" 47 // to set the debug_checknil variable. In general the list passed 48 // to -d can be comma-separated. 49 var debugtab = []struct { 50 name string 51 val *int 52 }{ 53 {"append", &Debug_append}, // print information about append compilation 54 {"disablenil", &Disable_checknil}, // disable nil checks 55 {"gcprog", &Debug_gcprog}, // print dump of GC programs 56 {"nil", &Debug_checknil}, // print information about nil checks 57 {"panic", &Debug_panic}, // do not hide any compiler panic 58 {"slice", &Debug_slice}, // print information about slice compilation 59 {"typeassert", &Debug_typeassert}, // print information about type assertion inlining 60 {"wb", &Debug_wb}, // print information about write barriers 61 } 62 63 // Our own isdigit, isspace, isalpha, isalnum that take care 64 // of EOF and other out of range arguments. 65 func yy_isdigit(c int) bool { 66 return c >= 0 && c <= 0xFF && isdigit(c) 67 } 68 69 func yy_isspace(c int) bool { 70 return c == ' ' || c == '\t' || c == '\n' || c == '\r' 71 } 72 73 func yy_isalpha(c int) bool { 74 return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' 75 } 76 77 func yy_isalnum(c int) bool { 78 return c >= 0 && c <= 0xFF && isalnum(c) 79 } 80 81 // Disallow use of isdigit etc. 82 83 const ( 84 EOF = -1 85 ) 86 87 func usage() { 88 fmt.Printf("usage: %cg [options] file.go...\n", Thearch.Thechar) 89 obj.Flagprint(1) 90 Exit(2) 91 } 92 93 func hidePanic() { 94 if Debug_panic == 0 && nsavederrors+nerrors > 0 { 95 // If we've already complained about things 96 // in the program, don't bother complaining 97 // about a panic too; let the user clean up 98 // the code and try again. 99 if err := recover(); err != nil { 100 errorexit() 101 } 102 } 103 } 104 105 func doversion() { 106 p := obj.Expstring() 107 if p == "X:none" { 108 p = "" 109 } 110 sep := "" 111 if p != "" { 112 sep = " " 113 } 114 fmt.Printf("%cg version %s%s%s\n", Thearch.Thechar, obj.Getgoversion(), sep, p) 115 os.Exit(0) 116 } 117 118 func Main() { 119 defer hidePanic() 120 121 // Allow GOARCH=thearch.thestring or GOARCH=thearch.thestringsuffix, 122 // but not other values. 123 p := obj.Getgoarch() 124 125 if !strings.HasPrefix(p, Thearch.Thestring) { 126 log.Fatalf("cannot use %cg with GOARCH=%s", Thearch.Thechar, p) 127 } 128 goarch = p 129 130 Thearch.Linkarchinit() 131 Ctxt = obj.Linknew(Thearch.Thelinkarch) 132 Ctxt.Diag = Yyerror 133 Ctxt.Bso = &bstdout 134 bstdout = *obj.Binitw(os.Stdout) 135 136 localpkg = mkpkg("") 137 localpkg.Prefix = "\"\"" 138 139 // pseudo-package, for scoping 140 builtinpkg = mkpkg("go.builtin") 141 142 builtinpkg.Prefix = "go.builtin" // not go%2ebuiltin 143 144 // pseudo-package, accessed by import "unsafe" 145 unsafepkg = mkpkg("unsafe") 146 147 unsafepkg.Name = "unsafe" 148 149 // real package, referred to by generated runtime calls 150 Runtimepkg = mkpkg("runtime") 151 152 Runtimepkg.Name = "runtime" 153 154 // pseudo-packages used in symbol tables 155 gostringpkg = mkpkg("go.string") 156 157 gostringpkg.Name = "go.string" 158 gostringpkg.Prefix = "go.string" // not go%2estring 159 160 itabpkg = mkpkg("go.itab") 161 162 itabpkg.Name = "go.itab" 163 itabpkg.Prefix = "go.itab" // not go%2eitab 164 165 weaktypepkg = mkpkg("go.weak.type") 166 167 weaktypepkg.Name = "go.weak.type" 168 weaktypepkg.Prefix = "go.weak.type" // not go%2eweak%2etype 169 170 typelinkpkg = mkpkg("go.typelink") 171 typelinkpkg.Name = "go.typelink" 172 typelinkpkg.Prefix = "go.typelink" // not go%2etypelink 173 174 trackpkg = mkpkg("go.track") 175 176 trackpkg.Name = "go.track" 177 trackpkg.Prefix = "go.track" // not go%2etrack 178 179 typepkg = mkpkg("type") 180 181 typepkg.Name = "type" 182 183 goroot = obj.Getgoroot() 184 goos = obj.Getgoos() 185 186 Nacl = goos == "nacl" 187 if Nacl { 188 flag_largemodel = 1 189 } 190 191 outfile = "" 192 obj.Flagcount("+", "compiling runtime", &compiling_runtime) 193 obj.Flagcount("%", "debug non-static initializers", &Debug['%']) 194 obj.Flagcount("A", "for bootstrapping, allow 'any' type", &Debug['A']) 195 obj.Flagcount("B", "disable bounds checking", &Debug['B']) 196 obj.Flagstr("D", "set relative `path` for local imports", &localimport) 197 obj.Flagcount("E", "debug symbol export", &Debug['E']) 198 obj.Flagfn1("I", "add `directory` to import search path", addidir) 199 obj.Flagcount("K", "debug missing line numbers", &Debug['K']) 200 obj.Flagcount("L", "use full (long) path in error messages", &Debug['L']) 201 obj.Flagcount("M", "debug move generation", &Debug['M']) 202 obj.Flagcount("N", "disable optimizations", &Debug['N']) 203 obj.Flagcount("P", "debug peephole optimizer", &Debug['P']) 204 obj.Flagcount("R", "debug register optimizer", &Debug['R']) 205 obj.Flagcount("S", "print assembly listing", &Debug['S']) 206 obj.Flagfn0("V", "print compiler version", doversion) 207 obj.Flagcount("W", "debug parse tree after type checking", &Debug['W']) 208 obj.Flagstr("asmhdr", "write assembly header to `file`", &asmhdr) 209 obj.Flagstr("buildid", "record `id` as the build id in the export metadata", &buildid) 210 obj.Flagcount("complete", "compiling complete package (no C or assembly)", &pure_go) 211 obj.Flagstr("d", "print debug information about items in `list`", &debugstr) 212 obj.Flagcount("e", "no limit on number of errors reported", &Debug['e']) 213 obj.Flagcount("f", "debug stack frames", &Debug['f']) 214 obj.Flagcount("g", "debug code generation", &Debug['g']) 215 obj.Flagcount("h", "halt on error", &Debug['h']) 216 obj.Flagcount("i", "debug line number stack", &Debug['i']) 217 obj.Flagfn1("importmap", "add `definition` of the form source=actual to import map", addImportMap) 218 obj.Flagstr("installsuffix", "set pkg directory `suffix`", &flag_installsuffix) 219 obj.Flagcount("j", "debug runtime-initialized variables", &Debug['j']) 220 obj.Flagcount("l", "disable inlining", &Debug['l']) 221 obj.Flagcount("live", "debug liveness analysis", &debuglive) 222 obj.Flagcount("m", "print optimization decisions", &Debug['m']) 223 obj.Flagcount("nolocalimports", "reject local (relative) imports", &nolocalimports) 224 obj.Flagstr("o", "write output to `file`", &outfile) 225 obj.Flagstr("p", "set expected package import `path`", &myimportpath) 226 obj.Flagcount("pack", "write package file instead of object file", &writearchive) 227 obj.Flagcount("r", "debug generated wrappers", &Debug['r']) 228 obj.Flagcount("race", "enable race detector", &flag_race) 229 obj.Flagcount("s", "warn about composite literals that can be simplified", &Debug['s']) 230 obj.Flagstr("trimpath", "remove `prefix` from recorded source file paths", &Ctxt.LineHist.TrimPathPrefix) 231 obj.Flagcount("u", "reject unsafe code", &safemode) 232 obj.Flagcount("v", "increase debug verbosity", &Debug['v']) 233 obj.Flagcount("w", "debug type checking", &Debug['w']) 234 use_writebarrier = 1 235 obj.Flagcount("wb", "enable write barrier", &use_writebarrier) 236 obj.Flagcount("x", "debug lexer", &Debug['x']) 237 obj.Flagcount("y", "debug declarations in canned imports (with -d)", &Debug['y']) 238 var flag_shared int 239 var flag_dynlink bool 240 if Thearch.Thechar == '6' { 241 obj.Flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel) 242 obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared) 243 flag.BoolVar(&flag_dynlink, "dynlink", false, "support references to Go symbols defined in other shared libraries") 244 } 245 obj.Flagstr("cpuprofile", "write cpu profile to `file`", &cpuprofile) 246 obj.Flagstr("memprofile", "write memory profile to `file`", &memprofile) 247 obj.Flagint64("memprofilerate", "set runtime.MemProfileRate to `rate`", &memprofilerate) 248 obj.Flagparse(usage) 249 250 if flag_dynlink { 251 flag_shared = 1 252 } 253 Ctxt.Flag_shared = int32(flag_shared) 254 Ctxt.Flag_dynlink = flag_dynlink 255 256 Ctxt.Debugasm = int32(Debug['S']) 257 Ctxt.Debugvlog = int32(Debug['v']) 258 259 if flag.NArg() < 1 { 260 usage() 261 } 262 263 startProfile() 264 265 if flag_race != 0 { 266 racepkg = mkpkg("runtime/race") 267 racepkg.Name = "race" 268 } 269 270 // parse -d argument 271 if debugstr != "" { 272 Split: 273 for _, name := range strings.Split(debugstr, ",") { 274 if name == "" { 275 continue 276 } 277 val := 1 278 if i := strings.Index(name, "="); i >= 0 { 279 var err error 280 val, err = strconv.Atoi(name[i+1:]) 281 if err != nil { 282 log.Fatalf("invalid debug value %v", name) 283 } 284 name = name[:i] 285 } 286 for _, t := range debugtab { 287 if t.name == name { 288 if t.val != nil { 289 *t.val = val 290 continue Split 291 } 292 } 293 } 294 log.Fatalf("unknown debug key -d %s\n", name) 295 } 296 } 297 298 // enable inlining. for now: 299 // default: inlining on. (debug['l'] == 1) 300 // -l: inlining off (debug['l'] == 0) 301 // -ll, -lll: inlining on again, with extra debugging (debug['l'] > 1) 302 if Debug['l'] <= 1 { 303 Debug['l'] = 1 - Debug['l'] 304 } 305 306 Thearch.Betypeinit() 307 if Widthptr == 0 { 308 Fatal("betypeinit failed") 309 } 310 311 lexinit() 312 typeinit() 313 lexinit1() 314 // TODO(rsc): Restore yytinit? 315 316 blockgen = 1 317 dclcontext = PEXTERN 318 nerrors = 0 319 lexlineno = 1 320 321 for _, infile = range flag.Args() { 322 linehistpush(infile) 323 324 curio.infile = infile 325 var err error 326 curio.bin, err = obj.Bopenr(infile) 327 if err != nil { 328 fmt.Printf("open %s: %v\n", infile, err) 329 errorexit() 330 } 331 332 curio.peekc = 0 333 curio.peekc1 = 0 334 curio.nlsemi = 0 335 curio.eofnl = 0 336 curio.last = 0 337 338 // Skip initial BOM if present. 339 if obj.Bgetrune(curio.bin) != obj.BOM { 340 obj.Bungetrune(curio.bin) 341 } 342 343 block = 1 344 iota_ = -1000000 345 346 imported_unsafe = 0 347 348 yyparse() 349 if nsyntaxerrors != 0 { 350 errorexit() 351 } 352 353 linehistpop() 354 if curio.bin != nil { 355 obj.Bterm(curio.bin) 356 } 357 } 358 359 testdclstack() 360 mkpackage(localpkg.Name) // final import not used checks 361 lexfini() 362 363 typecheckok = 1 364 if Debug['f'] != 0 { 365 frame(1) 366 } 367 368 // Process top-level declarations in phases. 369 370 // Phase 1: const, type, and names and types of funcs. 371 // This will gather all the information about types 372 // and methods but doesn't depend on any of it. 373 defercheckwidth() 374 375 for l := xtop; l != nil; l = l.Next { 376 if l.N.Op != ODCL && l.N.Op != OAS && l.N.Op != OAS2 { 377 typecheck(&l.N, Etop) 378 } 379 } 380 381 // Phase 2: Variable assignments. 382 // To check interface assignments, depends on phase 1. 383 for l := xtop; l != nil; l = l.Next { 384 if l.N.Op == ODCL || l.N.Op == OAS || l.N.Op == OAS2 { 385 typecheck(&l.N, Etop) 386 } 387 } 388 resumecheckwidth() 389 390 // Phase 3: Type check function bodies. 391 for l := xtop; l != nil; l = l.Next { 392 if l.N.Op == ODCLFUNC || l.N.Op == OCLOSURE { 393 Curfn = l.N 394 decldepth = 1 395 saveerrors() 396 typechecklist(l.N.Nbody, Etop) 397 checkreturn(l.N) 398 if nerrors != 0 { 399 l.N.Nbody = nil // type errors; do not compile 400 } 401 } 402 } 403 404 // Phase 4: Decide how to capture closed variables. 405 // This needs to run before escape analysis, 406 // because variables captured by value do not escape. 407 for l := xtop; l != nil; l = l.Next { 408 if l.N.Op == ODCLFUNC && l.N.Func.Closure != nil { 409 Curfn = l.N 410 capturevars(l.N) 411 } 412 } 413 414 Curfn = nil 415 416 if nsavederrors+nerrors != 0 { 417 errorexit() 418 } 419 420 // Phase 5: Inlining 421 if Debug['l'] > 1 { 422 // Typecheck imported function bodies if debug['l'] > 1, 423 // otherwise lazily when used or re-exported. 424 for l := importlist; l != nil; l = l.Next { 425 if l.N.Func.Inl != nil { 426 saveerrors() 427 typecheckinl(l.N) 428 } 429 } 430 431 if nsavederrors+nerrors != 0 { 432 errorexit() 433 } 434 } 435 436 if Debug['l'] != 0 { 437 // Find functions that can be inlined and clone them before walk expands them. 438 visitBottomUp(xtop, func(list *NodeList, recursive bool) { 439 for l := list; l != nil; l = l.Next { 440 if l.N.Op == ODCLFUNC { 441 caninl(l.N) 442 inlcalls(l.N) 443 } 444 } 445 }) 446 } 447 448 // Phase 6: Escape analysis. 449 // Required for moving heap allocations onto stack, 450 // which in turn is required by the closure implementation, 451 // which stores the addresses of stack variables into the closure. 452 // If the closure does not escape, it needs to be on the stack 453 // or else the stack copier will not update it. 454 // Large values are also moved off stack in escape analysis; 455 // because large values may contain pointers, it must happen early. 456 escapes(xtop) 457 458 // Phase 7: Transform closure bodies to properly reference captured variables. 459 // This needs to happen before walk, because closures must be transformed 460 // before walk reaches a call of a closure. 461 for l := xtop; l != nil; l = l.Next { 462 if l.N.Op == ODCLFUNC && l.N.Func.Closure != nil { 463 Curfn = l.N 464 transformclosure(l.N) 465 } 466 } 467 468 Curfn = nil 469 470 // Phase 8: Compile top level functions. 471 for l := xtop; l != nil; l = l.Next { 472 if l.N.Op == ODCLFUNC { 473 funccompile(l.N) 474 } 475 } 476 477 if nsavederrors+nerrors == 0 { 478 fninit(xtop) 479 } 480 481 // Phase 9: Check external declarations. 482 for l := externdcl; l != nil; l = l.Next { 483 if l.N.Op == ONAME { 484 typecheck(&l.N, Erv) 485 } 486 } 487 488 if nerrors+nsavederrors != 0 { 489 errorexit() 490 } 491 492 dumpobj() 493 494 if asmhdr != "" { 495 dumpasmhdr() 496 } 497 498 if nerrors+nsavederrors != 0 { 499 errorexit() 500 } 501 502 Flusherrors() 503 } 504 505 var importMap = map[string]string{} 506 507 func addImportMap(s string) { 508 if strings.Count(s, "=") != 1 { 509 log.Fatal("-importmap argument must be of the form source=actual") 510 } 511 i := strings.Index(s, "=") 512 source, actual := s[:i], s[i+1:] 513 if source == "" || actual == "" { 514 log.Fatal("-importmap argument must be of the form source=actual; source and actual must be non-empty") 515 } 516 importMap[source] = actual 517 } 518 519 func saveerrors() { 520 nsavederrors += nerrors 521 nerrors = 0 522 } 523 524 func arsize(b *obj.Biobuf, name string) int { 525 var buf [ArhdrSize]byte 526 if _, err := io.ReadFull(b, buf[:]); err != nil { 527 return -1 528 } 529 aname := strings.Trim(string(buf[0:16]), " ") 530 if !strings.HasPrefix(aname, name) { 531 return -1 532 } 533 asize := strings.Trim(string(buf[48:58]), " ") 534 i, _ := strconv.Atoi(asize) 535 return i 536 } 537 538 func skiptopkgdef(b *obj.Biobuf) bool { 539 /* archive header */ 540 p := obj.Brdline(b, '\n') 541 if p == "" { 542 return false 543 } 544 if obj.Blinelen(b) != 8 { 545 return false 546 } 547 if p != "!<arch>\n" { 548 return false 549 } 550 551 /* symbol table may be first; skip it */ 552 sz := arsize(b, "__.GOSYMDEF") 553 554 if sz >= 0 { 555 obj.Bseek(b, int64(sz), 1) 556 } else { 557 obj.Bseek(b, 8, 0) 558 } 559 560 /* package export block is next */ 561 sz = arsize(b, "__.PKGDEF") 562 563 if sz <= 0 { 564 return false 565 } 566 return true 567 } 568 569 func addidir(dir string) { 570 if dir == "" { 571 return 572 } 573 574 var pp **Idir 575 for pp = &idirs; *pp != nil; pp = &(*pp).link { 576 } 577 *pp = new(Idir) 578 (*pp).link = nil 579 (*pp).dir = dir 580 } 581 582 // is this path a local name? begins with ./ or ../ or / 583 func islocalname(name string) bool { 584 return strings.HasPrefix(name, "/") || 585 Ctxt.Windows != 0 && len(name) >= 3 && yy_isalpha(int(name[0])) && name[1] == ':' && name[2] == '/' || 586 strings.HasPrefix(name, "./") || name == "." || 587 strings.HasPrefix(name, "../") || name == ".." 588 } 589 590 func findpkg(name string) (file string, ok bool) { 591 if islocalname(name) { 592 if safemode != 0 || nolocalimports != 0 { 593 return "", false 594 } 595 596 // try .a before .6. important for building libraries: 597 // if there is an array.6 in the array.a library, 598 // want to find all of array.a, not just array.6. 599 file = fmt.Sprintf("%s.a", name) 600 if obj.Access(file, 0) >= 0 { 601 return file, true 602 } 603 file = fmt.Sprintf("%s.o", name) 604 if obj.Access(file, 0) >= 0 { 605 return file, true 606 } 607 return "", false 608 } 609 610 // local imports should be canonicalized already. 611 // don't want to see "encoding/../encoding/base64" 612 // as different from "encoding/base64". 613 var q string 614 _ = q 615 if path.Clean(name) != name { 616 Yyerror("non-canonical import path %q (should be %q)", name, q) 617 return "", false 618 } 619 620 for p := idirs; p != nil; p = p.link { 621 file = fmt.Sprintf("%s/%s.a", p.dir, name) 622 if obj.Access(file, 0) >= 0 { 623 return file, true 624 } 625 file = fmt.Sprintf("%s/%s.o", p.dir, name) 626 if obj.Access(file, 0) >= 0 { 627 return file, true 628 } 629 } 630 631 if goroot != "" { 632 suffix := "" 633 suffixsep := "" 634 if flag_installsuffix != "" { 635 suffixsep = "_" 636 suffix = flag_installsuffix 637 } else if flag_race != 0 { 638 suffixsep = "_" 639 suffix = "race" 640 } 641 642 file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.a", goroot, goos, goarch, suffixsep, suffix, name) 643 if obj.Access(file, 0) >= 0 { 644 return file, true 645 } 646 file = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.o", goroot, goos, goarch, suffixsep, suffix, name) 647 if obj.Access(file, 0) >= 0 { 648 return file, true 649 } 650 } 651 652 return "", false 653 } 654 655 func fakeimport() { 656 importpkg = mkpkg("fake") 657 cannedimports("fake.o", "$$\n") 658 } 659 660 func importfile(f *Val, line int) { 661 if _, ok := f.U.(string); !ok { 662 Yyerror("import statement not a string") 663 fakeimport() 664 return 665 } 666 667 if len(f.U.(string)) == 0 { 668 Yyerror("import path is empty") 669 fakeimport() 670 return 671 } 672 673 if isbadimport(f.U.(string)) { 674 fakeimport() 675 return 676 } 677 678 // The package name main is no longer reserved, 679 // but we reserve the import path "main" to identify 680 // the main package, just as we reserve the import 681 // path "math" to identify the standard math package. 682 if f.U.(string) == "main" { 683 Yyerror("cannot import \"main\"") 684 errorexit() 685 } 686 687 if myimportpath != "" && f.U.(string) == myimportpath { 688 Yyerror("import %q while compiling that package (import cycle)", f.U.(string)) 689 errorexit() 690 } 691 692 if f.U.(string) == "unsafe" { 693 if safemode != 0 { 694 Yyerror("cannot import package unsafe") 695 errorexit() 696 } 697 698 importpkg = mkpkg(f.U.(string)) 699 cannedimports("unsafe.o", unsafeimport) 700 imported_unsafe = 1 701 return 702 } 703 704 path_ := f.U.(string) 705 706 if mapped, ok := importMap[path_]; ok { 707 path_ = mapped 708 } 709 710 if islocalname(path_) { 711 if path_[0] == '/' { 712 Yyerror("import path cannot be absolute path") 713 fakeimport() 714 return 715 } 716 717 prefix := Ctxt.Pathname 718 if localimport != "" { 719 prefix = localimport 720 } 721 cleanbuf := prefix 722 cleanbuf += "/" 723 cleanbuf += path_ 724 cleanbuf = path.Clean(cleanbuf) 725 path_ = cleanbuf 726 727 if isbadimport(path_) { 728 fakeimport() 729 return 730 } 731 } 732 733 file, found := findpkg(path_) 734 if !found { 735 Yyerror("can't find import: %q", f.U.(string)) 736 errorexit() 737 } 738 739 importpkg = mkpkg(path_) 740 741 // If we already saw that package, feed a dummy statement 742 // to the lexer to avoid parsing export data twice. 743 if importpkg.Imported != 0 { 744 tag := "" 745 if importpkg.Safe { 746 tag = "safe" 747 } 748 749 p := fmt.Sprintf("package %s %s\n$$\n", importpkg.Name, tag) 750 cannedimports(file, p) 751 return 752 } 753 754 importpkg.Imported = 1 755 756 var err error 757 var imp *obj.Biobuf 758 imp, err = obj.Bopenr(file) 759 if err != nil { 760 Yyerror("can't open import: %q: %v", f.U.(string), err) 761 errorexit() 762 } 763 764 if strings.HasSuffix(file, ".a") { 765 if !skiptopkgdef(imp) { 766 Yyerror("import %s: not a package file", file) 767 errorexit() 768 } 769 } 770 771 // check object header 772 p := obj.Brdstr(imp, '\n', 1) 773 774 if p != "empty archive" { 775 if !strings.HasPrefix(p, "go object ") { 776 Yyerror("import %s: not a go object file", file) 777 errorexit() 778 } 779 780 q := fmt.Sprintf("%s %s %s %s", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring()) 781 if p[10:] != q { 782 Yyerror("import %s: object is [%s] expected [%s]", file, p[10:], q) 783 errorexit() 784 } 785 } 786 787 // assume files move (get installed) 788 // so don't record the full path. 789 linehistpragma(file[len(file)-len(path_)-2:]) // acts as #pragma lib 790 791 /* 792 * position the input right 793 * after $$ and return 794 */ 795 pushedio = curio 796 797 curio.bin = imp 798 curio.peekc = 0 799 curio.peekc1 = 0 800 curio.infile = file 801 curio.nlsemi = 0 802 typecheckok = 1 803 804 var c int32 805 for { 806 c = int32(getc()) 807 if c == EOF { 808 break 809 } 810 if c != '$' { 811 continue 812 } 813 c = int32(getc()) 814 if c == EOF { 815 break 816 } 817 if c != '$' { 818 continue 819 } 820 return 821 } 822 823 Yyerror("no import in %q", f.U.(string)) 824 unimportfile() 825 } 826 827 func unimportfile() { 828 if curio.bin != nil { 829 obj.Bterm(curio.bin) 830 curio.bin = nil 831 } else { 832 lexlineno-- // re correct sys.6 line number 833 } 834 835 curio = pushedio 836 837 pushedio.bin = nil 838 incannedimport = 0 839 typecheckok = 0 840 } 841 842 func cannedimports(file string, cp string) { 843 lexlineno++ // if sys.6 is included on line 1, 844 845 pushedio = curio 846 847 curio.bin = nil 848 curio.peekc = 0 849 curio.peekc1 = 0 850 curio.infile = file 851 curio.cp = cp 852 curio.nlsemi = 0 853 curio.importsafe = false 854 855 typecheckok = 1 856 incannedimport = 1 857 } 858 859 func isfrog(c int) bool { 860 // complain about possibly invisible control characters 861 if c < ' ' { 862 return !yy_isspace(c) // exclude good white space 863 } 864 865 if 0x7f <= c && c <= 0xa0 { // DEL, unicode block including unbreakable space. 866 return true 867 } 868 return false 869 } 870 871 type Loophack struct { 872 v int 873 next *Loophack 874 } 875 876 var _yylex_lstk *Loophack 877 878 func _yylex(yylval *yySymType) int32 { 879 var c1 int 880 var escflag int 881 var v int64 882 var cp *bytes.Buffer 883 var rune_ uint 884 var s *Sym 885 var h *Loophack 886 var str string 887 888 prevlineno = lineno 889 890 l0: 891 c := getc() 892 if yy_isspace(c) { 893 if c == '\n' && curio.nlsemi != 0 { 894 ungetc(c) 895 if Debug['x'] != 0 { 896 fmt.Printf("lex: implicit semi\n") 897 } 898 return ';' 899 } 900 901 goto l0 902 } 903 904 lineno = lexlineno /* start of token */ 905 906 if c >= utf8.RuneSelf { 907 /* all multibyte runes are alpha */ 908 cp = &lexbuf 909 cp.Reset() 910 911 goto talph 912 } 913 914 if yy_isalpha(c) { 915 cp = &lexbuf 916 cp.Reset() 917 goto talph 918 } 919 920 if yy_isdigit(c) { 921 cp = &lexbuf 922 cp.Reset() 923 if c != '0' { 924 for { 925 cp.WriteByte(byte(c)) 926 c = getc() 927 if yy_isdigit(c) { 928 continue 929 } 930 if c == '.' { 931 goto casedot 932 } 933 if c == 'e' || c == 'E' || c == 'p' || c == 'P' { 934 goto caseep 935 } 936 if c == 'i' { 937 goto casei 938 } 939 goto ncu 940 } 941 } 942 943 cp.WriteByte(byte(c)) 944 c = getc() 945 if c == 'x' || c == 'X' { 946 for { 947 cp.WriteByte(byte(c)) 948 c = getc() 949 if yy_isdigit(c) { 950 continue 951 } 952 if c >= 'a' && c <= 'f' { 953 continue 954 } 955 if c >= 'A' && c <= 'F' { 956 continue 957 } 958 if lexbuf.Len() == 2 { 959 Yyerror("malformed hex constant") 960 } 961 if c == 'p' { 962 goto caseep 963 } 964 goto ncu 965 } 966 } 967 968 if c == 'p' { // 0p begins floating point zero 969 goto caseep 970 } 971 972 c1 = 0 973 for { 974 if !yy_isdigit(c) { 975 break 976 } 977 if c < '0' || c > '7' { 978 c1 = 1 // not octal 979 } 980 cp.WriteByte(byte(c)) 981 c = getc() 982 } 983 984 if c == '.' { 985 goto casedot 986 } 987 if c == 'e' || c == 'E' { 988 goto caseep 989 } 990 if c == 'i' { 991 goto casei 992 } 993 if c1 != 0 { 994 Yyerror("malformed octal constant") 995 } 996 goto ncu 997 } 998 999 switch c { 1000 case EOF: 1001 lineno = prevlineno 1002 ungetc(EOF) 1003 return -1 1004 1005 case '_': 1006 cp = &lexbuf 1007 cp.Reset() 1008 goto talph 1009 1010 case '.': 1011 c1 = getc() 1012 if yy_isdigit(c1) { 1013 cp = &lexbuf 1014 cp.Reset() 1015 cp.WriteByte(byte(c)) 1016 c = c1 1017 goto casedot 1018 } 1019 1020 if c1 == '.' { 1021 c1 = getc() 1022 if c1 == '.' { 1023 c = LDDD 1024 goto lx 1025 } 1026 1027 ungetc(c1) 1028 c1 = '.' 1029 } 1030 1031 /* "..." */ 1032 case '"': 1033 lexbuf.Reset() 1034 lexbuf.WriteString(`"<string>"`) 1035 1036 cp = &strbuf 1037 cp.Reset() 1038 1039 for { 1040 if escchar('"', &escflag, &v) { 1041 break 1042 } 1043 if v < utf8.RuneSelf || escflag != 0 { 1044 cp.WriteByte(byte(v)) 1045 } else { 1046 rune_ = uint(v) 1047 cp.WriteRune(rune(rune_)) 1048 } 1049 } 1050 1051 goto strlit 1052 1053 /* `...` */ 1054 case '`': 1055 lexbuf.Reset() 1056 lexbuf.WriteString("`<string>`") 1057 1058 cp = &strbuf 1059 cp.Reset() 1060 1061 for { 1062 c = int(getr()) 1063 if c == '\r' { 1064 continue 1065 } 1066 if c == EOF { 1067 Yyerror("eof in string") 1068 break 1069 } 1070 1071 if c == '`' { 1072 break 1073 } 1074 cp.WriteRune(rune(c)) 1075 } 1076 1077 goto strlit 1078 1079 /* '.' */ 1080 case '\'': 1081 if escchar('\'', &escflag, &v) { 1082 Yyerror("empty character literal or unescaped ' in character literal") 1083 v = '\'' 1084 } 1085 1086 if !escchar('\'', &escflag, &v) { 1087 Yyerror("missing '") 1088 ungetc(int(v)) 1089 } 1090 1091 x := new(Mpint) 1092 yylval.val.U = x 1093 Mpmovecfix(x, v) 1094 x.Rune = true 1095 if Debug['x'] != 0 { 1096 fmt.Printf("lex: codepoint literal\n") 1097 } 1098 litbuf = "string literal" 1099 return LLITERAL 1100 1101 case '/': 1102 c1 = getc() 1103 if c1 == '*' { 1104 nl := 0 1105 for { 1106 c = int(getr()) 1107 if c == '\n' { 1108 nl = 1 1109 } 1110 for c == '*' { 1111 c = int(getr()) 1112 if c == '/' { 1113 if nl != 0 { 1114 ungetc('\n') 1115 } 1116 goto l0 1117 } 1118 1119 if c == '\n' { 1120 nl = 1 1121 } 1122 } 1123 1124 if c == EOF { 1125 Yyerror("eof in comment") 1126 errorexit() 1127 } 1128 } 1129 } 1130 1131 if c1 == '/' { 1132 c = getlinepragma() 1133 for { 1134 if c == '\n' || c == EOF { 1135 ungetc(c) 1136 goto l0 1137 } 1138 1139 c = int(getr()) 1140 } 1141 } 1142 1143 if c1 == '=' { 1144 c = ODIV 1145 goto asop 1146 } 1147 1148 case ':': 1149 c1 = getc() 1150 if c1 == '=' { 1151 c = LCOLAS 1152 yylval.i = int(lexlineno) 1153 goto lx 1154 } 1155 1156 case '*': 1157 c1 = getc() 1158 if c1 == '=' { 1159 c = OMUL 1160 goto asop 1161 } 1162 1163 case '%': 1164 c1 = getc() 1165 if c1 == '=' { 1166 c = OMOD 1167 goto asop 1168 } 1169 1170 case '+': 1171 c1 = getc() 1172 if c1 == '+' { 1173 c = LINC 1174 goto lx 1175 } 1176 1177 if c1 == '=' { 1178 c = OADD 1179 goto asop 1180 } 1181 1182 case '-': 1183 c1 = getc() 1184 if c1 == '-' { 1185 c = LDEC 1186 goto lx 1187 } 1188 1189 if c1 == '=' { 1190 c = OSUB 1191 goto asop 1192 } 1193 1194 case '>': 1195 c1 = getc() 1196 if c1 == '>' { 1197 c = LRSH 1198 c1 = getc() 1199 if c1 == '=' { 1200 c = ORSH 1201 goto asop 1202 } 1203 1204 break 1205 } 1206 1207 if c1 == '=' { 1208 c = LGE 1209 goto lx 1210 } 1211 1212 c = LGT 1213 1214 case '<': 1215 c1 = getc() 1216 if c1 == '<' { 1217 c = LLSH 1218 c1 = getc() 1219 if c1 == '=' { 1220 c = OLSH 1221 goto asop 1222 } 1223 1224 break 1225 } 1226 1227 if c1 == '=' { 1228 c = LLE 1229 goto lx 1230 } 1231 1232 if c1 == '-' { 1233 c = LCOMM 1234 goto lx 1235 } 1236 1237 c = LLT 1238 1239 case '=': 1240 c1 = getc() 1241 if c1 == '=' { 1242 c = LEQ 1243 goto lx 1244 } 1245 1246 case '!': 1247 c1 = getc() 1248 if c1 == '=' { 1249 c = LNE 1250 goto lx 1251 } 1252 1253 case '&': 1254 c1 = getc() 1255 if c1 == '&' { 1256 c = LANDAND 1257 goto lx 1258 } 1259 1260 if c1 == '^' { 1261 c = LANDNOT 1262 c1 = getc() 1263 if c1 == '=' { 1264 c = OANDNOT 1265 goto asop 1266 } 1267 1268 break 1269 } 1270 1271 if c1 == '=' { 1272 c = OAND 1273 goto asop 1274 } 1275 1276 case '|': 1277 c1 = getc() 1278 if c1 == '|' { 1279 c = LOROR 1280 goto lx 1281 } 1282 1283 if c1 == '=' { 1284 c = OOR 1285 goto asop 1286 } 1287 1288 case '^': 1289 c1 = getc() 1290 if c1 == '=' { 1291 c = OXOR 1292 goto asop 1293 } 1294 1295 /* 1296 * clumsy dance: 1297 * to implement rule that disallows 1298 * if T{1}[0] { ... } 1299 * but allows 1300 * if (T{1}[0]) { ... } 1301 * the block bodies for if/for/switch/select 1302 * begin with an LBODY token, not '{'. 1303 * 1304 * when we see the keyword, the next 1305 * non-parenthesized '{' becomes an LBODY. 1306 * loophack is normally 0. 1307 * a keyword makes it go up to 1. 1308 * parens push loophack onto a stack and go back to 0. 1309 * a '{' with loophack == 1 becomes LBODY and disables loophack. 1310 * 1311 * i said it was clumsy. 1312 */ 1313 case '(', '[': 1314 if loophack != 0 || _yylex_lstk != nil { 1315 h = new(Loophack) 1316 if h == nil { 1317 Flusherrors() 1318 Yyerror("out of memory") 1319 errorexit() 1320 } 1321 1322 h.v = loophack 1323 h.next = _yylex_lstk 1324 _yylex_lstk = h 1325 loophack = 0 1326 } 1327 1328 goto lx 1329 1330 case ')', ']': 1331 if _yylex_lstk != nil { 1332 h = _yylex_lstk 1333 loophack = h.v 1334 _yylex_lstk = h.next 1335 } 1336 1337 goto lx 1338 1339 case '{': 1340 if loophack == 1 { 1341 if Debug['x'] != 0 { 1342 fmt.Printf("%v lex: LBODY\n", Ctxt.Line(int(lexlineno))) 1343 } 1344 loophack = 0 1345 return LBODY 1346 } 1347 1348 goto lx 1349 1350 default: 1351 goto lx 1352 } 1353 1354 ungetc(c1) 1355 1356 lx: 1357 if c > 0xff { 1358 if Debug['x'] != 0 { 1359 fmt.Printf("%v lex: TOKEN %s\n", Ctxt.Line(int(lexlineno)), lexname(c)) 1360 } 1361 } else { 1362 if Debug['x'] != 0 { 1363 fmt.Printf("%v lex: TOKEN '%c'\n", Ctxt.Line(int(lexlineno)), c) 1364 } 1365 } 1366 if isfrog(c) { 1367 Yyerror("illegal character 0x%x", uint(c)) 1368 goto l0 1369 } 1370 1371 if importpkg == nil && (c == '#' || c == '$' || c == '?' || c == '@' || c == '\\') { 1372 Yyerror("%s: unexpected %c", "syntax error", c) 1373 goto l0 1374 } 1375 1376 return int32(c) 1377 1378 asop: 1379 yylval.i = c // rathole to hold which asop 1380 if Debug['x'] != 0 { 1381 fmt.Printf("lex: TOKEN ASOP %c\n", c) 1382 } 1383 return LASOP 1384 1385 /* 1386 * cp is set to lexbuf and some 1387 * prefix has been stored 1388 */ 1389 talph: 1390 for { 1391 if c >= utf8.RuneSelf { 1392 ungetc(c) 1393 rune_ = uint(getr()) 1394 1395 // 0xb7 is used for internal names 1396 if !unicode.IsLetter(rune(rune_)) && !unicode.IsDigit(rune(rune_)) && (importpkg == nil || rune_ != 0xb7) { 1397 Yyerror("invalid identifier character U+%04x", rune_) 1398 } 1399 cp.WriteRune(rune(rune_)) 1400 } else if !yy_isalnum(c) && c != '_' { 1401 break 1402 } else { 1403 cp.WriteByte(byte(c)) 1404 } 1405 c = getc() 1406 } 1407 1408 cp = nil 1409 ungetc(c) 1410 1411 s = LookupBytes(lexbuf.Bytes()) 1412 switch s.Lexical { 1413 case LIGNORE: 1414 goto l0 1415 1416 case LFOR, LIF, LSWITCH, LSELECT: 1417 loophack = 1 // see comment about loophack above 1418 } 1419 1420 if Debug['x'] != 0 { 1421 fmt.Printf("lex: %s %s\n", s, lexname(int(s.Lexical))) 1422 } 1423 yylval.sym = s 1424 return int32(s.Lexical) 1425 1426 ncu: 1427 cp = nil 1428 ungetc(c) 1429 1430 str = lexbuf.String() 1431 yylval.val.U = new(Mpint) 1432 mpatofix(yylval.val.U.(*Mpint), str) 1433 if yylval.val.U.(*Mpint).Ovf { 1434 Yyerror("overflow in constant") 1435 Mpmovecfix(yylval.val.U.(*Mpint), 0) 1436 } 1437 1438 if Debug['x'] != 0 { 1439 fmt.Printf("lex: integer literal\n") 1440 } 1441 litbuf = "literal " + str 1442 return LLITERAL 1443 1444 casedot: 1445 for { 1446 cp.WriteByte(byte(c)) 1447 c = getc() 1448 if !yy_isdigit(c) { 1449 break 1450 } 1451 } 1452 1453 if c == 'i' { 1454 goto casei 1455 } 1456 if c != 'e' && c != 'E' { 1457 goto caseout 1458 } 1459 1460 caseep: 1461 if importpkg == nil && (c == 'p' || c == 'P') { 1462 // <mantissa>p<base-2-exponent> is allowed in .a/.o imports, 1463 // but not in .go sources. See #9036. 1464 Yyerror("malformed floating point constant") 1465 } 1466 cp.WriteByte(byte(c)) 1467 c = getc() 1468 if c == '+' || c == '-' { 1469 cp.WriteByte(byte(c)) 1470 c = getc() 1471 } 1472 1473 if !yy_isdigit(c) { 1474 Yyerror("malformed floating point constant exponent") 1475 } 1476 for yy_isdigit(c) { 1477 cp.WriteByte(byte(c)) 1478 c = getc() 1479 } 1480 1481 if c == 'i' { 1482 goto casei 1483 } 1484 goto caseout 1485 1486 // imaginary constant 1487 casei: 1488 cp = nil 1489 1490 str = lexbuf.String() 1491 yylval.val.U = new(Mpcplx) 1492 Mpmovecflt(&yylval.val.U.(*Mpcplx).Real, 0.0) 1493 mpatoflt(&yylval.val.U.(*Mpcplx).Imag, str) 1494 if yylval.val.U.(*Mpcplx).Imag.Val.IsInf() { 1495 Yyerror("overflow in imaginary constant") 1496 Mpmovecflt(&yylval.val.U.(*Mpcplx).Real, 0.0) 1497 } 1498 1499 if Debug['x'] != 0 { 1500 fmt.Printf("lex: imaginary literal\n") 1501 } 1502 litbuf = "literal " + str 1503 return LLITERAL 1504 1505 caseout: 1506 cp = nil 1507 ungetc(c) 1508 1509 str = lexbuf.String() 1510 yylval.val.U = newMpflt() 1511 mpatoflt(yylval.val.U.(*Mpflt), str) 1512 if yylval.val.U.(*Mpflt).Val.IsInf() { 1513 Yyerror("overflow in float constant") 1514 Mpmovecflt(yylval.val.U.(*Mpflt), 0.0) 1515 } 1516 1517 if Debug['x'] != 0 { 1518 fmt.Printf("lex: floating literal\n") 1519 } 1520 litbuf = "literal " + str 1521 return LLITERAL 1522 1523 strlit: 1524 yylval.val.U = internString(cp.Bytes()) 1525 if Debug['x'] != 0 { 1526 fmt.Printf("lex: string literal\n") 1527 } 1528 litbuf = "string literal" 1529 return LLITERAL 1530 } 1531 1532 var internedStrings = map[string]string{} 1533 1534 func internString(b []byte) string { 1535 s, ok := internedStrings[string(b)] // string(b) here doesn't allocate 1536 if ok { 1537 return s 1538 } 1539 s = string(b) 1540 internedStrings[s] = s 1541 return s 1542 } 1543 1544 func more(pp *string) bool { 1545 p := *pp 1546 for p != "" && yy_isspace(int(p[0])) { 1547 p = p[1:] 1548 } 1549 *pp = p 1550 return p != "" 1551 } 1552 1553 /* 1554 * read and interpret syntax that looks like 1555 * //line parse.y:15 1556 * as a discontinuity in sequential line numbers. 1557 * the next line of input comes from parse.y:15 1558 */ 1559 func getlinepragma() int { 1560 var cmd, verb, name string 1561 1562 c := int(getr()) 1563 if c == 'g' { 1564 cp := &lexbuf 1565 cp.Reset() 1566 cp.WriteByte('g') // already read 1567 for { 1568 c = int(getr()) 1569 if c == EOF || c >= utf8.RuneSelf { 1570 return c 1571 } 1572 if c == '\n' { 1573 break 1574 } 1575 cp.WriteByte(byte(c)) 1576 } 1577 cp = nil 1578 1579 text := strings.TrimSuffix(lexbuf.String(), "\r") 1580 1581 if strings.HasPrefix(text, "go:cgo_") { 1582 pragcgo(text) 1583 } 1584 1585 cmd = text 1586 verb = cmd 1587 if i := strings.Index(verb, " "); i >= 0 { 1588 verb = verb[:i] 1589 } 1590 1591 if verb == "go:linkname" { 1592 if imported_unsafe == 0 { 1593 Yyerror("//go:linkname only allowed in Go files that import \"unsafe\"") 1594 } 1595 f := strings.Fields(cmd) 1596 if len(f) != 3 { 1597 Yyerror("usage: //go:linkname localname linkname") 1598 return c 1599 } 1600 1601 Lookup(f[1]).Linkname = f[2] 1602 return c 1603 } 1604 1605 if verb == "go:nointerface" && obj.Fieldtrack_enabled != 0 { 1606 nointerface = true 1607 return c 1608 } 1609 1610 if verb == "go:noescape" { 1611 noescape = true 1612 return c 1613 } 1614 1615 if verb == "go:norace" { 1616 norace = true 1617 return c 1618 } 1619 1620 if verb == "go:nosplit" { 1621 nosplit = true 1622 return c 1623 } 1624 1625 if verb == "go:systemstack" { 1626 systemstack = true 1627 return c 1628 } 1629 1630 if verb == "go:nowritebarrier" { 1631 if compiling_runtime == 0 { 1632 Yyerror("//go:nowritebarrier only allowed in runtime") 1633 } 1634 nowritebarrier = true 1635 return c 1636 } 1637 return c 1638 } 1639 if c != 'l' { 1640 return c 1641 } 1642 for i := 1; i < 5; i++ { 1643 c = int(getr()) 1644 if c != int("line "[i]) { 1645 return c 1646 } 1647 } 1648 1649 cp := &lexbuf 1650 cp.Reset() 1651 linep := 0 1652 for { 1653 c = int(getr()) 1654 if c == EOF { 1655 return c 1656 } 1657 if c == '\n' { 1658 break 1659 } 1660 if c == ' ' { 1661 continue 1662 } 1663 if c == ':' { 1664 linep = cp.Len() + 1 1665 } 1666 cp.WriteByte(byte(c)) 1667 } 1668 1669 cp = nil 1670 1671 if linep == 0 { 1672 return c 1673 } 1674 text := strings.TrimSuffix(lexbuf.String(), "\r") 1675 n := 0 1676 for _, c := range text[linep:] { 1677 if c < '0' || c > '9' { 1678 goto out 1679 } 1680 n = n*10 + int(c) - '0' 1681 if n > 1e8 { 1682 Yyerror("line number out of range") 1683 errorexit() 1684 } 1685 } 1686 1687 if n <= 0 { 1688 return c 1689 } 1690 1691 name = text[:linep-1] 1692 linehistupdate(name, n) 1693 return c 1694 1695 out: 1696 return c 1697 } 1698 1699 func getimpsym(pp *string) string { 1700 more(pp) // skip spaces 1701 p := *pp 1702 if p == "" || p[0] == '"' { 1703 return "" 1704 } 1705 i := 0 1706 for i < len(p) && !yy_isspace(int(p[i])) && p[i] != '"' { 1707 i++ 1708 } 1709 sym := p[:i] 1710 *pp = p[i:] 1711 return sym 1712 } 1713 1714 func getquoted(pp *string) (string, bool) { 1715 more(pp) // skip spaces 1716 p := *pp 1717 if p == "" || p[0] != '"' { 1718 return "", false 1719 } 1720 p = p[1:] 1721 i := strings.Index(p, `"`) 1722 if i < 0 { 1723 return "", false 1724 } 1725 *pp = p[i+1:] 1726 return p[:i], true 1727 } 1728 1729 // Copied nearly verbatim from the C compiler's #pragma parser. 1730 // TODO: Rewrite more cleanly once the compiler is written in Go. 1731 func pragcgo(text string) { 1732 var q string 1733 1734 if i := strings.Index(text, " "); i >= 0 { 1735 text, q = text[:i], text[i:] 1736 } 1737 1738 verb := text[3:] // skip "go:" 1739 1740 if verb == "cgo_dynamic_linker" || verb == "dynlinker" { 1741 var ok bool 1742 var p string 1743 p, ok = getquoted(&q) 1744 if !ok { 1745 Yyerror("usage: //go:cgo_dynamic_linker \"path\"") 1746 return 1747 } 1748 pragcgobuf += fmt.Sprintf("cgo_dynamic_linker %v\n", plan9quote(p)) 1749 return 1750 1751 } 1752 1753 if verb == "dynexport" { 1754 verb = "cgo_export_dynamic" 1755 } 1756 if verb == "cgo_export_static" || verb == "cgo_export_dynamic" { 1757 local := getimpsym(&q) 1758 var remote string 1759 if local == "" { 1760 goto err2 1761 } 1762 if !more(&q) { 1763 pragcgobuf += fmt.Sprintf("%s %v\n", verb, plan9quote(local)) 1764 return 1765 } 1766 1767 remote = getimpsym(&q) 1768 if remote == "" { 1769 goto err2 1770 } 1771 pragcgobuf += fmt.Sprintf("%s %v %v\n", verb, plan9quote(local), plan9quote(remote)) 1772 return 1773 1774 err2: 1775 Yyerror("usage: //go:%s local [remote]", verb) 1776 return 1777 } 1778 1779 if verb == "cgo_import_dynamic" || verb == "dynimport" { 1780 var ok bool 1781 local := getimpsym(&q) 1782 var p string 1783 var remote string 1784 if local == "" { 1785 goto err3 1786 } 1787 if !more(&q) { 1788 pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v\n", plan9quote(local)) 1789 return 1790 } 1791 1792 remote = getimpsym(&q) 1793 if remote == "" { 1794 goto err3 1795 } 1796 if !more(&q) { 1797 pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v\n", plan9quote(local), plan9quote(remote)) 1798 return 1799 } 1800 1801 p, ok = getquoted(&q) 1802 if !ok { 1803 goto err3 1804 } 1805 pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v %v\n", plan9quote(local), plan9quote(remote), plan9quote(p)) 1806 return 1807 1808 err3: 1809 Yyerror("usage: //go:cgo_import_dynamic local [remote [\"library\"]]") 1810 return 1811 } 1812 1813 if verb == "cgo_import_static" { 1814 local := getimpsym(&q) 1815 if local == "" || more(&q) { 1816 Yyerror("usage: //go:cgo_import_static local") 1817 return 1818 } 1819 pragcgobuf += fmt.Sprintf("cgo_import_static %v\n", plan9quote(local)) 1820 return 1821 1822 } 1823 1824 if verb == "cgo_ldflag" { 1825 var ok bool 1826 var p string 1827 p, ok = getquoted(&q) 1828 if !ok { 1829 Yyerror("usage: //go:cgo_ldflag \"arg\"") 1830 return 1831 } 1832 pragcgobuf += fmt.Sprintf("cgo_ldflag %v\n", plan9quote(p)) 1833 return 1834 1835 } 1836 } 1837 1838 type yy struct{} 1839 1840 func (yy) Lex(v *yySymType) int { 1841 return int(yylex(v)) 1842 } 1843 1844 func (yy) Error(msg string) { 1845 Yyerror("%s", msg) 1846 } 1847 1848 var theparser yyParser 1849 var parsing bool 1850 1851 func yyparse() { 1852 theparser = yyNewParser() 1853 parsing = true 1854 theparser.Parse(yy{}) 1855 parsing = false 1856 } 1857 1858 func yylex(yylval *yySymType) int32 { 1859 lx := int(_yylex(yylval)) 1860 1861 if curio.nlsemi != 0 && lx == EOF { 1862 // Treat EOF as "end of line" for the purposes 1863 // of inserting a semicolon. 1864 lx = ';' 1865 } 1866 1867 switch lx { 1868 case LNAME, 1869 LLITERAL, 1870 LBREAK, 1871 LCONTINUE, 1872 LFALL, 1873 LRETURN, 1874 LINC, 1875 LDEC, 1876 ')', 1877 '}', 1878 ']': 1879 curio.nlsemi = 1 1880 1881 default: 1882 curio.nlsemi = 0 1883 } 1884 1885 // Track last two tokens returned by yylex. 1886 yyprev = yylast 1887 1888 yylast = lx 1889 return int32(lx) 1890 } 1891 1892 func getc() int { 1893 c := curio.peekc 1894 if c != 0 { 1895 curio.peekc = curio.peekc1 1896 curio.peekc1 = 0 1897 goto check 1898 } 1899 1900 if curio.bin == nil { 1901 if len(curio.cp) == 0 { 1902 c = 0 1903 } else { 1904 c = int(curio.cp[0]) 1905 curio.cp = curio.cp[1:] 1906 } 1907 } else { 1908 loop: 1909 c = obj.Bgetc(curio.bin) 1910 if c == 0xef { 1911 buf, err := curio.bin.Peek(2) 1912 if err != nil { 1913 log.Fatalf("getc: peeking: %v", err) 1914 } 1915 if buf[0] == 0xbb && buf[1] == 0xbf { 1916 yyerrorl(int(lexlineno), "Unicode (UTF-8) BOM in middle of file") 1917 1918 // consume BOM bytes 1919 obj.Bgetc(curio.bin) 1920 obj.Bgetc(curio.bin) 1921 goto loop 1922 } 1923 } 1924 } 1925 1926 check: 1927 switch c { 1928 case 0: 1929 if curio.bin != nil { 1930 Yyerror("illegal NUL byte") 1931 break 1932 } 1933 fallthrough 1934 1935 // insert \n at EOF 1936 case EOF: 1937 if curio.eofnl != 0 || curio.last == '\n' { 1938 return EOF 1939 } 1940 curio.eofnl = 1 1941 c = '\n' 1942 fallthrough 1943 1944 case '\n': 1945 if pushedio.bin == nil { 1946 lexlineno++ 1947 } 1948 } 1949 1950 curio.last = c 1951 return c 1952 } 1953 1954 func ungetc(c int) { 1955 curio.peekc1 = curio.peekc 1956 curio.peekc = c 1957 if c == '\n' && pushedio.bin == nil { 1958 lexlineno-- 1959 } 1960 } 1961 1962 func getr() int32 { 1963 var buf [utf8.UTFMax]byte 1964 1965 for i := 0; ; i++ { 1966 c := getc() 1967 if i == 0 && c < utf8.RuneSelf { 1968 return int32(c) 1969 } 1970 buf[i] = byte(c) 1971 if i+1 == len(buf) || utf8.FullRune(buf[:i+1]) { 1972 r, w := utf8.DecodeRune(buf[:i+1]) 1973 if r == utf8.RuneError && w == 1 { 1974 lineno = lexlineno 1975 // The string conversion here makes a copy for passing 1976 // to fmt.Printf, so that buf itself does not escape and can 1977 // be allocated on the stack. 1978 Yyerror("illegal UTF-8 sequence % x", string(buf[:i+1])) 1979 } 1980 return int32(r) 1981 } 1982 } 1983 } 1984 1985 func escchar(e int, escflg *int, val *int64) bool { 1986 *escflg = 0 1987 1988 c := int(getr()) 1989 switch c { 1990 case EOF: 1991 Yyerror("eof in string") 1992 return true 1993 1994 case '\n': 1995 Yyerror("newline in string") 1996 return true 1997 1998 case '\\': 1999 break 2000 2001 default: 2002 if c == e { 2003 return true 2004 } 2005 *val = int64(c) 2006 return false 2007 } 2008 2009 u := 0 2010 c = int(getr()) 2011 var i int 2012 switch c { 2013 case 'x': 2014 *escflg = 1 // it's a byte 2015 i = 2 2016 goto hex 2017 2018 case 'u': 2019 i = 4 2020 u = 1 2021 goto hex 2022 2023 case 'U': 2024 i = 8 2025 u = 1 2026 goto hex 2027 2028 case '0', 2029 '1', 2030 '2', 2031 '3', 2032 '4', 2033 '5', 2034 '6', 2035 '7': 2036 *escflg = 1 // it's a byte 2037 l := int64(c) - '0' 2038 for i := 2; i > 0; i-- { 2039 c = getc() 2040 if c >= '0' && c <= '7' { 2041 l = l*8 + int64(c) - '0' 2042 continue 2043 } 2044 2045 Yyerror("non-octal character in escape sequence: %c", c) 2046 ungetc(c) 2047 } 2048 2049 if l > 255 { 2050 Yyerror("octal escape value > 255: %d", l) 2051 } 2052 2053 *val = l 2054 return false 2055 2056 case 'a': 2057 c = '\a' 2058 case 'b': 2059 c = '\b' 2060 case 'f': 2061 c = '\f' 2062 case 'n': 2063 c = '\n' 2064 case 'r': 2065 c = '\r' 2066 case 't': 2067 c = '\t' 2068 case 'v': 2069 c = '\v' 2070 case '\\': 2071 c = '\\' 2072 2073 default: 2074 if c != e { 2075 Yyerror("unknown escape sequence: %c", c) 2076 } 2077 } 2078 2079 *val = int64(c) 2080 return false 2081 2082 hex: 2083 l := int64(0) 2084 for ; i > 0; i-- { 2085 c = getc() 2086 if c >= '0' && c <= '9' { 2087 l = l*16 + int64(c) - '0' 2088 continue 2089 } 2090 2091 if c >= 'a' && c <= 'f' { 2092 l = l*16 + int64(c) - 'a' + 10 2093 continue 2094 } 2095 2096 if c >= 'A' && c <= 'F' { 2097 l = l*16 + int64(c) - 'A' + 10 2098 continue 2099 } 2100 2101 Yyerror("non-hex character in escape sequence: %c", c) 2102 ungetc(c) 2103 break 2104 } 2105 2106 if u != 0 && (l > utf8.MaxRune || (0xd800 <= l && l < 0xe000)) { 2107 Yyerror("invalid Unicode code point in escape sequence: %#x", l) 2108 l = utf8.RuneError 2109 } 2110 2111 *val = l 2112 return false 2113 } 2114 2115 var syms = []struct { 2116 name string 2117 lexical int 2118 etype int 2119 op int 2120 }{ 2121 /* basic types */ 2122 {"int8", LNAME, TINT8, OXXX}, 2123 {"int16", LNAME, TINT16, OXXX}, 2124 {"int32", LNAME, TINT32, OXXX}, 2125 {"int64", LNAME, TINT64, OXXX}, 2126 {"uint8", LNAME, TUINT8, OXXX}, 2127 {"uint16", LNAME, TUINT16, OXXX}, 2128 {"uint32", LNAME, TUINT32, OXXX}, 2129 {"uint64", LNAME, TUINT64, OXXX}, 2130 {"float32", LNAME, TFLOAT32, OXXX}, 2131 {"float64", LNAME, TFLOAT64, OXXX}, 2132 {"complex64", LNAME, TCOMPLEX64, OXXX}, 2133 {"complex128", LNAME, TCOMPLEX128, OXXX}, 2134 {"bool", LNAME, TBOOL, OXXX}, 2135 {"string", LNAME, TSTRING, OXXX}, 2136 {"any", LNAME, TANY, OXXX}, 2137 {"break", LBREAK, Txxx, OXXX}, 2138 {"case", LCASE, Txxx, OXXX}, 2139 {"chan", LCHAN, Txxx, OXXX}, 2140 {"const", LCONST, Txxx, OXXX}, 2141 {"continue", LCONTINUE, Txxx, OXXX}, 2142 {"default", LDEFAULT, Txxx, OXXX}, 2143 {"else", LELSE, Txxx, OXXX}, 2144 {"defer", LDEFER, Txxx, OXXX}, 2145 {"fallthrough", LFALL, Txxx, OXXX}, 2146 {"for", LFOR, Txxx, OXXX}, 2147 {"func", LFUNC, Txxx, OXXX}, 2148 {"go", LGO, Txxx, OXXX}, 2149 {"goto", LGOTO, Txxx, OXXX}, 2150 {"if", LIF, Txxx, OXXX}, 2151 {"import", LIMPORT, Txxx, OXXX}, 2152 {"interface", LINTERFACE, Txxx, OXXX}, 2153 {"map", LMAP, Txxx, OXXX}, 2154 {"package", LPACKAGE, Txxx, OXXX}, 2155 {"range", LRANGE, Txxx, OXXX}, 2156 {"return", LRETURN, Txxx, OXXX}, 2157 {"select", LSELECT, Txxx, OXXX}, 2158 {"struct", LSTRUCT, Txxx, OXXX}, 2159 {"switch", LSWITCH, Txxx, OXXX}, 2160 {"type", LTYPE, Txxx, OXXX}, 2161 {"var", LVAR, Txxx, OXXX}, 2162 {"append", LNAME, Txxx, OAPPEND}, 2163 {"cap", LNAME, Txxx, OCAP}, 2164 {"close", LNAME, Txxx, OCLOSE}, 2165 {"complex", LNAME, Txxx, OCOMPLEX}, 2166 {"copy", LNAME, Txxx, OCOPY}, 2167 {"delete", LNAME, Txxx, ODELETE}, 2168 {"imag", LNAME, Txxx, OIMAG}, 2169 {"len", LNAME, Txxx, OLEN}, 2170 {"make", LNAME, Txxx, OMAKE}, 2171 {"new", LNAME, Txxx, ONEW}, 2172 {"panic", LNAME, Txxx, OPANIC}, 2173 {"print", LNAME, Txxx, OPRINT}, 2174 {"println", LNAME, Txxx, OPRINTN}, 2175 {"real", LNAME, Txxx, OREAL}, 2176 {"recover", LNAME, Txxx, ORECOVER}, 2177 {"notwithstanding", LIGNORE, Txxx, OXXX}, 2178 {"thetruthofthematter", LIGNORE, Txxx, OXXX}, 2179 {"despiteallobjections", LIGNORE, Txxx, OXXX}, 2180 {"whereas", LIGNORE, Txxx, OXXX}, 2181 {"insofaras", LIGNORE, Txxx, OXXX}, 2182 } 2183 2184 func lexinit() { 2185 var lex int 2186 var s *Sym 2187 var s1 *Sym 2188 var t *Type 2189 var etype int 2190 2191 /* 2192 * initialize basic types array 2193 * initialize known symbols 2194 */ 2195 for i := 0; i < len(syms); i++ { 2196 lex = syms[i].lexical 2197 s = Lookup(syms[i].name) 2198 s.Lexical = uint16(lex) 2199 2200 etype = syms[i].etype 2201 if etype != Txxx { 2202 if etype < 0 || etype >= len(Types) { 2203 Fatal("lexinit: %s bad etype", s.Name) 2204 } 2205 s1 = Pkglookup(syms[i].name, builtinpkg) 2206 t = Types[etype] 2207 if t == nil { 2208 t = typ(etype) 2209 t.Sym = s1 2210 2211 if etype != TANY && etype != TSTRING { 2212 dowidth(t) 2213 } 2214 Types[etype] = t 2215 } 2216 2217 s1.Lexical = LNAME 2218 s1.Def = typenod(t) 2219 s1.Def.Name = new(Name) 2220 continue 2221 } 2222 2223 etype = syms[i].op 2224 if etype != OXXX { 2225 s1 = Pkglookup(syms[i].name, builtinpkg) 2226 s1.Lexical = LNAME 2227 s1.Def = Nod(ONAME, nil, nil) 2228 s1.Def.Sym = s1 2229 s1.Def.Etype = uint8(etype) 2230 } 2231 } 2232 2233 // logically, the type of a string literal. 2234 // types[TSTRING] is the named type string 2235 // (the type of x in var x string or var x = "hello"). 2236 // this is the ideal form 2237 // (the type of x in const x = "hello"). 2238 idealstring = typ(TSTRING) 2239 2240 idealbool = typ(TBOOL) 2241 2242 s = Pkglookup("true", builtinpkg) 2243 s.Def = Nodbool(true) 2244 s.Def.Sym = Lookup("true") 2245 s.Def.Name = new(Name) 2246 s.Def.Type = idealbool 2247 2248 s = Pkglookup("false", builtinpkg) 2249 s.Def = Nodbool(false) 2250 s.Def.Sym = Lookup("false") 2251 s.Def.Name = new(Name) 2252 s.Def.Type = idealbool 2253 2254 s = Lookup("_") 2255 s.Block = -100 2256 s.Def = Nod(ONAME, nil, nil) 2257 s.Def.Sym = s 2258 Types[TBLANK] = typ(TBLANK) 2259 s.Def.Type = Types[TBLANK] 2260 nblank = s.Def 2261 2262 s = Pkglookup("_", builtinpkg) 2263 s.Block = -100 2264 s.Def = Nod(ONAME, nil, nil) 2265 s.Def.Sym = s 2266 Types[TBLANK] = typ(TBLANK) 2267 s.Def.Type = Types[TBLANK] 2268 2269 Types[TNIL] = typ(TNIL) 2270 s = Pkglookup("nil", builtinpkg) 2271 var v Val 2272 v.U = new(NilVal) 2273 s.Def = nodlit(v) 2274 s.Def.Sym = s 2275 s.Def.Name = new(Name) 2276 } 2277 2278 func lexinit1() { 2279 // t = interface { Error() string } 2280 rcvr := typ(TSTRUCT) 2281 2282 rcvr.Type = typ(TFIELD) 2283 rcvr.Type.Type = Ptrto(typ(TSTRUCT)) 2284 rcvr.Funarg = 1 2285 in := typ(TSTRUCT) 2286 in.Funarg = 1 2287 out := typ(TSTRUCT) 2288 out.Type = typ(TFIELD) 2289 out.Type.Type = Types[TSTRING] 2290 out.Funarg = 1 2291 f := typ(TFUNC) 2292 *getthis(f) = rcvr 2293 *Getoutarg(f) = out 2294 *getinarg(f) = in 2295 f.Thistuple = 1 2296 f.Intuple = 0 2297 f.Outnamed = 0 2298 f.Outtuple = 1 2299 t := typ(TINTER) 2300 t.Type = typ(TFIELD) 2301 t.Type.Sym = Lookup("Error") 2302 t.Type.Type = f 2303 2304 // error type 2305 s := Lookup("error") 2306 2307 s.Lexical = LNAME 2308 s1 := Pkglookup("error", builtinpkg) 2309 errortype = t 2310 errortype.Sym = s1 2311 s1.Lexical = LNAME 2312 s1.Def = typenod(errortype) 2313 2314 // byte alias 2315 s = Lookup("byte") 2316 2317 s.Lexical = LNAME 2318 s1 = Pkglookup("byte", builtinpkg) 2319 bytetype = typ(TUINT8) 2320 bytetype.Sym = s1 2321 s1.Lexical = LNAME 2322 s1.Def = typenod(bytetype) 2323 s1.Def.Name = new(Name) 2324 2325 // rune alias 2326 s = Lookup("rune") 2327 2328 s.Lexical = LNAME 2329 s1 = Pkglookup("rune", builtinpkg) 2330 runetype = typ(TINT32) 2331 runetype.Sym = s1 2332 s1.Lexical = LNAME 2333 s1.Def = typenod(runetype) 2334 s1.Def.Name = new(Name) 2335 } 2336 2337 func lexfini() { 2338 var s *Sym 2339 var lex int 2340 var etype int 2341 var i int 2342 2343 for i = 0; i < len(syms); i++ { 2344 lex = syms[i].lexical 2345 if lex != LNAME { 2346 continue 2347 } 2348 s = Lookup(syms[i].name) 2349 s.Lexical = uint16(lex) 2350 2351 etype = syms[i].etype 2352 if etype != Txxx && (etype != TANY || Debug['A'] != 0) && s.Def == nil { 2353 s.Def = typenod(Types[etype]) 2354 s.Def.Name = new(Name) 2355 s.Origpkg = builtinpkg 2356 } 2357 2358 etype = syms[i].op 2359 if etype != OXXX && s.Def == nil { 2360 s.Def = Nod(ONAME, nil, nil) 2361 s.Def.Sym = s 2362 s.Def.Etype = uint8(etype) 2363 s.Origpkg = builtinpkg 2364 } 2365 } 2366 2367 // backend-specific builtin types (e.g. int). 2368 for i = range Thearch.Typedefs { 2369 s = Lookup(Thearch.Typedefs[i].Name) 2370 if s.Def == nil { 2371 s.Def = typenod(Types[Thearch.Typedefs[i].Etype]) 2372 s.Def.Name = new(Name) 2373 s.Origpkg = builtinpkg 2374 } 2375 } 2376 2377 // there's only so much table-driven we can handle. 2378 // these are special cases. 2379 s = Lookup("byte") 2380 2381 if s.Def == nil { 2382 s.Def = typenod(bytetype) 2383 s.Def.Name = new(Name) 2384 s.Origpkg = builtinpkg 2385 } 2386 2387 s = Lookup("error") 2388 if s.Def == nil { 2389 s.Def = typenod(errortype) 2390 s.Def.Name = new(Name) 2391 s.Origpkg = builtinpkg 2392 } 2393 2394 s = Lookup("rune") 2395 if s.Def == nil { 2396 s.Def = typenod(runetype) 2397 s.Def.Name = new(Name) 2398 s.Origpkg = builtinpkg 2399 } 2400 2401 s = Lookup("nil") 2402 if s.Def == nil { 2403 var v Val 2404 v.U = new(NilVal) 2405 s.Def = nodlit(v) 2406 s.Def.Sym = s 2407 s.Def.Name = new(Name) 2408 s.Origpkg = builtinpkg 2409 } 2410 2411 s = Lookup("iota") 2412 if s.Def == nil { 2413 s.Def = Nod(OIOTA, nil, nil) 2414 s.Def.Sym = s 2415 s.Origpkg = builtinpkg 2416 } 2417 2418 s = Lookup("true") 2419 if s.Def == nil { 2420 s.Def = Nodbool(true) 2421 s.Def.Sym = s 2422 s.Def.Name = new(Name) 2423 s.Origpkg = builtinpkg 2424 } 2425 2426 s = Lookup("false") 2427 if s.Def == nil { 2428 s.Def = Nodbool(false) 2429 s.Def.Sym = s 2430 s.Def.Name = new(Name) 2431 s.Origpkg = builtinpkg 2432 } 2433 2434 nodfp = Nod(ONAME, nil, nil) 2435 nodfp.Type = Types[TINT32] 2436 nodfp.Xoffset = 0 2437 nodfp.Class = PPARAM 2438 nodfp.Sym = Lookup(".fp") 2439 } 2440 2441 var lexn = []struct { 2442 lex int 2443 name string 2444 }{ 2445 {LANDAND, "ANDAND"}, 2446 {LANDNOT, "ANDNOT"}, 2447 {LASOP, "ASOP"}, 2448 {LBREAK, "BREAK"}, 2449 {LCASE, "CASE"}, 2450 {LCHAN, "CHAN"}, 2451 {LCOLAS, "COLAS"}, 2452 {LCOMM, "<-"}, 2453 {LCONST, "CONST"}, 2454 {LCONTINUE, "CONTINUE"}, 2455 {LDDD, "..."}, 2456 {LDEC, "DEC"}, 2457 {LDEFAULT, "DEFAULT"}, 2458 {LDEFER, "DEFER"}, 2459 {LELSE, "ELSE"}, 2460 {LEQ, "EQ"}, 2461 {LFALL, "FALL"}, 2462 {LFOR, "FOR"}, 2463 {LFUNC, "FUNC"}, 2464 {LGE, "GE"}, 2465 {LGO, "GO"}, 2466 {LGOTO, "GOTO"}, 2467 {LGT, "GT"}, 2468 {LIF, "IF"}, 2469 {LIMPORT, "IMPORT"}, 2470 {LINC, "INC"}, 2471 {LINTERFACE, "INTERFACE"}, 2472 {LLE, "LE"}, 2473 {LLITERAL, "LITERAL"}, 2474 {LLSH, "LSH"}, 2475 {LLT, "LT"}, 2476 {LMAP, "MAP"}, 2477 {LNAME, "NAME"}, 2478 {LNE, "NE"}, 2479 {LOROR, "OROR"}, 2480 {LPACKAGE, "PACKAGE"}, 2481 {LRANGE, "RANGE"}, 2482 {LRETURN, "RETURN"}, 2483 {LRSH, "RSH"}, 2484 {LSELECT, "SELECT"}, 2485 {LSTRUCT, "STRUCT"}, 2486 {LSWITCH, "SWITCH"}, 2487 {LTYPE, "TYPE"}, 2488 {LVAR, "VAR"}, 2489 } 2490 2491 func lexname(lex int) string { 2492 for i := 0; i < len(lexn); i++ { 2493 if lexn[i].lex == lex { 2494 return lexn[i].name 2495 } 2496 } 2497 return fmt.Sprintf("LEX-%d", lex) 2498 } 2499 2500 var yytfix = []struct { 2501 have string 2502 want string 2503 }{ 2504 {"$end", "EOF"}, 2505 {"LASOP", "op="}, 2506 {"LBREAK", "break"}, 2507 {"LCASE", "case"}, 2508 {"LCHAN", "chan"}, 2509 {"LCOLAS", ":="}, 2510 {"LCONST", "const"}, 2511 {"LCONTINUE", "continue"}, 2512 {"LDDD", "..."}, 2513 {"LDEFAULT", "default"}, 2514 {"LDEFER", "defer"}, 2515 {"LELSE", "else"}, 2516 {"LFALL", "fallthrough"}, 2517 {"LFOR", "for"}, 2518 {"LFUNC", "func"}, 2519 {"LGO", "go"}, 2520 {"LGOTO", "goto"}, 2521 {"LIF", "if"}, 2522 {"LIMPORT", "import"}, 2523 {"LINTERFACE", "interface"}, 2524 {"LMAP", "map"}, 2525 {"LNAME", "name"}, 2526 {"LPACKAGE", "package"}, 2527 {"LRANGE", "range"}, 2528 {"LRETURN", "return"}, 2529 {"LSELECT", "select"}, 2530 {"LSTRUCT", "struct"}, 2531 {"LSWITCH", "switch"}, 2532 {"LTYPE", "type"}, 2533 {"LVAR", "var"}, 2534 {"LANDAND", "&&"}, 2535 {"LANDNOT", "&^"}, 2536 {"LBODY", "{"}, 2537 {"LCOMM", "<-"}, 2538 {"LDEC", "--"}, 2539 {"LINC", "++"}, 2540 {"LEQ", "=="}, 2541 {"LGE", ">="}, 2542 {"LGT", ">"}, 2543 {"LLE", "<="}, 2544 {"LLT", "<"}, 2545 {"LLSH", "<<"}, 2546 {"LRSH", ">>"}, 2547 {"LOROR", "||"}, 2548 {"LNE", "!="}, 2549 // spell out to avoid confusion with punctuation in error messages 2550 {"';'", "semicolon or newline"}, 2551 {"','", "comma"}, 2552 } 2553 2554 func init() { 2555 yyErrorVerbose = true 2556 2557 Outer: 2558 for i, s := range yyToknames { 2559 // Apply yytfix if possible. 2560 for _, fix := range yytfix { 2561 if s == fix.have { 2562 yyToknames[i] = fix.want 2563 continue Outer 2564 } 2565 } 2566 2567 // Turn 'x' into x. 2568 if len(s) == 3 && s[0] == '\'' && s[2] == '\'' { 2569 yyToknames[i] = s[1:2] 2570 continue 2571 } 2572 } 2573 } 2574 2575 func pkgnotused(lineno int, path string, name string) { 2576 // If the package was imported with a name other than the final 2577 // import path element, show it explicitly in the error message. 2578 // Note that this handles both renamed imports and imports of 2579 // packages containing unconventional package declarations. 2580 // Note that this uses / always, even on Windows, because Go import 2581 // paths always use forward slashes. 2582 elem := path 2583 if i := strings.LastIndex(elem, "/"); i >= 0 { 2584 elem = elem[i+1:] 2585 } 2586 if name == "" || elem == name { 2587 yyerrorl(int(lineno), "imported and not used: %q", path) 2588 } else { 2589 yyerrorl(int(lineno), "imported and not used: %q as %s", path, name) 2590 } 2591 } 2592 2593 func mkpackage(pkgname string) { 2594 if localpkg.Name == "" { 2595 if pkgname == "_" { 2596 Yyerror("invalid package name _") 2597 } 2598 localpkg.Name = pkgname 2599 } else { 2600 if pkgname != localpkg.Name { 2601 Yyerror("package %s; expected %s", pkgname, localpkg.Name) 2602 } 2603 for _, s := range localpkg.Syms { 2604 if s.Def == nil { 2605 continue 2606 } 2607 if s.Def.Op == OPACK { 2608 // throw away top-level package name leftover 2609 // from previous file. 2610 // leave s->block set to cause redeclaration 2611 // errors if a conflicting top-level name is 2612 // introduced by a different file. 2613 if !s.Def.Used && nsyntaxerrors == 0 { 2614 pkgnotused(int(s.Def.Lineno), s.Def.Name.Pkg.Path, s.Name) 2615 } 2616 s.Def = nil 2617 continue 2618 } 2619 2620 if s.Def.Sym != s { 2621 // throw away top-level name left over 2622 // from previous import . "x" 2623 if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 { 2624 pkgnotused(int(s.Def.Name.Pack.Lineno), s.Def.Name.Pack.Name.Pkg.Path, "") 2625 s.Def.Name.Pack.Used = true 2626 } 2627 2628 s.Def = nil 2629 continue 2630 } 2631 } 2632 } 2633 2634 if outfile == "" { 2635 p := infile 2636 if i := strings.LastIndex(p, "/"); i >= 0 { 2637 p = p[i+1:] 2638 } 2639 if Ctxt.Windows != 0 { 2640 if i := strings.LastIndex(p, `\`); i >= 0 { 2641 p = p[i+1:] 2642 } 2643 } 2644 if i := strings.LastIndex(p, "."); i >= 0 { 2645 p = p[:i] 2646 } 2647 suffix := ".o" 2648 if writearchive > 0 { 2649 suffix = ".a" 2650 } 2651 outfile = p + suffix 2652 } 2653 } 2654