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