github.com/aloncn/graphics-go@v0.0.1/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.DiagFunc = 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 path_ := f.U.(string) 698 699 if mapped, ok := importMap[path_]; ok { 700 path_ = mapped 701 } 702 703 if path_ == "unsafe" { 704 if safemode != 0 { 705 Yyerror("cannot import package unsafe") 706 errorexit() 707 } 708 709 importpkg = mkpkg(f.U.(string)) 710 cannedimports("unsafe.o", unsafeimport) 711 imported_unsafe = true 712 return 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 // Reset incannedimport flag (we are not truly in a 847 // canned import) - this will cause importpkg.Direct to 848 // be set via parser.import_package (was issue #13977). 849 // 850 // TODO(gri) Remove this global variable and convoluted 851 // code in the process of streamlining the import code. 852 incannedimport = 0 853 854 default: 855 Yyerror("no import in %q", f.U.(string)) 856 } 857 } 858 859 func unimportfile() { 860 pop_parser() 861 862 if curio.bin != nil { 863 obj.Bterm(curio.bin) 864 curio.bin = nil 865 } else { 866 lexlineno-- // re correct sys.6 line number 867 } 868 869 curio = pushedio 870 871 pushedio.bin = nil 872 incannedimport = 0 873 typecheckok = false 874 } 875 876 func cannedimports(file string, cp string) { 877 lexlineno++ // if sys.6 is included on line 1, 878 879 pushedio = curio 880 881 curio.bin = nil 882 curio.peekc = 0 883 curio.peekc1 = 0 884 curio.infile = file 885 curio.cp = cp 886 curio.nlsemi = false 887 curio.importsafe = false 888 889 typecheckok = true 890 incannedimport = 1 891 892 push_parser() 893 } 894 895 func isSpace(c int) bool { 896 return c == ' ' || c == '\t' || c == '\n' || c == '\r' 897 } 898 899 func isAlpha(c int) bool { 900 return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' 901 } 902 903 func isDigit(c int) bool { 904 return '0' <= c && c <= '9' 905 } 906 func isAlnum(c int) bool { 907 return isAlpha(c) || isDigit(c) 908 } 909 910 func plan9quote(s string) string { 911 if s == "" { 912 return "''" 913 } 914 for _, c := range s { 915 if c <= ' ' || c == '\'' { 916 return "'" + strings.Replace(s, "'", "''", -1) + "'" 917 } 918 } 919 return s 920 } 921 922 func isfrog(c int) bool { 923 // complain about possibly invisible control characters 924 if c < ' ' { 925 return !isSpace(c) // exclude good white space 926 } 927 928 if 0x7f <= c && c <= 0xa0 { // DEL, unicode block including unbreakable space. 929 return true 930 } 931 return false 932 } 933 934 type yySymType struct { 935 sym *Sym 936 val Val 937 op Op 938 } 939 940 const ( 941 LLITERAL = 57346 + iota 942 LASOP 943 LCOLAS 944 LBREAK 945 LCASE 946 LCHAN 947 LCONST 948 LCONTINUE 949 LDDD 950 LDEFAULT 951 LDEFER 952 LELSE 953 LFALL 954 LFOR 955 LFUNC 956 LGO 957 LGOTO 958 LIF 959 LIMPORT 960 LINTERFACE 961 LMAP 962 LNAME 963 LPACKAGE 964 LRANGE 965 LRETURN 966 LSELECT 967 LSTRUCT 968 LSWITCH 969 LTYPE 970 LVAR 971 LANDAND 972 LANDNOT 973 LCOMM 974 LDEC 975 LEQ 976 LGE 977 LGT 978 LIGNORE 979 LINC 980 LLE 981 LLSH 982 LLT 983 LNE 984 LOROR 985 LRSH 986 ) 987 988 func _yylex(yylval *yySymType) int32 { 989 var c1 int 990 var op Op 991 var escflag int 992 var v int64 993 var cp *bytes.Buffer 994 var s *Sym 995 var str string 996 997 prevlineno = lineno 998 999 l0: 1000 c := getc() 1001 if isSpace(c) { 1002 if c == '\n' && curio.nlsemi { 1003 ungetc(c) 1004 if Debug['x'] != 0 { 1005 fmt.Printf("lex: implicit semi\n") 1006 } 1007 return ';' 1008 } 1009 1010 goto l0 1011 } 1012 1013 lineno = lexlineno // start of token 1014 1015 if c >= utf8.RuneSelf { 1016 // all multibyte runes are alpha 1017 cp = &lexbuf 1018 cp.Reset() 1019 1020 goto talph 1021 } 1022 1023 if isAlpha(c) { 1024 cp = &lexbuf 1025 cp.Reset() 1026 goto talph 1027 } 1028 1029 if isDigit(c) { 1030 cp = &lexbuf 1031 cp.Reset() 1032 if c != '0' { 1033 for { 1034 cp.WriteByte(byte(c)) 1035 c = getc() 1036 if isDigit(c) { 1037 continue 1038 } 1039 if c == '.' { 1040 goto casedot 1041 } 1042 if c == 'e' || c == 'E' || c == 'p' || c == 'P' { 1043 goto caseep 1044 } 1045 if c == 'i' { 1046 goto casei 1047 } 1048 goto ncu 1049 } 1050 } 1051 1052 cp.WriteByte(byte(c)) 1053 c = getc() 1054 if c == 'x' || c == 'X' { 1055 for { 1056 cp.WriteByte(byte(c)) 1057 c = getc() 1058 if isDigit(c) { 1059 continue 1060 } 1061 if c >= 'a' && c <= 'f' { 1062 continue 1063 } 1064 if c >= 'A' && c <= 'F' { 1065 continue 1066 } 1067 if lexbuf.Len() == 2 { 1068 Yyerror("malformed hex constant") 1069 } 1070 if c == 'p' { 1071 goto caseep 1072 } 1073 goto ncu 1074 } 1075 } 1076 1077 if c == 'p' { // 0p begins floating point zero 1078 goto caseep 1079 } 1080 1081 c1 = 0 1082 for { 1083 if !isDigit(c) { 1084 break 1085 } 1086 if c < '0' || c > '7' { 1087 c1 = 1 // not octal 1088 } 1089 cp.WriteByte(byte(c)) 1090 c = getc() 1091 } 1092 1093 if c == '.' { 1094 goto casedot 1095 } 1096 if c == 'e' || c == 'E' { 1097 goto caseep 1098 } 1099 if c == 'i' { 1100 goto casei 1101 } 1102 if c1 != 0 { 1103 Yyerror("malformed octal constant") 1104 } 1105 goto ncu 1106 } 1107 1108 switch c { 1109 case EOF: 1110 lineno = prevlineno 1111 ungetc(EOF) 1112 return -1 1113 1114 case '_': 1115 cp = &lexbuf 1116 cp.Reset() 1117 goto talph 1118 1119 case '.': 1120 c1 = getc() 1121 if isDigit(c1) { 1122 cp = &lexbuf 1123 cp.Reset() 1124 cp.WriteByte(byte(c)) 1125 c = c1 1126 goto casedot 1127 } 1128 1129 if c1 == '.' { 1130 c1 = getc() 1131 if c1 == '.' { 1132 c = LDDD 1133 goto lx 1134 } 1135 1136 ungetc(c1) 1137 c1 = '.' 1138 } 1139 1140 // "..." 1141 case '"': 1142 lexbuf.Reset() 1143 lexbuf.WriteString(`"<string>"`) 1144 1145 cp = &strbuf 1146 cp.Reset() 1147 1148 for { 1149 if escchar('"', &escflag, &v) { 1150 break 1151 } 1152 if v < utf8.RuneSelf || escflag != 0 { 1153 cp.WriteByte(byte(v)) 1154 } else { 1155 cp.WriteRune(rune(v)) 1156 } 1157 } 1158 1159 goto strlit 1160 1161 // `...` 1162 case '`': 1163 lexbuf.Reset() 1164 lexbuf.WriteString("`<string>`") 1165 1166 cp = &strbuf 1167 cp.Reset() 1168 1169 for { 1170 c = int(getr()) 1171 if c == '\r' { 1172 continue 1173 } 1174 if c == EOF { 1175 Yyerror("eof in string") 1176 break 1177 } 1178 1179 if c == '`' { 1180 break 1181 } 1182 cp.WriteRune(rune(c)) 1183 } 1184 1185 goto strlit 1186 1187 // '.' 1188 case '\'': 1189 if escchar('\'', &escflag, &v) { 1190 Yyerror("empty character literal or unescaped ' in character literal") 1191 v = '\'' 1192 } 1193 1194 if !escchar('\'', &escflag, &v) { 1195 Yyerror("missing '") 1196 ungetc(int(v)) 1197 } 1198 1199 x := new(Mpint) 1200 yylval.val.U = x 1201 Mpmovecfix(x, v) 1202 x.Rune = true 1203 if Debug['x'] != 0 { 1204 fmt.Printf("lex: codepoint literal\n") 1205 } 1206 litbuf = "string literal" 1207 return LLITERAL 1208 1209 case '/': 1210 c1 = getc() 1211 if c1 == '*' { 1212 nl := false 1213 for { 1214 c = int(getr()) 1215 if c == '\n' { 1216 nl = true 1217 } 1218 for c == '*' { 1219 c = int(getr()) 1220 if c == '/' { 1221 if nl { 1222 ungetc('\n') 1223 } 1224 goto l0 1225 } 1226 1227 if c == '\n' { 1228 nl = true 1229 } 1230 } 1231 1232 if c == EOF { 1233 Yyerror("eof in comment") 1234 errorexit() 1235 } 1236 } 1237 } 1238 1239 if c1 == '/' { 1240 c = getlinepragma() 1241 for { 1242 if c == '\n' || c == EOF { 1243 ungetc(c) 1244 goto l0 1245 } 1246 1247 c = int(getr()) 1248 } 1249 } 1250 1251 if c1 == '=' { 1252 op = ODIV 1253 goto asop 1254 } 1255 1256 case ':': 1257 c1 = getc() 1258 if c1 == '=' { 1259 c = int(LCOLAS) 1260 goto lx 1261 } 1262 1263 case '*': 1264 c1 = getc() 1265 if c1 == '=' { 1266 op = OMUL 1267 goto asop 1268 } 1269 1270 case '%': 1271 c1 = getc() 1272 if c1 == '=' { 1273 op = OMOD 1274 goto asop 1275 } 1276 1277 case '+': 1278 c1 = getc() 1279 if c1 == '+' { 1280 c = int(LINC) 1281 goto lx 1282 } 1283 1284 if c1 == '=' { 1285 op = OADD 1286 goto asop 1287 } 1288 1289 case '-': 1290 c1 = getc() 1291 if c1 == '-' { 1292 c = int(LDEC) 1293 goto lx 1294 } 1295 1296 if c1 == '=' { 1297 op = OSUB 1298 goto asop 1299 } 1300 1301 case '>': 1302 c1 = getc() 1303 if c1 == '>' { 1304 c = int(LRSH) 1305 c1 = getc() 1306 if c1 == '=' { 1307 op = ORSH 1308 goto asop 1309 } 1310 1311 break 1312 } 1313 1314 if c1 == '=' { 1315 c = int(LGE) 1316 goto lx 1317 } 1318 1319 c = int(LGT) 1320 1321 case '<': 1322 c1 = getc() 1323 if c1 == '<' { 1324 c = int(LLSH) 1325 c1 = getc() 1326 if c1 == '=' { 1327 op = OLSH 1328 goto asop 1329 } 1330 1331 break 1332 } 1333 1334 if c1 == '=' { 1335 c = int(LLE) 1336 goto lx 1337 } 1338 1339 if c1 == '-' { 1340 c = int(LCOMM) 1341 goto lx 1342 } 1343 1344 c = int(LLT) 1345 1346 case '=': 1347 c1 = getc() 1348 if c1 == '=' { 1349 c = int(LEQ) 1350 goto lx 1351 } 1352 1353 case '!': 1354 c1 = getc() 1355 if c1 == '=' { 1356 c = int(LNE) 1357 goto lx 1358 } 1359 1360 case '&': 1361 c1 = getc() 1362 if c1 == '&' { 1363 c = int(LANDAND) 1364 goto lx 1365 } 1366 1367 if c1 == '^' { 1368 c = int(LANDNOT) 1369 c1 = getc() 1370 if c1 == '=' { 1371 op = OANDNOT 1372 goto asop 1373 } 1374 1375 break 1376 } 1377 1378 if c1 == '=' { 1379 op = OAND 1380 goto asop 1381 } 1382 1383 case '|': 1384 c1 = getc() 1385 if c1 == '|' { 1386 c = int(LOROR) 1387 goto lx 1388 } 1389 1390 if c1 == '=' { 1391 op = OOR 1392 goto asop 1393 } 1394 1395 case '^': 1396 c1 = getc() 1397 if c1 == '=' { 1398 op = OXOR 1399 goto asop 1400 } 1401 1402 default: 1403 goto lx 1404 } 1405 1406 ungetc(c1) 1407 1408 lx: 1409 if Debug['x'] != 0 { 1410 if c > 0xff { 1411 fmt.Printf("%v lex: TOKEN %s\n", Ctxt.Line(int(lexlineno)), lexname(c)) 1412 } else { 1413 fmt.Printf("%v lex: TOKEN '%c'\n", Ctxt.Line(int(lexlineno)), c) 1414 } 1415 } 1416 if isfrog(c) { 1417 Yyerror("illegal character 0x%x", uint(c)) 1418 goto l0 1419 } 1420 1421 if importpkg == nil && (c == '#' || c == '$' || c == '?' || c == '@' || c == '\\') { 1422 Yyerror("%s: unexpected %c", "syntax error", c) 1423 goto l0 1424 } 1425 1426 return int32(c) 1427 1428 asop: 1429 yylval.op = op 1430 if Debug['x'] != 0 { 1431 fmt.Printf("lex: TOKEN ASOP %s=\n", goopnames[op]) 1432 } 1433 return LASOP 1434 1435 // cp is set to lexbuf and some 1436 // prefix has been stored 1437 talph: 1438 for { 1439 if c >= utf8.RuneSelf { 1440 ungetc(c) 1441 r := rune(getr()) 1442 1443 // 0xb7 ยท is used for internal names 1444 if !unicode.IsLetter(r) && !unicode.IsDigit(r) && (importpkg == nil || r != 0xb7) { 1445 Yyerror("invalid identifier character U+%04x", r) 1446 } 1447 if cp.Len() == 0 && unicode.IsDigit(r) { 1448 Yyerror("identifier cannot begin with digit U+%04x", r) 1449 } 1450 cp.WriteRune(r) 1451 } else if !isAlnum(c) && c != '_' { 1452 break 1453 } else { 1454 cp.WriteByte(byte(c)) 1455 } 1456 c = getc() 1457 } 1458 1459 cp = nil 1460 ungetc(c) 1461 1462 s = LookupBytes(lexbuf.Bytes()) 1463 if s.Lexical == LIGNORE { 1464 goto l0 1465 } 1466 1467 if Debug['x'] != 0 { 1468 fmt.Printf("lex: %s %s\n", s, lexname(int(s.Lexical))) 1469 } 1470 yylval.sym = s 1471 return int32(s.Lexical) 1472 1473 ncu: 1474 cp = nil 1475 ungetc(c) 1476 1477 str = lexbuf.String() 1478 yylval.val.U = new(Mpint) 1479 mpatofix(yylval.val.U.(*Mpint), str) 1480 if yylval.val.U.(*Mpint).Ovf { 1481 Yyerror("overflow in constant") 1482 Mpmovecfix(yylval.val.U.(*Mpint), 0) 1483 } 1484 1485 if Debug['x'] != 0 { 1486 fmt.Printf("lex: integer literal\n") 1487 } 1488 litbuf = "literal " + str 1489 return LLITERAL 1490 1491 casedot: 1492 for { 1493 cp.WriteByte(byte(c)) 1494 c = getc() 1495 if !isDigit(c) { 1496 break 1497 } 1498 } 1499 1500 if c == 'i' { 1501 goto casei 1502 } 1503 if c != 'e' && c != 'E' { 1504 goto caseout 1505 } 1506 1507 caseep: 1508 if importpkg == nil && (c == 'p' || c == 'P') { 1509 // <mantissa>p<base-2-exponent> is allowed in .a/.o imports, 1510 // but not in .go sources. See #9036. 1511 Yyerror("malformed floating point constant") 1512 } 1513 cp.WriteByte(byte(c)) 1514 c = getc() 1515 if c == '+' || c == '-' { 1516 cp.WriteByte(byte(c)) 1517 c = getc() 1518 } 1519 1520 if !isDigit(c) { 1521 Yyerror("malformed floating point constant exponent") 1522 } 1523 for isDigit(c) { 1524 cp.WriteByte(byte(c)) 1525 c = getc() 1526 } 1527 1528 if c == 'i' { 1529 goto casei 1530 } 1531 goto caseout 1532 1533 // imaginary constant 1534 casei: 1535 cp = nil 1536 1537 str = lexbuf.String() 1538 yylval.val.U = new(Mpcplx) 1539 Mpmovecflt(&yylval.val.U.(*Mpcplx).Real, 0.0) 1540 mpatoflt(&yylval.val.U.(*Mpcplx).Imag, str) 1541 if yylval.val.U.(*Mpcplx).Imag.Val.IsInf() { 1542 Yyerror("overflow in imaginary constant") 1543 Mpmovecflt(&yylval.val.U.(*Mpcplx).Imag, 0.0) 1544 } 1545 1546 if Debug['x'] != 0 { 1547 fmt.Printf("lex: imaginary literal\n") 1548 } 1549 litbuf = "literal " + str 1550 return LLITERAL 1551 1552 caseout: 1553 cp = nil 1554 ungetc(c) 1555 1556 str = lexbuf.String() 1557 yylval.val.U = newMpflt() 1558 mpatoflt(yylval.val.U.(*Mpflt), str) 1559 if yylval.val.U.(*Mpflt).Val.IsInf() { 1560 Yyerror("overflow in float constant") 1561 Mpmovecflt(yylval.val.U.(*Mpflt), 0.0) 1562 } 1563 1564 if Debug['x'] != 0 { 1565 fmt.Printf("lex: floating literal\n") 1566 } 1567 litbuf = "literal " + str 1568 return LLITERAL 1569 1570 strlit: 1571 yylval.val.U = internString(cp.Bytes()) 1572 if Debug['x'] != 0 { 1573 fmt.Printf("lex: string literal\n") 1574 } 1575 litbuf = "string literal" 1576 return LLITERAL 1577 } 1578 1579 var internedStrings = map[string]string{} 1580 1581 func internString(b []byte) string { 1582 s, ok := internedStrings[string(b)] // string(b) here doesn't allocate 1583 if ok { 1584 return s 1585 } 1586 s = string(b) 1587 internedStrings[s] = s 1588 return s 1589 } 1590 1591 func more(pp *string) bool { 1592 p := *pp 1593 for p != "" && isSpace(int(p[0])) { 1594 p = p[1:] 1595 } 1596 *pp = p 1597 return p != "" 1598 } 1599 1600 // read and interpret syntax that looks like 1601 // //line parse.y:15 1602 // as a discontinuity in sequential line numbers. 1603 // the next line of input comes from parse.y:15 1604 func getlinepragma() int { 1605 var cmd, verb, name string 1606 1607 c := int(getr()) 1608 if c == 'g' { 1609 cp := &lexbuf 1610 cp.Reset() 1611 cp.WriteByte('g') // already read 1612 for { 1613 c = int(getr()) 1614 if c == EOF || c >= utf8.RuneSelf { 1615 return c 1616 } 1617 if c == '\n' { 1618 break 1619 } 1620 cp.WriteByte(byte(c)) 1621 } 1622 cp = nil 1623 1624 text := strings.TrimSuffix(lexbuf.String(), "\r") 1625 1626 if strings.HasPrefix(text, "go:cgo_") { 1627 pragcgo(text) 1628 } 1629 1630 cmd = text 1631 verb = cmd 1632 if i := strings.Index(verb, " "); i >= 0 { 1633 verb = verb[:i] 1634 } 1635 1636 if verb == "go:linkname" { 1637 if !imported_unsafe { 1638 Yyerror("//go:linkname only allowed in Go files that import \"unsafe\"") 1639 } 1640 f := strings.Fields(cmd) 1641 if len(f) != 3 { 1642 Yyerror("usage: //go:linkname localname linkname") 1643 return c 1644 } 1645 1646 Lookup(f[1]).Linkname = f[2] 1647 return c 1648 } 1649 1650 if verb == "go:nointerface" && obj.Fieldtrack_enabled != 0 { 1651 nointerface = true 1652 return c 1653 } 1654 1655 if verb == "go:noescape" { 1656 noescape = true 1657 return c 1658 } 1659 1660 if verb == "go:norace" { 1661 norace = true 1662 return c 1663 } 1664 1665 if verb == "go:nosplit" { 1666 nosplit = true 1667 return c 1668 } 1669 1670 if verb == "go:noinline" { 1671 noinline = true 1672 return c 1673 } 1674 1675 if verb == "go:systemstack" { 1676 if compiling_runtime == 0 { 1677 Yyerror("//go:systemstack only allowed in runtime") 1678 } 1679 systemstack = true 1680 return c 1681 } 1682 1683 if verb == "go:nowritebarrier" { 1684 if compiling_runtime == 0 { 1685 Yyerror("//go:nowritebarrier only allowed in runtime") 1686 } 1687 nowritebarrier = true 1688 return c 1689 } 1690 1691 if verb == "go:nowritebarrierrec" { 1692 if compiling_runtime == 0 { 1693 Yyerror("//go:nowritebarrierrec only allowed in runtime") 1694 } 1695 nowritebarrierrec = true 1696 nowritebarrier = true // Implies nowritebarrier 1697 return c 1698 } 1699 return c 1700 } 1701 if c != 'l' { 1702 return c 1703 } 1704 for i := 1; i < 5; i++ { 1705 c = int(getr()) 1706 if c != int("line "[i]) { 1707 return c 1708 } 1709 } 1710 1711 cp := &lexbuf 1712 cp.Reset() 1713 linep := 0 1714 for { 1715 c = int(getr()) 1716 if c == EOF { 1717 return c 1718 } 1719 if c == '\n' { 1720 break 1721 } 1722 if c == ' ' { 1723 continue 1724 } 1725 if c == ':' { 1726 linep = cp.Len() + 1 1727 } 1728 cp.WriteByte(byte(c)) 1729 } 1730 1731 cp = nil 1732 1733 if linep == 0 { 1734 return c 1735 } 1736 text := strings.TrimSuffix(lexbuf.String(), "\r") 1737 n := 0 1738 for _, c := range text[linep:] { 1739 if c < '0' || c > '9' { 1740 goto out 1741 } 1742 n = n*10 + int(c) - '0' 1743 if n > 1e8 { 1744 Yyerror("line number out of range") 1745 errorexit() 1746 } 1747 } 1748 1749 if n <= 0 { 1750 return c 1751 } 1752 1753 name = text[:linep-1] 1754 linehistupdate(name, n) 1755 return c 1756 1757 out: 1758 return c 1759 } 1760 1761 func getimpsym(pp *string) string { 1762 more(pp) // skip spaces 1763 p := *pp 1764 if p == "" || p[0] == '"' { 1765 return "" 1766 } 1767 i := 0 1768 for i < len(p) && !isSpace(int(p[i])) && p[i] != '"' { 1769 i++ 1770 } 1771 sym := p[:i] 1772 *pp = p[i:] 1773 return sym 1774 } 1775 1776 func getquoted(pp *string) (string, bool) { 1777 more(pp) // skip spaces 1778 p := *pp 1779 if p == "" || p[0] != '"' { 1780 return "", false 1781 } 1782 p = p[1:] 1783 i := strings.Index(p, `"`) 1784 if i < 0 { 1785 return "", false 1786 } 1787 *pp = p[i+1:] 1788 return p[:i], true 1789 } 1790 1791 // Copied nearly verbatim from the C compiler's #pragma parser. 1792 // TODO: Rewrite more cleanly once the compiler is written in Go. 1793 func pragcgo(text string) { 1794 var q string 1795 1796 if i := strings.Index(text, " "); i >= 0 { 1797 text, q = text[:i], text[i:] 1798 } 1799 1800 verb := text[3:] // skip "go:" 1801 1802 if verb == "cgo_dynamic_linker" || verb == "dynlinker" { 1803 p, ok := getquoted(&q) 1804 if !ok { 1805 Yyerror("usage: //go:cgo_dynamic_linker \"path\"") 1806 return 1807 } 1808 pragcgobuf += fmt.Sprintf("cgo_dynamic_linker %v\n", plan9quote(p)) 1809 return 1810 1811 } 1812 1813 if verb == "dynexport" { 1814 verb = "cgo_export_dynamic" 1815 } 1816 if verb == "cgo_export_static" || verb == "cgo_export_dynamic" { 1817 local := getimpsym(&q) 1818 var remote string 1819 if local == "" { 1820 goto err2 1821 } 1822 if !more(&q) { 1823 pragcgobuf += fmt.Sprintf("%s %v\n", verb, plan9quote(local)) 1824 return 1825 } 1826 1827 remote = getimpsym(&q) 1828 if remote == "" { 1829 goto err2 1830 } 1831 pragcgobuf += fmt.Sprintf("%s %v %v\n", verb, plan9quote(local), plan9quote(remote)) 1832 return 1833 1834 err2: 1835 Yyerror("usage: //go:%s local [remote]", verb) 1836 return 1837 } 1838 1839 if verb == "cgo_import_dynamic" || verb == "dynimport" { 1840 var ok bool 1841 local := getimpsym(&q) 1842 var p string 1843 var remote string 1844 if local == "" { 1845 goto err3 1846 } 1847 if !more(&q) { 1848 pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v\n", plan9quote(local)) 1849 return 1850 } 1851 1852 remote = getimpsym(&q) 1853 if remote == "" { 1854 goto err3 1855 } 1856 if !more(&q) { 1857 pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v\n", plan9quote(local), plan9quote(remote)) 1858 return 1859 } 1860 1861 p, ok = getquoted(&q) 1862 if !ok { 1863 goto err3 1864 } 1865 pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v %v\n", plan9quote(local), plan9quote(remote), plan9quote(p)) 1866 return 1867 1868 err3: 1869 Yyerror("usage: //go:cgo_import_dynamic local [remote [\"library\"]]") 1870 return 1871 } 1872 1873 if verb == "cgo_import_static" { 1874 local := getimpsym(&q) 1875 if local == "" || more(&q) { 1876 Yyerror("usage: //go:cgo_import_static local") 1877 return 1878 } 1879 pragcgobuf += fmt.Sprintf("cgo_import_static %v\n", plan9quote(local)) 1880 return 1881 1882 } 1883 1884 if verb == "cgo_ldflag" { 1885 p, ok := getquoted(&q) 1886 if !ok { 1887 Yyerror("usage: //go:cgo_ldflag \"arg\"") 1888 return 1889 } 1890 pragcgobuf += fmt.Sprintf("cgo_ldflag %v\n", plan9quote(p)) 1891 return 1892 1893 } 1894 } 1895 1896 func yylex(yylval *yySymType) int32 { 1897 lx := _yylex(yylval) 1898 1899 if curio.nlsemi && lx == EOF { 1900 // Treat EOF as "end of line" for the purposes 1901 // of inserting a semicolon. 1902 lx = ';' 1903 } 1904 1905 switch lx { 1906 case LNAME, 1907 LLITERAL, 1908 LBREAK, 1909 LCONTINUE, 1910 LFALL, 1911 LRETURN, 1912 LINC, 1913 LDEC, 1914 ')', 1915 '}', 1916 ']': 1917 curio.nlsemi = true 1918 1919 default: 1920 curio.nlsemi = false 1921 } 1922 1923 return lx 1924 } 1925 1926 func getc() int { 1927 c := curio.peekc 1928 if c != 0 { 1929 curio.peekc = curio.peekc1 1930 curio.peekc1 = 0 1931 goto check 1932 } 1933 1934 if curio.bin == nil { 1935 if len(curio.cp) == 0 { 1936 c = 0 1937 } else { 1938 c = int(curio.cp[0]) 1939 curio.cp = curio.cp[1:] 1940 } 1941 } else { 1942 loop: 1943 c = obj.Bgetc(curio.bin) 1944 // recognize BOM (U+FEFF): UTF-8 encoding is 0xef 0xbb 0xbf 1945 if c == 0xef { 1946 buf, err := curio.bin.Peek(2) 1947 if err != nil { 1948 yyerrorl(int(lexlineno), "illegal UTF-8 sequence ef % x followed by read error (%v)", string(buf), err) 1949 errorexit() 1950 } 1951 if buf[0] == 0xbb && buf[1] == 0xbf { 1952 yyerrorl(int(lexlineno), "Unicode (UTF-8) BOM in middle of file") 1953 1954 // consume BOM bytes 1955 obj.Bgetc(curio.bin) 1956 obj.Bgetc(curio.bin) 1957 goto loop 1958 } 1959 } 1960 } 1961 1962 check: 1963 switch c { 1964 case 0: 1965 if curio.bin != nil { 1966 Yyerror("illegal NUL byte") 1967 break 1968 } 1969 fallthrough 1970 1971 // insert \n at EOF 1972 case EOF: 1973 if curio.eofnl || curio.last == '\n' { 1974 return EOF 1975 } 1976 curio.eofnl = true 1977 c = '\n' 1978 fallthrough 1979 1980 case '\n': 1981 if pushedio.bin == nil { 1982 lexlineno++ 1983 } 1984 } 1985 1986 curio.last = c 1987 return c 1988 } 1989 1990 func ungetc(c int) { 1991 curio.peekc1 = curio.peekc 1992 curio.peekc = c 1993 if c == '\n' && pushedio.bin == nil { 1994 lexlineno-- 1995 } 1996 } 1997 1998 func getr() int32 { 1999 var buf [utf8.UTFMax]byte 2000 2001 for i := 0; ; i++ { 2002 c := getc() 2003 if i == 0 && c < utf8.RuneSelf { 2004 return int32(c) 2005 } 2006 buf[i] = byte(c) 2007 if i+1 == len(buf) || utf8.FullRune(buf[:i+1]) { 2008 r, w := utf8.DecodeRune(buf[:i+1]) 2009 if r == utf8.RuneError && w == 1 { 2010 lineno = lexlineno 2011 // The string conversion here makes a copy for passing 2012 // to fmt.Printf, so that buf itself does not escape and can 2013 // be allocated on the stack. 2014 Yyerror("illegal UTF-8 sequence % x", string(buf[:i+1])) 2015 } 2016 return int32(r) 2017 } 2018 } 2019 } 2020 2021 func escchar(e int, escflg *int, val *int64) bool { 2022 *escflg = 0 2023 2024 c := int(getr()) 2025 switch c { 2026 case EOF: 2027 Yyerror("eof in string") 2028 return true 2029 2030 case '\n': 2031 Yyerror("newline in string") 2032 return true 2033 2034 case '\\': 2035 break 2036 2037 default: 2038 if c == e { 2039 return true 2040 } 2041 *val = int64(c) 2042 return false 2043 } 2044 2045 u := 0 2046 c = int(getr()) 2047 var i int 2048 switch c { 2049 case 'x': 2050 *escflg = 1 // it's a byte 2051 i = 2 2052 goto hex 2053 2054 case 'u': 2055 i = 4 2056 u = 1 2057 goto hex 2058 2059 case 'U': 2060 i = 8 2061 u = 1 2062 goto hex 2063 2064 case '0', 2065 '1', 2066 '2', 2067 '3', 2068 '4', 2069 '5', 2070 '6', 2071 '7': 2072 *escflg = 1 // it's a byte 2073 l := int64(c) - '0' 2074 for i := 2; i > 0; i-- { 2075 c = getc() 2076 if c >= '0' && c <= '7' { 2077 l = l*8 + int64(c) - '0' 2078 continue 2079 } 2080 2081 Yyerror("non-octal character in escape sequence: %c", c) 2082 ungetc(c) 2083 } 2084 2085 if l > 255 { 2086 Yyerror("octal escape value > 255: %d", l) 2087 } 2088 2089 *val = l 2090 return false 2091 2092 case 'a': 2093 c = '\a' 2094 case 'b': 2095 c = '\b' 2096 case 'f': 2097 c = '\f' 2098 case 'n': 2099 c = '\n' 2100 case 'r': 2101 c = '\r' 2102 case 't': 2103 c = '\t' 2104 case 'v': 2105 c = '\v' 2106 case '\\': 2107 c = '\\' 2108 2109 default: 2110 if c != e { 2111 Yyerror("unknown escape sequence: %c", c) 2112 } 2113 } 2114 2115 *val = int64(c) 2116 return false 2117 2118 hex: 2119 l := int64(0) 2120 for ; i > 0; i-- { 2121 c = getc() 2122 if c >= '0' && c <= '9' { 2123 l = l*16 + int64(c) - '0' 2124 continue 2125 } 2126 2127 if c >= 'a' && c <= 'f' { 2128 l = l*16 + int64(c) - 'a' + 10 2129 continue 2130 } 2131 2132 if c >= 'A' && c <= 'F' { 2133 l = l*16 + int64(c) - 'A' + 10 2134 continue 2135 } 2136 2137 Yyerror("non-hex character in escape sequence: %c", c) 2138 ungetc(c) 2139 break 2140 } 2141 2142 if u != 0 && (l > utf8.MaxRune || (0xd800 <= l && l < 0xe000)) { 2143 Yyerror("invalid Unicode code point in escape sequence: %#x", l) 2144 l = utf8.RuneError 2145 } 2146 2147 *val = l 2148 return false 2149 } 2150 2151 var syms = []struct { 2152 name string 2153 lexical int 2154 etype EType 2155 op Op 2156 }{ 2157 // basic types 2158 {"int8", LNAME, TINT8, OXXX}, 2159 {"int16", LNAME, TINT16, OXXX}, 2160 {"int32", LNAME, TINT32, OXXX}, 2161 {"int64", LNAME, TINT64, OXXX}, 2162 {"uint8", LNAME, TUINT8, OXXX}, 2163 {"uint16", LNAME, TUINT16, OXXX}, 2164 {"uint32", LNAME, TUINT32, OXXX}, 2165 {"uint64", LNAME, TUINT64, OXXX}, 2166 {"float32", LNAME, TFLOAT32, OXXX}, 2167 {"float64", LNAME, TFLOAT64, OXXX}, 2168 {"complex64", LNAME, TCOMPLEX64, OXXX}, 2169 {"complex128", LNAME, TCOMPLEX128, OXXX}, 2170 {"bool", LNAME, TBOOL, OXXX}, 2171 {"string", LNAME, TSTRING, OXXX}, 2172 {"any", LNAME, TANY, OXXX}, 2173 {"break", LBREAK, Txxx, OXXX}, 2174 {"case", LCASE, Txxx, OXXX}, 2175 {"chan", LCHAN, Txxx, OXXX}, 2176 {"const", LCONST, Txxx, OXXX}, 2177 {"continue", LCONTINUE, Txxx, OXXX}, 2178 {"default", LDEFAULT, Txxx, OXXX}, 2179 {"else", LELSE, Txxx, OXXX}, 2180 {"defer", LDEFER, Txxx, OXXX}, 2181 {"fallthrough", LFALL, Txxx, OXXX}, 2182 {"for", LFOR, Txxx, OXXX}, 2183 {"func", LFUNC, Txxx, OXXX}, 2184 {"go", LGO, Txxx, OXXX}, 2185 {"goto", LGOTO, Txxx, OXXX}, 2186 {"if", LIF, Txxx, OXXX}, 2187 {"import", LIMPORT, Txxx, OXXX}, 2188 {"interface", LINTERFACE, Txxx, OXXX}, 2189 {"map", LMAP, Txxx, OXXX}, 2190 {"package", LPACKAGE, Txxx, OXXX}, 2191 {"range", LRANGE, Txxx, OXXX}, 2192 {"return", LRETURN, Txxx, OXXX}, 2193 {"select", LSELECT, Txxx, OXXX}, 2194 {"struct", LSTRUCT, Txxx, OXXX}, 2195 {"switch", LSWITCH, Txxx, OXXX}, 2196 {"type", LTYPE, Txxx, OXXX}, 2197 {"var", LVAR, Txxx, OXXX}, 2198 {"append", LNAME, Txxx, OAPPEND}, 2199 {"cap", LNAME, Txxx, OCAP}, 2200 {"close", LNAME, Txxx, OCLOSE}, 2201 {"complex", LNAME, Txxx, OCOMPLEX}, 2202 {"copy", LNAME, Txxx, OCOPY}, 2203 {"delete", LNAME, Txxx, ODELETE}, 2204 {"imag", LNAME, Txxx, OIMAG}, 2205 {"len", LNAME, Txxx, OLEN}, 2206 {"make", LNAME, Txxx, OMAKE}, 2207 {"new", LNAME, Txxx, ONEW}, 2208 {"panic", LNAME, Txxx, OPANIC}, 2209 {"print", LNAME, Txxx, OPRINT}, 2210 {"println", LNAME, Txxx, OPRINTN}, 2211 {"real", LNAME, Txxx, OREAL}, 2212 {"recover", LNAME, Txxx, ORECOVER}, 2213 {"notwithstanding", LIGNORE, Txxx, OXXX}, 2214 {"thetruthofthematter", LIGNORE, Txxx, OXXX}, 2215 {"despiteallobjections", LIGNORE, Txxx, OXXX}, 2216 {"whereas", LIGNORE, Txxx, OXXX}, 2217 {"insofaras", LIGNORE, Txxx, OXXX}, 2218 } 2219 2220 // lexinit initializes known symbols and the basic types. 2221 func lexinit() { 2222 for _, s := range syms { 2223 lex := s.lexical 2224 s1 := Lookup(s.name) 2225 s1.Lexical = uint16(lex) 2226 2227 if etype := s.etype; etype != Txxx { 2228 if int(etype) >= len(Types) { 2229 Fatalf("lexinit: %s bad etype", s.name) 2230 } 2231 s2 := Pkglookup(s.name, builtinpkg) 2232 t := Types[etype] 2233 if t == nil { 2234 t = typ(etype) 2235 t.Sym = s2 2236 2237 if etype != TANY && etype != TSTRING { 2238 dowidth(t) 2239 } 2240 Types[etype] = t 2241 } 2242 2243 s2.Lexical = LNAME 2244 s2.Def = typenod(t) 2245 s2.Def.Name = new(Name) 2246 continue 2247 } 2248 2249 // TODO(marvin): Fix Node.EType type union. 2250 if etype := s.op; etype != OXXX { 2251 s2 := Pkglookup(s.name, builtinpkg) 2252 s2.Lexical = LNAME 2253 s2.Def = Nod(ONAME, nil, nil) 2254 s2.Def.Sym = s2 2255 s2.Def.Etype = EType(etype) 2256 } 2257 } 2258 2259 // logically, the type of a string literal. 2260 // types[TSTRING] is the named type string 2261 // (the type of x in var x string or var x = "hello"). 2262 // this is the ideal form 2263 // (the type of x in const x = "hello"). 2264 idealstring = typ(TSTRING) 2265 2266 idealbool = typ(TBOOL) 2267 2268 s := Pkglookup("true", builtinpkg) 2269 s.Def = Nodbool(true) 2270 s.Def.Sym = Lookup("true") 2271 s.Def.Name = new(Name) 2272 s.Def.Type = idealbool 2273 2274 s = Pkglookup("false", builtinpkg) 2275 s.Def = Nodbool(false) 2276 s.Def.Sym = Lookup("false") 2277 s.Def.Name = new(Name) 2278 s.Def.Type = idealbool 2279 2280 s = Lookup("_") 2281 s.Block = -100 2282 s.Def = Nod(ONAME, nil, nil) 2283 s.Def.Sym = s 2284 Types[TBLANK] = typ(TBLANK) 2285 s.Def.Type = Types[TBLANK] 2286 nblank = s.Def 2287 2288 s = Pkglookup("_", builtinpkg) 2289 s.Block = -100 2290 s.Def = Nod(ONAME, nil, nil) 2291 s.Def.Sym = s 2292 Types[TBLANK] = typ(TBLANK) 2293 s.Def.Type = Types[TBLANK] 2294 2295 Types[TNIL] = typ(TNIL) 2296 s = Pkglookup("nil", builtinpkg) 2297 var v Val 2298 v.U = new(NilVal) 2299 s.Def = nodlit(v) 2300 s.Def.Sym = s 2301 s.Def.Name = new(Name) 2302 } 2303 2304 func lexinit1() { 2305 // t = interface { Error() string } 2306 rcvr := typ(TSTRUCT) 2307 2308 rcvr.Type = typ(TFIELD) 2309 rcvr.Type.Type = Ptrto(typ(TSTRUCT)) 2310 rcvr.Funarg = true 2311 in := typ(TSTRUCT) 2312 in.Funarg = true 2313 out := typ(TSTRUCT) 2314 out.Type = typ(TFIELD) 2315 out.Type.Type = Types[TSTRING] 2316 out.Funarg = true 2317 f := typ(TFUNC) 2318 *getthis(f) = rcvr 2319 *Getoutarg(f) = out 2320 *getinarg(f) = in 2321 f.Thistuple = 1 2322 f.Intuple = 0 2323 f.Outnamed = false 2324 f.Outtuple = 1 2325 t := typ(TINTER) 2326 t.Type = typ(TFIELD) 2327 t.Type.Sym = Lookup("Error") 2328 t.Type.Type = f 2329 2330 // error type 2331 s := Lookup("error") 2332 2333 s.Lexical = LNAME 2334 s1 := Pkglookup("error", builtinpkg) 2335 errortype = t 2336 errortype.Sym = s1 2337 s1.Lexical = LNAME 2338 s1.Def = typenod(errortype) 2339 2340 // byte alias 2341 s = Lookup("byte") 2342 2343 s.Lexical = LNAME 2344 s1 = Pkglookup("byte", builtinpkg) 2345 bytetype = typ(TUINT8) 2346 bytetype.Sym = s1 2347 s1.Lexical = LNAME 2348 s1.Def = typenod(bytetype) 2349 s1.Def.Name = new(Name) 2350 2351 // rune alias 2352 s = Lookup("rune") 2353 2354 s.Lexical = LNAME 2355 s1 = Pkglookup("rune", builtinpkg) 2356 runetype = typ(TINT32) 2357 runetype.Sym = s1 2358 s1.Lexical = LNAME 2359 s1.Def = typenod(runetype) 2360 s1.Def.Name = new(Name) 2361 } 2362 2363 func lexfini() { 2364 for i := range syms { 2365 lex := syms[i].lexical 2366 if lex != LNAME { 2367 continue 2368 } 2369 s := Lookup(syms[i].name) 2370 s.Lexical = uint16(lex) 2371 2372 etype := syms[i].etype 2373 if etype != Txxx && (etype != TANY || Debug['A'] != 0) && s.Def == nil { 2374 s.Def = typenod(Types[etype]) 2375 s.Def.Name = new(Name) 2376 s.Origpkg = builtinpkg 2377 } 2378 2379 // TODO(marvin): Fix Node.EType type union. 2380 etype = EType(syms[i].op) 2381 if etype != EType(OXXX) && s.Def == nil { 2382 s.Def = Nod(ONAME, nil, nil) 2383 s.Def.Sym = s 2384 s.Def.Etype = etype 2385 s.Origpkg = builtinpkg 2386 } 2387 } 2388 2389 // backend-specific builtin types (e.g. int). 2390 for i := range Thearch.Typedefs { 2391 s := Lookup(Thearch.Typedefs[i].Name) 2392 if s.Def == nil { 2393 s.Def = typenod(Types[Thearch.Typedefs[i].Etype]) 2394 s.Def.Name = new(Name) 2395 s.Origpkg = builtinpkg 2396 } 2397 } 2398 2399 // there's only so much table-driven we can handle. 2400 // these are special cases. 2401 if s := Lookup("byte"); s.Def == nil { 2402 s.Def = typenod(bytetype) 2403 s.Def.Name = new(Name) 2404 s.Origpkg = builtinpkg 2405 } 2406 2407 if s := Lookup("error"); s.Def == nil { 2408 s.Def = typenod(errortype) 2409 s.Def.Name = new(Name) 2410 s.Origpkg = builtinpkg 2411 } 2412 2413 if s := Lookup("rune"); s.Def == nil { 2414 s.Def = typenod(runetype) 2415 s.Def.Name = new(Name) 2416 s.Origpkg = builtinpkg 2417 } 2418 2419 if s := Lookup("nil"); s.Def == nil { 2420 var v Val 2421 v.U = new(NilVal) 2422 s.Def = nodlit(v) 2423 s.Def.Sym = s 2424 s.Def.Name = new(Name) 2425 s.Origpkg = builtinpkg 2426 } 2427 2428 if s := Lookup("iota"); s.Def == nil { 2429 s.Def = Nod(OIOTA, nil, nil) 2430 s.Def.Sym = s 2431 s.Origpkg = builtinpkg 2432 } 2433 2434 if s := Lookup("true"); s.Def == nil { 2435 s.Def = Nodbool(true) 2436 s.Def.Sym = s 2437 s.Def.Name = new(Name) 2438 s.Origpkg = builtinpkg 2439 } 2440 2441 if s := Lookup("false"); s.Def == nil { 2442 s.Def = Nodbool(false) 2443 s.Def.Sym = s 2444 s.Def.Name = new(Name) 2445 s.Origpkg = builtinpkg 2446 } 2447 2448 nodfp = Nod(ONAME, nil, nil) 2449 nodfp.Type = Types[TINT32] 2450 nodfp.Xoffset = 0 2451 nodfp.Class = PPARAM 2452 nodfp.Sym = Lookup(".fp") 2453 } 2454 2455 var lexn = map[int]string{ 2456 LANDAND: "ANDAND", 2457 LANDNOT: "ANDNOT", 2458 LASOP: "ASOP", 2459 LBREAK: "BREAK", 2460 LCASE: "CASE", 2461 LCHAN: "CHAN", 2462 LCOLAS: "COLAS", 2463 LCOMM: "<-", 2464 LCONST: "CONST", 2465 LCONTINUE: "CONTINUE", 2466 LDDD: "...", 2467 LDEC: "DEC", 2468 LDEFAULT: "DEFAULT", 2469 LDEFER: "DEFER", 2470 LELSE: "ELSE", 2471 LEQ: "EQ", 2472 LFALL: "FALL", 2473 LFOR: "FOR", 2474 LFUNC: "FUNC", 2475 LGE: "GE", 2476 LGO: "GO", 2477 LGOTO: "GOTO", 2478 LGT: "GT", 2479 LIF: "IF", 2480 LIMPORT: "IMPORT", 2481 LINC: "INC", 2482 LINTERFACE: "INTERFACE", 2483 LLE: "LE", 2484 LLITERAL: "LITERAL", 2485 LLSH: "LSH", 2486 LLT: "LT", 2487 LMAP: "MAP", 2488 LNAME: "NAME", 2489 LNE: "NE", 2490 LOROR: "OROR", 2491 LPACKAGE: "PACKAGE", 2492 LRANGE: "RANGE", 2493 LRETURN: "RETURN", 2494 LRSH: "RSH", 2495 LSELECT: "SELECT", 2496 LSTRUCT: "STRUCT", 2497 LSWITCH: "SWITCH", 2498 LTYPE: "TYPE", 2499 LVAR: "VAR", 2500 } 2501 2502 func lexname(lex int) string { 2503 if s, ok := lexn[lex]; ok { 2504 return s 2505 } 2506 return fmt.Sprintf("LEX-%d", lex) 2507 } 2508 2509 func pkgnotused(lineno int, path string, name string) { 2510 // If the package was imported with a name other than the final 2511 // import path element, show it explicitly in the error message. 2512 // Note that this handles both renamed imports and imports of 2513 // packages containing unconventional package declarations. 2514 // Note that this uses / always, even on Windows, because Go import 2515 // paths always use forward slashes. 2516 elem := path 2517 if i := strings.LastIndex(elem, "/"); i >= 0 { 2518 elem = elem[i+1:] 2519 } 2520 if name == "" || elem == name { 2521 yyerrorl(int(lineno), "imported and not used: %q", path) 2522 } else { 2523 yyerrorl(int(lineno), "imported and not used: %q as %s", path, name) 2524 } 2525 } 2526 2527 func mkpackage(pkgname string) { 2528 if localpkg.Name == "" { 2529 if pkgname == "_" { 2530 Yyerror("invalid package name _") 2531 } 2532 localpkg.Name = pkgname 2533 } else { 2534 if pkgname != localpkg.Name { 2535 Yyerror("package %s; expected %s", pkgname, localpkg.Name) 2536 } 2537 for _, s := range localpkg.Syms { 2538 if s.Def == nil { 2539 continue 2540 } 2541 if s.Def.Op == OPACK { 2542 // throw away top-level package name leftover 2543 // from previous file. 2544 // leave s->block set to cause redeclaration 2545 // errors if a conflicting top-level name is 2546 // introduced by a different file. 2547 if !s.Def.Used && nsyntaxerrors == 0 { 2548 pkgnotused(int(s.Def.Lineno), s.Def.Name.Pkg.Path, s.Name) 2549 } 2550 s.Def = nil 2551 continue 2552 } 2553 2554 if s.Def.Sym != s { 2555 // throw away top-level name left over 2556 // from previous import . "x" 2557 if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 { 2558 pkgnotused(int(s.Def.Name.Pack.Lineno), s.Def.Name.Pack.Name.Pkg.Path, "") 2559 s.Def.Name.Pack.Used = true 2560 } 2561 2562 s.Def = nil 2563 continue 2564 } 2565 } 2566 } 2567 2568 if outfile == "" { 2569 p := infile 2570 if i := strings.LastIndex(p, "/"); i >= 0 { 2571 p = p[i+1:] 2572 } 2573 if Ctxt.Windows != 0 { 2574 if i := strings.LastIndex(p, `\`); i >= 0 { 2575 p = p[i+1:] 2576 } 2577 } 2578 if i := strings.LastIndex(p, "."); i >= 0 { 2579 p = p[:i] 2580 } 2581 suffix := ".o" 2582 if writearchive > 0 { 2583 suffix = ".a" 2584 } 2585 outfile = p + suffix 2586 } 2587 }