github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/src/cmd/compile/internal/gc/lex.go (about)

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