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