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