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