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