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