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