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