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