github.com/aloncn/graphics-go@v0.0.1/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.DiagFunc = 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  	path_ := f.U.(string)
   698  
   699  	if mapped, ok := importMap[path_]; ok {
   700  		path_ = mapped
   701  	}
   702  
   703  	if path_ == "unsafe" {
   704  		if safemode != 0 {
   705  			Yyerror("cannot import package unsafe")
   706  			errorexit()
   707  		}
   708  
   709  		importpkg = mkpkg(f.U.(string))
   710  		cannedimports("unsafe.o", unsafeimport)
   711  		imported_unsafe = true
   712  		return
   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  		// Reset incannedimport flag (we are not truly in a
   847  		// canned import) - this will cause importpkg.Direct to
   848  		// be set via parser.import_package (was issue #13977).
   849  		//
   850  		// TODO(gri) Remove this global variable and convoluted
   851  		// code in the process of streamlining the import code.
   852  		incannedimport = 0
   853  
   854  	default:
   855  		Yyerror("no import in %q", f.U.(string))
   856  	}
   857  }
   858  
   859  func unimportfile() {
   860  	pop_parser()
   861  
   862  	if curio.bin != nil {
   863  		obj.Bterm(curio.bin)
   864  		curio.bin = nil
   865  	} else {
   866  		lexlineno-- // re correct sys.6 line number
   867  	}
   868  
   869  	curio = pushedio
   870  
   871  	pushedio.bin = nil
   872  	incannedimport = 0
   873  	typecheckok = false
   874  }
   875  
   876  func cannedimports(file string, cp string) {
   877  	lexlineno++ // if sys.6 is included on line 1,
   878  
   879  	pushedio = curio
   880  
   881  	curio.bin = nil
   882  	curio.peekc = 0
   883  	curio.peekc1 = 0
   884  	curio.infile = file
   885  	curio.cp = cp
   886  	curio.nlsemi = false
   887  	curio.importsafe = false
   888  
   889  	typecheckok = true
   890  	incannedimport = 1
   891  
   892  	push_parser()
   893  }
   894  
   895  func isSpace(c int) bool {
   896  	return c == ' ' || c == '\t' || c == '\n' || c == '\r'
   897  }
   898  
   899  func isAlpha(c int) bool {
   900  	return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
   901  }
   902  
   903  func isDigit(c int) bool {
   904  	return '0' <= c && c <= '9'
   905  }
   906  func isAlnum(c int) bool {
   907  	return isAlpha(c) || isDigit(c)
   908  }
   909  
   910  func plan9quote(s string) string {
   911  	if s == "" {
   912  		return "''"
   913  	}
   914  	for _, c := range s {
   915  		if c <= ' ' || c == '\'' {
   916  			return "'" + strings.Replace(s, "'", "''", -1) + "'"
   917  		}
   918  	}
   919  	return s
   920  }
   921  
   922  func isfrog(c int) bool {
   923  	// complain about possibly invisible control characters
   924  	if c < ' ' {
   925  		return !isSpace(c) // exclude good white space
   926  	}
   927  
   928  	if 0x7f <= c && c <= 0xa0 { // DEL, unicode block including unbreakable space.
   929  		return true
   930  	}
   931  	return false
   932  }
   933  
   934  type yySymType struct {
   935  	sym *Sym
   936  	val Val
   937  	op  Op
   938  }
   939  
   940  const (
   941  	LLITERAL = 57346 + iota
   942  	LASOP
   943  	LCOLAS
   944  	LBREAK
   945  	LCASE
   946  	LCHAN
   947  	LCONST
   948  	LCONTINUE
   949  	LDDD
   950  	LDEFAULT
   951  	LDEFER
   952  	LELSE
   953  	LFALL
   954  	LFOR
   955  	LFUNC
   956  	LGO
   957  	LGOTO
   958  	LIF
   959  	LIMPORT
   960  	LINTERFACE
   961  	LMAP
   962  	LNAME
   963  	LPACKAGE
   964  	LRANGE
   965  	LRETURN
   966  	LSELECT
   967  	LSTRUCT
   968  	LSWITCH
   969  	LTYPE
   970  	LVAR
   971  	LANDAND
   972  	LANDNOT
   973  	LCOMM
   974  	LDEC
   975  	LEQ
   976  	LGE
   977  	LGT
   978  	LIGNORE
   979  	LINC
   980  	LLE
   981  	LLSH
   982  	LLT
   983  	LNE
   984  	LOROR
   985  	LRSH
   986  )
   987  
   988  func _yylex(yylval *yySymType) int32 {
   989  	var c1 int
   990  	var op Op
   991  	var escflag int
   992  	var v int64
   993  	var cp *bytes.Buffer
   994  	var s *Sym
   995  	var str string
   996  
   997  	prevlineno = lineno
   998  
   999  l0:
  1000  	c := getc()
  1001  	if isSpace(c) {
  1002  		if c == '\n' && curio.nlsemi {
  1003  			ungetc(c)
  1004  			if Debug['x'] != 0 {
  1005  				fmt.Printf("lex: implicit semi\n")
  1006  			}
  1007  			return ';'
  1008  		}
  1009  
  1010  		goto l0
  1011  	}
  1012  
  1013  	lineno = lexlineno // start of token
  1014  
  1015  	if c >= utf8.RuneSelf {
  1016  		// all multibyte runes are alpha
  1017  		cp = &lexbuf
  1018  		cp.Reset()
  1019  
  1020  		goto talph
  1021  	}
  1022  
  1023  	if isAlpha(c) {
  1024  		cp = &lexbuf
  1025  		cp.Reset()
  1026  		goto talph
  1027  	}
  1028  
  1029  	if isDigit(c) {
  1030  		cp = &lexbuf
  1031  		cp.Reset()
  1032  		if c != '0' {
  1033  			for {
  1034  				cp.WriteByte(byte(c))
  1035  				c = getc()
  1036  				if isDigit(c) {
  1037  					continue
  1038  				}
  1039  				if c == '.' {
  1040  					goto casedot
  1041  				}
  1042  				if c == 'e' || c == 'E' || c == 'p' || c == 'P' {
  1043  					goto caseep
  1044  				}
  1045  				if c == 'i' {
  1046  					goto casei
  1047  				}
  1048  				goto ncu
  1049  			}
  1050  		}
  1051  
  1052  		cp.WriteByte(byte(c))
  1053  		c = getc()
  1054  		if c == 'x' || c == 'X' {
  1055  			for {
  1056  				cp.WriteByte(byte(c))
  1057  				c = getc()
  1058  				if isDigit(c) {
  1059  					continue
  1060  				}
  1061  				if c >= 'a' && c <= 'f' {
  1062  					continue
  1063  				}
  1064  				if c >= 'A' && c <= 'F' {
  1065  					continue
  1066  				}
  1067  				if lexbuf.Len() == 2 {
  1068  					Yyerror("malformed hex constant")
  1069  				}
  1070  				if c == 'p' {
  1071  					goto caseep
  1072  				}
  1073  				goto ncu
  1074  			}
  1075  		}
  1076  
  1077  		if c == 'p' { // 0p begins floating point zero
  1078  			goto caseep
  1079  		}
  1080  
  1081  		c1 = 0
  1082  		for {
  1083  			if !isDigit(c) {
  1084  				break
  1085  			}
  1086  			if c < '0' || c > '7' {
  1087  				c1 = 1 // not octal
  1088  			}
  1089  			cp.WriteByte(byte(c))
  1090  			c = getc()
  1091  		}
  1092  
  1093  		if c == '.' {
  1094  			goto casedot
  1095  		}
  1096  		if c == 'e' || c == 'E' {
  1097  			goto caseep
  1098  		}
  1099  		if c == 'i' {
  1100  			goto casei
  1101  		}
  1102  		if c1 != 0 {
  1103  			Yyerror("malformed octal constant")
  1104  		}
  1105  		goto ncu
  1106  	}
  1107  
  1108  	switch c {
  1109  	case EOF:
  1110  		lineno = prevlineno
  1111  		ungetc(EOF)
  1112  		return -1
  1113  
  1114  	case '_':
  1115  		cp = &lexbuf
  1116  		cp.Reset()
  1117  		goto talph
  1118  
  1119  	case '.':
  1120  		c1 = getc()
  1121  		if isDigit(c1) {
  1122  			cp = &lexbuf
  1123  			cp.Reset()
  1124  			cp.WriteByte(byte(c))
  1125  			c = c1
  1126  			goto casedot
  1127  		}
  1128  
  1129  		if c1 == '.' {
  1130  			c1 = getc()
  1131  			if c1 == '.' {
  1132  				c = LDDD
  1133  				goto lx
  1134  			}
  1135  
  1136  			ungetc(c1)
  1137  			c1 = '.'
  1138  		}
  1139  
  1140  		// "..."
  1141  	case '"':
  1142  		lexbuf.Reset()
  1143  		lexbuf.WriteString(`"<string>"`)
  1144  
  1145  		cp = &strbuf
  1146  		cp.Reset()
  1147  
  1148  		for {
  1149  			if escchar('"', &escflag, &v) {
  1150  				break
  1151  			}
  1152  			if v < utf8.RuneSelf || escflag != 0 {
  1153  				cp.WriteByte(byte(v))
  1154  			} else {
  1155  				cp.WriteRune(rune(v))
  1156  			}
  1157  		}
  1158  
  1159  		goto strlit
  1160  
  1161  		// `...`
  1162  	case '`':
  1163  		lexbuf.Reset()
  1164  		lexbuf.WriteString("`<string>`")
  1165  
  1166  		cp = &strbuf
  1167  		cp.Reset()
  1168  
  1169  		for {
  1170  			c = int(getr())
  1171  			if c == '\r' {
  1172  				continue
  1173  			}
  1174  			if c == EOF {
  1175  				Yyerror("eof in string")
  1176  				break
  1177  			}
  1178  
  1179  			if c == '`' {
  1180  				break
  1181  			}
  1182  			cp.WriteRune(rune(c))
  1183  		}
  1184  
  1185  		goto strlit
  1186  
  1187  		// '.'
  1188  	case '\'':
  1189  		if escchar('\'', &escflag, &v) {
  1190  			Yyerror("empty character literal or unescaped ' in character literal")
  1191  			v = '\''
  1192  		}
  1193  
  1194  		if !escchar('\'', &escflag, &v) {
  1195  			Yyerror("missing '")
  1196  			ungetc(int(v))
  1197  		}
  1198  
  1199  		x := new(Mpint)
  1200  		yylval.val.U = x
  1201  		Mpmovecfix(x, v)
  1202  		x.Rune = true
  1203  		if Debug['x'] != 0 {
  1204  			fmt.Printf("lex: codepoint literal\n")
  1205  		}
  1206  		litbuf = "string literal"
  1207  		return LLITERAL
  1208  
  1209  	case '/':
  1210  		c1 = getc()
  1211  		if c1 == '*' {
  1212  			nl := false
  1213  			for {
  1214  				c = int(getr())
  1215  				if c == '\n' {
  1216  					nl = true
  1217  				}
  1218  				for c == '*' {
  1219  					c = int(getr())
  1220  					if c == '/' {
  1221  						if nl {
  1222  							ungetc('\n')
  1223  						}
  1224  						goto l0
  1225  					}
  1226  
  1227  					if c == '\n' {
  1228  						nl = true
  1229  					}
  1230  				}
  1231  
  1232  				if c == EOF {
  1233  					Yyerror("eof in comment")
  1234  					errorexit()
  1235  				}
  1236  			}
  1237  		}
  1238  
  1239  		if c1 == '/' {
  1240  			c = getlinepragma()
  1241  			for {
  1242  				if c == '\n' || c == EOF {
  1243  					ungetc(c)
  1244  					goto l0
  1245  				}
  1246  
  1247  				c = int(getr())
  1248  			}
  1249  		}
  1250  
  1251  		if c1 == '=' {
  1252  			op = ODIV
  1253  			goto asop
  1254  		}
  1255  
  1256  	case ':':
  1257  		c1 = getc()
  1258  		if c1 == '=' {
  1259  			c = int(LCOLAS)
  1260  			goto lx
  1261  		}
  1262  
  1263  	case '*':
  1264  		c1 = getc()
  1265  		if c1 == '=' {
  1266  			op = OMUL
  1267  			goto asop
  1268  		}
  1269  
  1270  	case '%':
  1271  		c1 = getc()
  1272  		if c1 == '=' {
  1273  			op = OMOD
  1274  			goto asop
  1275  		}
  1276  
  1277  	case '+':
  1278  		c1 = getc()
  1279  		if c1 == '+' {
  1280  			c = int(LINC)
  1281  			goto lx
  1282  		}
  1283  
  1284  		if c1 == '=' {
  1285  			op = OADD
  1286  			goto asop
  1287  		}
  1288  
  1289  	case '-':
  1290  		c1 = getc()
  1291  		if c1 == '-' {
  1292  			c = int(LDEC)
  1293  			goto lx
  1294  		}
  1295  
  1296  		if c1 == '=' {
  1297  			op = OSUB
  1298  			goto asop
  1299  		}
  1300  
  1301  	case '>':
  1302  		c1 = getc()
  1303  		if c1 == '>' {
  1304  			c = int(LRSH)
  1305  			c1 = getc()
  1306  			if c1 == '=' {
  1307  				op = ORSH
  1308  				goto asop
  1309  			}
  1310  
  1311  			break
  1312  		}
  1313  
  1314  		if c1 == '=' {
  1315  			c = int(LGE)
  1316  			goto lx
  1317  		}
  1318  
  1319  		c = int(LGT)
  1320  
  1321  	case '<':
  1322  		c1 = getc()
  1323  		if c1 == '<' {
  1324  			c = int(LLSH)
  1325  			c1 = getc()
  1326  			if c1 == '=' {
  1327  				op = OLSH
  1328  				goto asop
  1329  			}
  1330  
  1331  			break
  1332  		}
  1333  
  1334  		if c1 == '=' {
  1335  			c = int(LLE)
  1336  			goto lx
  1337  		}
  1338  
  1339  		if c1 == '-' {
  1340  			c = int(LCOMM)
  1341  			goto lx
  1342  		}
  1343  
  1344  		c = int(LLT)
  1345  
  1346  	case '=':
  1347  		c1 = getc()
  1348  		if c1 == '=' {
  1349  			c = int(LEQ)
  1350  			goto lx
  1351  		}
  1352  
  1353  	case '!':
  1354  		c1 = getc()
  1355  		if c1 == '=' {
  1356  			c = int(LNE)
  1357  			goto lx
  1358  		}
  1359  
  1360  	case '&':
  1361  		c1 = getc()
  1362  		if c1 == '&' {
  1363  			c = int(LANDAND)
  1364  			goto lx
  1365  		}
  1366  
  1367  		if c1 == '^' {
  1368  			c = int(LANDNOT)
  1369  			c1 = getc()
  1370  			if c1 == '=' {
  1371  				op = OANDNOT
  1372  				goto asop
  1373  			}
  1374  
  1375  			break
  1376  		}
  1377  
  1378  		if c1 == '=' {
  1379  			op = OAND
  1380  			goto asop
  1381  		}
  1382  
  1383  	case '|':
  1384  		c1 = getc()
  1385  		if c1 == '|' {
  1386  			c = int(LOROR)
  1387  			goto lx
  1388  		}
  1389  
  1390  		if c1 == '=' {
  1391  			op = OOR
  1392  			goto asop
  1393  		}
  1394  
  1395  	case '^':
  1396  		c1 = getc()
  1397  		if c1 == '=' {
  1398  			op = OXOR
  1399  			goto asop
  1400  		}
  1401  
  1402  	default:
  1403  		goto lx
  1404  	}
  1405  
  1406  	ungetc(c1)
  1407  
  1408  lx:
  1409  	if Debug['x'] != 0 {
  1410  		if c > 0xff {
  1411  			fmt.Printf("%v lex: TOKEN %s\n", Ctxt.Line(int(lexlineno)), lexname(c))
  1412  		} else {
  1413  			fmt.Printf("%v lex: TOKEN '%c'\n", Ctxt.Line(int(lexlineno)), c)
  1414  		}
  1415  	}
  1416  	if isfrog(c) {
  1417  		Yyerror("illegal character 0x%x", uint(c))
  1418  		goto l0
  1419  	}
  1420  
  1421  	if importpkg == nil && (c == '#' || c == '$' || c == '?' || c == '@' || c == '\\') {
  1422  		Yyerror("%s: unexpected %c", "syntax error", c)
  1423  		goto l0
  1424  	}
  1425  
  1426  	return int32(c)
  1427  
  1428  asop:
  1429  	yylval.op = op
  1430  	if Debug['x'] != 0 {
  1431  		fmt.Printf("lex: TOKEN ASOP %s=\n", goopnames[op])
  1432  	}
  1433  	return LASOP
  1434  
  1435  	// cp is set to lexbuf and some
  1436  	// prefix has been stored
  1437  talph:
  1438  	for {
  1439  		if c >= utf8.RuneSelf {
  1440  			ungetc(c)
  1441  			r := rune(getr())
  1442  
  1443  			// 0xb7 ยท is used for internal names
  1444  			if !unicode.IsLetter(r) && !unicode.IsDigit(r) && (importpkg == nil || r != 0xb7) {
  1445  				Yyerror("invalid identifier character U+%04x", r)
  1446  			}
  1447  			if cp.Len() == 0 && unicode.IsDigit(r) {
  1448  				Yyerror("identifier cannot begin with digit U+%04x", r)
  1449  			}
  1450  			cp.WriteRune(r)
  1451  		} else if !isAlnum(c) && c != '_' {
  1452  			break
  1453  		} else {
  1454  			cp.WriteByte(byte(c))
  1455  		}
  1456  		c = getc()
  1457  	}
  1458  
  1459  	cp = nil
  1460  	ungetc(c)
  1461  
  1462  	s = LookupBytes(lexbuf.Bytes())
  1463  	if s.Lexical == LIGNORE {
  1464  		goto l0
  1465  	}
  1466  
  1467  	if Debug['x'] != 0 {
  1468  		fmt.Printf("lex: %s %s\n", s, lexname(int(s.Lexical)))
  1469  	}
  1470  	yylval.sym = s
  1471  	return int32(s.Lexical)
  1472  
  1473  ncu:
  1474  	cp = nil
  1475  	ungetc(c)
  1476  
  1477  	str = lexbuf.String()
  1478  	yylval.val.U = new(Mpint)
  1479  	mpatofix(yylval.val.U.(*Mpint), str)
  1480  	if yylval.val.U.(*Mpint).Ovf {
  1481  		Yyerror("overflow in constant")
  1482  		Mpmovecfix(yylval.val.U.(*Mpint), 0)
  1483  	}
  1484  
  1485  	if Debug['x'] != 0 {
  1486  		fmt.Printf("lex: integer literal\n")
  1487  	}
  1488  	litbuf = "literal " + str
  1489  	return LLITERAL
  1490  
  1491  casedot:
  1492  	for {
  1493  		cp.WriteByte(byte(c))
  1494  		c = getc()
  1495  		if !isDigit(c) {
  1496  			break
  1497  		}
  1498  	}
  1499  
  1500  	if c == 'i' {
  1501  		goto casei
  1502  	}
  1503  	if c != 'e' && c != 'E' {
  1504  		goto caseout
  1505  	}
  1506  
  1507  caseep:
  1508  	if importpkg == nil && (c == 'p' || c == 'P') {
  1509  		// <mantissa>p<base-2-exponent> is allowed in .a/.o imports,
  1510  		// but not in .go sources.  See #9036.
  1511  		Yyerror("malformed floating point constant")
  1512  	}
  1513  	cp.WriteByte(byte(c))
  1514  	c = getc()
  1515  	if c == '+' || c == '-' {
  1516  		cp.WriteByte(byte(c))
  1517  		c = getc()
  1518  	}
  1519  
  1520  	if !isDigit(c) {
  1521  		Yyerror("malformed floating point constant exponent")
  1522  	}
  1523  	for isDigit(c) {
  1524  		cp.WriteByte(byte(c))
  1525  		c = getc()
  1526  	}
  1527  
  1528  	if c == 'i' {
  1529  		goto casei
  1530  	}
  1531  	goto caseout
  1532  
  1533  	// imaginary constant
  1534  casei:
  1535  	cp = nil
  1536  
  1537  	str = lexbuf.String()
  1538  	yylval.val.U = new(Mpcplx)
  1539  	Mpmovecflt(&yylval.val.U.(*Mpcplx).Real, 0.0)
  1540  	mpatoflt(&yylval.val.U.(*Mpcplx).Imag, str)
  1541  	if yylval.val.U.(*Mpcplx).Imag.Val.IsInf() {
  1542  		Yyerror("overflow in imaginary constant")
  1543  		Mpmovecflt(&yylval.val.U.(*Mpcplx).Imag, 0.0)
  1544  	}
  1545  
  1546  	if Debug['x'] != 0 {
  1547  		fmt.Printf("lex: imaginary literal\n")
  1548  	}
  1549  	litbuf = "literal " + str
  1550  	return LLITERAL
  1551  
  1552  caseout:
  1553  	cp = nil
  1554  	ungetc(c)
  1555  
  1556  	str = lexbuf.String()
  1557  	yylval.val.U = newMpflt()
  1558  	mpatoflt(yylval.val.U.(*Mpflt), str)
  1559  	if yylval.val.U.(*Mpflt).Val.IsInf() {
  1560  		Yyerror("overflow in float constant")
  1561  		Mpmovecflt(yylval.val.U.(*Mpflt), 0.0)
  1562  	}
  1563  
  1564  	if Debug['x'] != 0 {
  1565  		fmt.Printf("lex: floating literal\n")
  1566  	}
  1567  	litbuf = "literal " + str
  1568  	return LLITERAL
  1569  
  1570  strlit:
  1571  	yylval.val.U = internString(cp.Bytes())
  1572  	if Debug['x'] != 0 {
  1573  		fmt.Printf("lex: string literal\n")
  1574  	}
  1575  	litbuf = "string literal"
  1576  	return LLITERAL
  1577  }
  1578  
  1579  var internedStrings = map[string]string{}
  1580  
  1581  func internString(b []byte) string {
  1582  	s, ok := internedStrings[string(b)] // string(b) here doesn't allocate
  1583  	if ok {
  1584  		return s
  1585  	}
  1586  	s = string(b)
  1587  	internedStrings[s] = s
  1588  	return s
  1589  }
  1590  
  1591  func more(pp *string) bool {
  1592  	p := *pp
  1593  	for p != "" && isSpace(int(p[0])) {
  1594  		p = p[1:]
  1595  	}
  1596  	*pp = p
  1597  	return p != ""
  1598  }
  1599  
  1600  // read and interpret syntax that looks like
  1601  // //line parse.y:15
  1602  // as a discontinuity in sequential line numbers.
  1603  // the next line of input comes from parse.y:15
  1604  func getlinepragma() int {
  1605  	var cmd, verb, name string
  1606  
  1607  	c := int(getr())
  1608  	if c == 'g' {
  1609  		cp := &lexbuf
  1610  		cp.Reset()
  1611  		cp.WriteByte('g') // already read
  1612  		for {
  1613  			c = int(getr())
  1614  			if c == EOF || c >= utf8.RuneSelf {
  1615  				return c
  1616  			}
  1617  			if c == '\n' {
  1618  				break
  1619  			}
  1620  			cp.WriteByte(byte(c))
  1621  		}
  1622  		cp = nil
  1623  
  1624  		text := strings.TrimSuffix(lexbuf.String(), "\r")
  1625  
  1626  		if strings.HasPrefix(text, "go:cgo_") {
  1627  			pragcgo(text)
  1628  		}
  1629  
  1630  		cmd = text
  1631  		verb = cmd
  1632  		if i := strings.Index(verb, " "); i >= 0 {
  1633  			verb = verb[:i]
  1634  		}
  1635  
  1636  		if verb == "go:linkname" {
  1637  			if !imported_unsafe {
  1638  				Yyerror("//go:linkname only allowed in Go files that import \"unsafe\"")
  1639  			}
  1640  			f := strings.Fields(cmd)
  1641  			if len(f) != 3 {
  1642  				Yyerror("usage: //go:linkname localname linkname")
  1643  				return c
  1644  			}
  1645  
  1646  			Lookup(f[1]).Linkname = f[2]
  1647  			return c
  1648  		}
  1649  
  1650  		if verb == "go:nointerface" && obj.Fieldtrack_enabled != 0 {
  1651  			nointerface = true
  1652  			return c
  1653  		}
  1654  
  1655  		if verb == "go:noescape" {
  1656  			noescape = true
  1657  			return c
  1658  		}
  1659  
  1660  		if verb == "go:norace" {
  1661  			norace = true
  1662  			return c
  1663  		}
  1664  
  1665  		if verb == "go:nosplit" {
  1666  			nosplit = true
  1667  			return c
  1668  		}
  1669  
  1670  		if verb == "go:noinline" {
  1671  			noinline = true
  1672  			return c
  1673  		}
  1674  
  1675  		if verb == "go:systemstack" {
  1676  			if compiling_runtime == 0 {
  1677  				Yyerror("//go:systemstack only allowed in runtime")
  1678  			}
  1679  			systemstack = true
  1680  			return c
  1681  		}
  1682  
  1683  		if verb == "go:nowritebarrier" {
  1684  			if compiling_runtime == 0 {
  1685  				Yyerror("//go:nowritebarrier only allowed in runtime")
  1686  			}
  1687  			nowritebarrier = true
  1688  			return c
  1689  		}
  1690  
  1691  		if verb == "go:nowritebarrierrec" {
  1692  			if compiling_runtime == 0 {
  1693  				Yyerror("//go:nowritebarrierrec only allowed in runtime")
  1694  			}
  1695  			nowritebarrierrec = true
  1696  			nowritebarrier = true // Implies nowritebarrier
  1697  			return c
  1698  		}
  1699  		return c
  1700  	}
  1701  	if c != 'l' {
  1702  		return c
  1703  	}
  1704  	for i := 1; i < 5; i++ {
  1705  		c = int(getr())
  1706  		if c != int("line "[i]) {
  1707  			return c
  1708  		}
  1709  	}
  1710  
  1711  	cp := &lexbuf
  1712  	cp.Reset()
  1713  	linep := 0
  1714  	for {
  1715  		c = int(getr())
  1716  		if c == EOF {
  1717  			return c
  1718  		}
  1719  		if c == '\n' {
  1720  			break
  1721  		}
  1722  		if c == ' ' {
  1723  			continue
  1724  		}
  1725  		if c == ':' {
  1726  			linep = cp.Len() + 1
  1727  		}
  1728  		cp.WriteByte(byte(c))
  1729  	}
  1730  
  1731  	cp = nil
  1732  
  1733  	if linep == 0 {
  1734  		return c
  1735  	}
  1736  	text := strings.TrimSuffix(lexbuf.String(), "\r")
  1737  	n := 0
  1738  	for _, c := range text[linep:] {
  1739  		if c < '0' || c > '9' {
  1740  			goto out
  1741  		}
  1742  		n = n*10 + int(c) - '0'
  1743  		if n > 1e8 {
  1744  			Yyerror("line number out of range")
  1745  			errorexit()
  1746  		}
  1747  	}
  1748  
  1749  	if n <= 0 {
  1750  		return c
  1751  	}
  1752  
  1753  	name = text[:linep-1]
  1754  	linehistupdate(name, n)
  1755  	return c
  1756  
  1757  out:
  1758  	return c
  1759  }
  1760  
  1761  func getimpsym(pp *string) string {
  1762  	more(pp) // skip spaces
  1763  	p := *pp
  1764  	if p == "" || p[0] == '"' {
  1765  		return ""
  1766  	}
  1767  	i := 0
  1768  	for i < len(p) && !isSpace(int(p[i])) && p[i] != '"' {
  1769  		i++
  1770  	}
  1771  	sym := p[:i]
  1772  	*pp = p[i:]
  1773  	return sym
  1774  }
  1775  
  1776  func getquoted(pp *string) (string, bool) {
  1777  	more(pp) // skip spaces
  1778  	p := *pp
  1779  	if p == "" || p[0] != '"' {
  1780  		return "", false
  1781  	}
  1782  	p = p[1:]
  1783  	i := strings.Index(p, `"`)
  1784  	if i < 0 {
  1785  		return "", false
  1786  	}
  1787  	*pp = p[i+1:]
  1788  	return p[:i], true
  1789  }
  1790  
  1791  // Copied nearly verbatim from the C compiler's #pragma parser.
  1792  // TODO: Rewrite more cleanly once the compiler is written in Go.
  1793  func pragcgo(text string) {
  1794  	var q string
  1795  
  1796  	if i := strings.Index(text, " "); i >= 0 {
  1797  		text, q = text[:i], text[i:]
  1798  	}
  1799  
  1800  	verb := text[3:] // skip "go:"
  1801  
  1802  	if verb == "cgo_dynamic_linker" || verb == "dynlinker" {
  1803  		p, ok := getquoted(&q)
  1804  		if !ok {
  1805  			Yyerror("usage: //go:cgo_dynamic_linker \"path\"")
  1806  			return
  1807  		}
  1808  		pragcgobuf += fmt.Sprintf("cgo_dynamic_linker %v\n", plan9quote(p))
  1809  		return
  1810  
  1811  	}
  1812  
  1813  	if verb == "dynexport" {
  1814  		verb = "cgo_export_dynamic"
  1815  	}
  1816  	if verb == "cgo_export_static" || verb == "cgo_export_dynamic" {
  1817  		local := getimpsym(&q)
  1818  		var remote string
  1819  		if local == "" {
  1820  			goto err2
  1821  		}
  1822  		if !more(&q) {
  1823  			pragcgobuf += fmt.Sprintf("%s %v\n", verb, plan9quote(local))
  1824  			return
  1825  		}
  1826  
  1827  		remote = getimpsym(&q)
  1828  		if remote == "" {
  1829  			goto err2
  1830  		}
  1831  		pragcgobuf += fmt.Sprintf("%s %v %v\n", verb, plan9quote(local), plan9quote(remote))
  1832  		return
  1833  
  1834  	err2:
  1835  		Yyerror("usage: //go:%s local [remote]", verb)
  1836  		return
  1837  	}
  1838  
  1839  	if verb == "cgo_import_dynamic" || verb == "dynimport" {
  1840  		var ok bool
  1841  		local := getimpsym(&q)
  1842  		var p string
  1843  		var remote string
  1844  		if local == "" {
  1845  			goto err3
  1846  		}
  1847  		if !more(&q) {
  1848  			pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v\n", plan9quote(local))
  1849  			return
  1850  		}
  1851  
  1852  		remote = getimpsym(&q)
  1853  		if remote == "" {
  1854  			goto err3
  1855  		}
  1856  		if !more(&q) {
  1857  			pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v\n", plan9quote(local), plan9quote(remote))
  1858  			return
  1859  		}
  1860  
  1861  		p, ok = getquoted(&q)
  1862  		if !ok {
  1863  			goto err3
  1864  		}
  1865  		pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v %v\n", plan9quote(local), plan9quote(remote), plan9quote(p))
  1866  		return
  1867  
  1868  	err3:
  1869  		Yyerror("usage: //go:cgo_import_dynamic local [remote [\"library\"]]")
  1870  		return
  1871  	}
  1872  
  1873  	if verb == "cgo_import_static" {
  1874  		local := getimpsym(&q)
  1875  		if local == "" || more(&q) {
  1876  			Yyerror("usage: //go:cgo_import_static local")
  1877  			return
  1878  		}
  1879  		pragcgobuf += fmt.Sprintf("cgo_import_static %v\n", plan9quote(local))
  1880  		return
  1881  
  1882  	}
  1883  
  1884  	if verb == "cgo_ldflag" {
  1885  		p, ok := getquoted(&q)
  1886  		if !ok {
  1887  			Yyerror("usage: //go:cgo_ldflag \"arg\"")
  1888  			return
  1889  		}
  1890  		pragcgobuf += fmt.Sprintf("cgo_ldflag %v\n", plan9quote(p))
  1891  		return
  1892  
  1893  	}
  1894  }
  1895  
  1896  func yylex(yylval *yySymType) int32 {
  1897  	lx := _yylex(yylval)
  1898  
  1899  	if curio.nlsemi && lx == EOF {
  1900  		// Treat EOF as "end of line" for the purposes
  1901  		// of inserting a semicolon.
  1902  		lx = ';'
  1903  	}
  1904  
  1905  	switch lx {
  1906  	case LNAME,
  1907  		LLITERAL,
  1908  		LBREAK,
  1909  		LCONTINUE,
  1910  		LFALL,
  1911  		LRETURN,
  1912  		LINC,
  1913  		LDEC,
  1914  		')',
  1915  		'}',
  1916  		']':
  1917  		curio.nlsemi = true
  1918  
  1919  	default:
  1920  		curio.nlsemi = false
  1921  	}
  1922  
  1923  	return lx
  1924  }
  1925  
  1926  func getc() int {
  1927  	c := curio.peekc
  1928  	if c != 0 {
  1929  		curio.peekc = curio.peekc1
  1930  		curio.peekc1 = 0
  1931  		goto check
  1932  	}
  1933  
  1934  	if curio.bin == nil {
  1935  		if len(curio.cp) == 0 {
  1936  			c = 0
  1937  		} else {
  1938  			c = int(curio.cp[0])
  1939  			curio.cp = curio.cp[1:]
  1940  		}
  1941  	} else {
  1942  	loop:
  1943  		c = obj.Bgetc(curio.bin)
  1944  		// recognize BOM (U+FEFF): UTF-8 encoding is 0xef 0xbb 0xbf
  1945  		if c == 0xef {
  1946  			buf, err := curio.bin.Peek(2)
  1947  			if err != nil {
  1948  				yyerrorl(int(lexlineno), "illegal UTF-8 sequence ef % x followed by read error (%v)", string(buf), err)
  1949  				errorexit()
  1950  			}
  1951  			if buf[0] == 0xbb && buf[1] == 0xbf {
  1952  				yyerrorl(int(lexlineno), "Unicode (UTF-8) BOM in middle of file")
  1953  
  1954  				// consume BOM bytes
  1955  				obj.Bgetc(curio.bin)
  1956  				obj.Bgetc(curio.bin)
  1957  				goto loop
  1958  			}
  1959  		}
  1960  	}
  1961  
  1962  check:
  1963  	switch c {
  1964  	case 0:
  1965  		if curio.bin != nil {
  1966  			Yyerror("illegal NUL byte")
  1967  			break
  1968  		}
  1969  		fallthrough
  1970  
  1971  		// insert \n at EOF
  1972  	case EOF:
  1973  		if curio.eofnl || curio.last == '\n' {
  1974  			return EOF
  1975  		}
  1976  		curio.eofnl = true
  1977  		c = '\n'
  1978  		fallthrough
  1979  
  1980  	case '\n':
  1981  		if pushedio.bin == nil {
  1982  			lexlineno++
  1983  		}
  1984  	}
  1985  
  1986  	curio.last = c
  1987  	return c
  1988  }
  1989  
  1990  func ungetc(c int) {
  1991  	curio.peekc1 = curio.peekc
  1992  	curio.peekc = c
  1993  	if c == '\n' && pushedio.bin == nil {
  1994  		lexlineno--
  1995  	}
  1996  }
  1997  
  1998  func getr() int32 {
  1999  	var buf [utf8.UTFMax]byte
  2000  
  2001  	for i := 0; ; i++ {
  2002  		c := getc()
  2003  		if i == 0 && c < utf8.RuneSelf {
  2004  			return int32(c)
  2005  		}
  2006  		buf[i] = byte(c)
  2007  		if i+1 == len(buf) || utf8.FullRune(buf[:i+1]) {
  2008  			r, w := utf8.DecodeRune(buf[:i+1])
  2009  			if r == utf8.RuneError && w == 1 {
  2010  				lineno = lexlineno
  2011  				// The string conversion here makes a copy for passing
  2012  				// to fmt.Printf, so that buf itself does not escape and can
  2013  				// be allocated on the stack.
  2014  				Yyerror("illegal UTF-8 sequence % x", string(buf[:i+1]))
  2015  			}
  2016  			return int32(r)
  2017  		}
  2018  	}
  2019  }
  2020  
  2021  func escchar(e int, escflg *int, val *int64) bool {
  2022  	*escflg = 0
  2023  
  2024  	c := int(getr())
  2025  	switch c {
  2026  	case EOF:
  2027  		Yyerror("eof in string")
  2028  		return true
  2029  
  2030  	case '\n':
  2031  		Yyerror("newline in string")
  2032  		return true
  2033  
  2034  	case '\\':
  2035  		break
  2036  
  2037  	default:
  2038  		if c == e {
  2039  			return true
  2040  		}
  2041  		*val = int64(c)
  2042  		return false
  2043  	}
  2044  
  2045  	u := 0
  2046  	c = int(getr())
  2047  	var i int
  2048  	switch c {
  2049  	case 'x':
  2050  		*escflg = 1 // it's a byte
  2051  		i = 2
  2052  		goto hex
  2053  
  2054  	case 'u':
  2055  		i = 4
  2056  		u = 1
  2057  		goto hex
  2058  
  2059  	case 'U':
  2060  		i = 8
  2061  		u = 1
  2062  		goto hex
  2063  
  2064  	case '0',
  2065  		'1',
  2066  		'2',
  2067  		'3',
  2068  		'4',
  2069  		'5',
  2070  		'6',
  2071  		'7':
  2072  		*escflg = 1 // it's a byte
  2073  		l := int64(c) - '0'
  2074  		for i := 2; i > 0; i-- {
  2075  			c = getc()
  2076  			if c >= '0' && c <= '7' {
  2077  				l = l*8 + int64(c) - '0'
  2078  				continue
  2079  			}
  2080  
  2081  			Yyerror("non-octal character in escape sequence: %c", c)
  2082  			ungetc(c)
  2083  		}
  2084  
  2085  		if l > 255 {
  2086  			Yyerror("octal escape value > 255: %d", l)
  2087  		}
  2088  
  2089  		*val = l
  2090  		return false
  2091  
  2092  	case 'a':
  2093  		c = '\a'
  2094  	case 'b':
  2095  		c = '\b'
  2096  	case 'f':
  2097  		c = '\f'
  2098  	case 'n':
  2099  		c = '\n'
  2100  	case 'r':
  2101  		c = '\r'
  2102  	case 't':
  2103  		c = '\t'
  2104  	case 'v':
  2105  		c = '\v'
  2106  	case '\\':
  2107  		c = '\\'
  2108  
  2109  	default:
  2110  		if c != e {
  2111  			Yyerror("unknown escape sequence: %c", c)
  2112  		}
  2113  	}
  2114  
  2115  	*val = int64(c)
  2116  	return false
  2117  
  2118  hex:
  2119  	l := int64(0)
  2120  	for ; i > 0; i-- {
  2121  		c = getc()
  2122  		if c >= '0' && c <= '9' {
  2123  			l = l*16 + int64(c) - '0'
  2124  			continue
  2125  		}
  2126  
  2127  		if c >= 'a' && c <= 'f' {
  2128  			l = l*16 + int64(c) - 'a' + 10
  2129  			continue
  2130  		}
  2131  
  2132  		if c >= 'A' && c <= 'F' {
  2133  			l = l*16 + int64(c) - 'A' + 10
  2134  			continue
  2135  		}
  2136  
  2137  		Yyerror("non-hex character in escape sequence: %c", c)
  2138  		ungetc(c)
  2139  		break
  2140  	}
  2141  
  2142  	if u != 0 && (l > utf8.MaxRune || (0xd800 <= l && l < 0xe000)) {
  2143  		Yyerror("invalid Unicode code point in escape sequence: %#x", l)
  2144  		l = utf8.RuneError
  2145  	}
  2146  
  2147  	*val = l
  2148  	return false
  2149  }
  2150  
  2151  var syms = []struct {
  2152  	name    string
  2153  	lexical int
  2154  	etype   EType
  2155  	op      Op
  2156  }{
  2157  	// basic types
  2158  	{"int8", LNAME, TINT8, OXXX},
  2159  	{"int16", LNAME, TINT16, OXXX},
  2160  	{"int32", LNAME, TINT32, OXXX},
  2161  	{"int64", LNAME, TINT64, OXXX},
  2162  	{"uint8", LNAME, TUINT8, OXXX},
  2163  	{"uint16", LNAME, TUINT16, OXXX},
  2164  	{"uint32", LNAME, TUINT32, OXXX},
  2165  	{"uint64", LNAME, TUINT64, OXXX},
  2166  	{"float32", LNAME, TFLOAT32, OXXX},
  2167  	{"float64", LNAME, TFLOAT64, OXXX},
  2168  	{"complex64", LNAME, TCOMPLEX64, OXXX},
  2169  	{"complex128", LNAME, TCOMPLEX128, OXXX},
  2170  	{"bool", LNAME, TBOOL, OXXX},
  2171  	{"string", LNAME, TSTRING, OXXX},
  2172  	{"any", LNAME, TANY, OXXX},
  2173  	{"break", LBREAK, Txxx, OXXX},
  2174  	{"case", LCASE, Txxx, OXXX},
  2175  	{"chan", LCHAN, Txxx, OXXX},
  2176  	{"const", LCONST, Txxx, OXXX},
  2177  	{"continue", LCONTINUE, Txxx, OXXX},
  2178  	{"default", LDEFAULT, Txxx, OXXX},
  2179  	{"else", LELSE, Txxx, OXXX},
  2180  	{"defer", LDEFER, Txxx, OXXX},
  2181  	{"fallthrough", LFALL, Txxx, OXXX},
  2182  	{"for", LFOR, Txxx, OXXX},
  2183  	{"func", LFUNC, Txxx, OXXX},
  2184  	{"go", LGO, Txxx, OXXX},
  2185  	{"goto", LGOTO, Txxx, OXXX},
  2186  	{"if", LIF, Txxx, OXXX},
  2187  	{"import", LIMPORT, Txxx, OXXX},
  2188  	{"interface", LINTERFACE, Txxx, OXXX},
  2189  	{"map", LMAP, Txxx, OXXX},
  2190  	{"package", LPACKAGE, Txxx, OXXX},
  2191  	{"range", LRANGE, Txxx, OXXX},
  2192  	{"return", LRETURN, Txxx, OXXX},
  2193  	{"select", LSELECT, Txxx, OXXX},
  2194  	{"struct", LSTRUCT, Txxx, OXXX},
  2195  	{"switch", LSWITCH, Txxx, OXXX},
  2196  	{"type", LTYPE, Txxx, OXXX},
  2197  	{"var", LVAR, Txxx, OXXX},
  2198  	{"append", LNAME, Txxx, OAPPEND},
  2199  	{"cap", LNAME, Txxx, OCAP},
  2200  	{"close", LNAME, Txxx, OCLOSE},
  2201  	{"complex", LNAME, Txxx, OCOMPLEX},
  2202  	{"copy", LNAME, Txxx, OCOPY},
  2203  	{"delete", LNAME, Txxx, ODELETE},
  2204  	{"imag", LNAME, Txxx, OIMAG},
  2205  	{"len", LNAME, Txxx, OLEN},
  2206  	{"make", LNAME, Txxx, OMAKE},
  2207  	{"new", LNAME, Txxx, ONEW},
  2208  	{"panic", LNAME, Txxx, OPANIC},
  2209  	{"print", LNAME, Txxx, OPRINT},
  2210  	{"println", LNAME, Txxx, OPRINTN},
  2211  	{"real", LNAME, Txxx, OREAL},
  2212  	{"recover", LNAME, Txxx, ORECOVER},
  2213  	{"notwithstanding", LIGNORE, Txxx, OXXX},
  2214  	{"thetruthofthematter", LIGNORE, Txxx, OXXX},
  2215  	{"despiteallobjections", LIGNORE, Txxx, OXXX},
  2216  	{"whereas", LIGNORE, Txxx, OXXX},
  2217  	{"insofaras", LIGNORE, Txxx, OXXX},
  2218  }
  2219  
  2220  // lexinit initializes known symbols and the basic types.
  2221  func lexinit() {
  2222  	for _, s := range syms {
  2223  		lex := s.lexical
  2224  		s1 := Lookup(s.name)
  2225  		s1.Lexical = uint16(lex)
  2226  
  2227  		if etype := s.etype; etype != Txxx {
  2228  			if int(etype) >= len(Types) {
  2229  				Fatalf("lexinit: %s bad etype", s.name)
  2230  			}
  2231  			s2 := Pkglookup(s.name, builtinpkg)
  2232  			t := Types[etype]
  2233  			if t == nil {
  2234  				t = typ(etype)
  2235  				t.Sym = s2
  2236  
  2237  				if etype != TANY && etype != TSTRING {
  2238  					dowidth(t)
  2239  				}
  2240  				Types[etype] = t
  2241  			}
  2242  
  2243  			s2.Lexical = LNAME
  2244  			s2.Def = typenod(t)
  2245  			s2.Def.Name = new(Name)
  2246  			continue
  2247  		}
  2248  
  2249  		// TODO(marvin): Fix Node.EType type union.
  2250  		if etype := s.op; etype != OXXX {
  2251  			s2 := Pkglookup(s.name, builtinpkg)
  2252  			s2.Lexical = LNAME
  2253  			s2.Def = Nod(ONAME, nil, nil)
  2254  			s2.Def.Sym = s2
  2255  			s2.Def.Etype = EType(etype)
  2256  		}
  2257  	}
  2258  
  2259  	// logically, the type of a string literal.
  2260  	// types[TSTRING] is the named type string
  2261  	// (the type of x in var x string or var x = "hello").
  2262  	// this is the ideal form
  2263  	// (the type of x in const x = "hello").
  2264  	idealstring = typ(TSTRING)
  2265  
  2266  	idealbool = typ(TBOOL)
  2267  
  2268  	s := Pkglookup("true", builtinpkg)
  2269  	s.Def = Nodbool(true)
  2270  	s.Def.Sym = Lookup("true")
  2271  	s.Def.Name = new(Name)
  2272  	s.Def.Type = idealbool
  2273  
  2274  	s = Pkglookup("false", builtinpkg)
  2275  	s.Def = Nodbool(false)
  2276  	s.Def.Sym = Lookup("false")
  2277  	s.Def.Name = new(Name)
  2278  	s.Def.Type = idealbool
  2279  
  2280  	s = Lookup("_")
  2281  	s.Block = -100
  2282  	s.Def = Nod(ONAME, nil, nil)
  2283  	s.Def.Sym = s
  2284  	Types[TBLANK] = typ(TBLANK)
  2285  	s.Def.Type = Types[TBLANK]
  2286  	nblank = s.Def
  2287  
  2288  	s = Pkglookup("_", builtinpkg)
  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  
  2295  	Types[TNIL] = typ(TNIL)
  2296  	s = Pkglookup("nil", builtinpkg)
  2297  	var v Val
  2298  	v.U = new(NilVal)
  2299  	s.Def = nodlit(v)
  2300  	s.Def.Sym = s
  2301  	s.Def.Name = new(Name)
  2302  }
  2303  
  2304  func lexinit1() {
  2305  	// t = interface { Error() string }
  2306  	rcvr := typ(TSTRUCT)
  2307  
  2308  	rcvr.Type = typ(TFIELD)
  2309  	rcvr.Type.Type = Ptrto(typ(TSTRUCT))
  2310  	rcvr.Funarg = true
  2311  	in := typ(TSTRUCT)
  2312  	in.Funarg = true
  2313  	out := typ(TSTRUCT)
  2314  	out.Type = typ(TFIELD)
  2315  	out.Type.Type = Types[TSTRING]
  2316  	out.Funarg = true
  2317  	f := typ(TFUNC)
  2318  	*getthis(f) = rcvr
  2319  	*Getoutarg(f) = out
  2320  	*getinarg(f) = in
  2321  	f.Thistuple = 1
  2322  	f.Intuple = 0
  2323  	f.Outnamed = false
  2324  	f.Outtuple = 1
  2325  	t := typ(TINTER)
  2326  	t.Type = typ(TFIELD)
  2327  	t.Type.Sym = Lookup("Error")
  2328  	t.Type.Type = f
  2329  
  2330  	// error type
  2331  	s := Lookup("error")
  2332  
  2333  	s.Lexical = LNAME
  2334  	s1 := Pkglookup("error", builtinpkg)
  2335  	errortype = t
  2336  	errortype.Sym = s1
  2337  	s1.Lexical = LNAME
  2338  	s1.Def = typenod(errortype)
  2339  
  2340  	// byte alias
  2341  	s = Lookup("byte")
  2342  
  2343  	s.Lexical = LNAME
  2344  	s1 = Pkglookup("byte", builtinpkg)
  2345  	bytetype = typ(TUINT8)
  2346  	bytetype.Sym = s1
  2347  	s1.Lexical = LNAME
  2348  	s1.Def = typenod(bytetype)
  2349  	s1.Def.Name = new(Name)
  2350  
  2351  	// rune alias
  2352  	s = Lookup("rune")
  2353  
  2354  	s.Lexical = LNAME
  2355  	s1 = Pkglookup("rune", builtinpkg)
  2356  	runetype = typ(TINT32)
  2357  	runetype.Sym = s1
  2358  	s1.Lexical = LNAME
  2359  	s1.Def = typenod(runetype)
  2360  	s1.Def.Name = new(Name)
  2361  }
  2362  
  2363  func lexfini() {
  2364  	for i := range syms {
  2365  		lex := syms[i].lexical
  2366  		if lex != LNAME {
  2367  			continue
  2368  		}
  2369  		s := Lookup(syms[i].name)
  2370  		s.Lexical = uint16(lex)
  2371  
  2372  		etype := syms[i].etype
  2373  		if etype != Txxx && (etype != TANY || Debug['A'] != 0) && s.Def == nil {
  2374  			s.Def = typenod(Types[etype])
  2375  			s.Def.Name = new(Name)
  2376  			s.Origpkg = builtinpkg
  2377  		}
  2378  
  2379  		// TODO(marvin): Fix Node.EType type union.
  2380  		etype = EType(syms[i].op)
  2381  		if etype != EType(OXXX) && s.Def == nil {
  2382  			s.Def = Nod(ONAME, nil, nil)
  2383  			s.Def.Sym = s
  2384  			s.Def.Etype = etype
  2385  			s.Origpkg = builtinpkg
  2386  		}
  2387  	}
  2388  
  2389  	// backend-specific builtin types (e.g. int).
  2390  	for i := range Thearch.Typedefs {
  2391  		s := Lookup(Thearch.Typedefs[i].Name)
  2392  		if s.Def == nil {
  2393  			s.Def = typenod(Types[Thearch.Typedefs[i].Etype])
  2394  			s.Def.Name = new(Name)
  2395  			s.Origpkg = builtinpkg
  2396  		}
  2397  	}
  2398  
  2399  	// there's only so much table-driven we can handle.
  2400  	// these are special cases.
  2401  	if s := Lookup("byte"); s.Def == nil {
  2402  		s.Def = typenod(bytetype)
  2403  		s.Def.Name = new(Name)
  2404  		s.Origpkg = builtinpkg
  2405  	}
  2406  
  2407  	if s := Lookup("error"); s.Def == nil {
  2408  		s.Def = typenod(errortype)
  2409  		s.Def.Name = new(Name)
  2410  		s.Origpkg = builtinpkg
  2411  	}
  2412  
  2413  	if s := Lookup("rune"); s.Def == nil {
  2414  		s.Def = typenod(runetype)
  2415  		s.Def.Name = new(Name)
  2416  		s.Origpkg = builtinpkg
  2417  	}
  2418  
  2419  	if s := Lookup("nil"); s.Def == nil {
  2420  		var v Val
  2421  		v.U = new(NilVal)
  2422  		s.Def = nodlit(v)
  2423  		s.Def.Sym = s
  2424  		s.Def.Name = new(Name)
  2425  		s.Origpkg = builtinpkg
  2426  	}
  2427  
  2428  	if s := Lookup("iota"); s.Def == nil {
  2429  		s.Def = Nod(OIOTA, nil, nil)
  2430  		s.Def.Sym = s
  2431  		s.Origpkg = builtinpkg
  2432  	}
  2433  
  2434  	if s := Lookup("true"); s.Def == nil {
  2435  		s.Def = Nodbool(true)
  2436  		s.Def.Sym = s
  2437  		s.Def.Name = new(Name)
  2438  		s.Origpkg = builtinpkg
  2439  	}
  2440  
  2441  	if s := Lookup("false"); s.Def == nil {
  2442  		s.Def = Nodbool(false)
  2443  		s.Def.Sym = s
  2444  		s.Def.Name = new(Name)
  2445  		s.Origpkg = builtinpkg
  2446  	}
  2447  
  2448  	nodfp = Nod(ONAME, nil, nil)
  2449  	nodfp.Type = Types[TINT32]
  2450  	nodfp.Xoffset = 0
  2451  	nodfp.Class = PPARAM
  2452  	nodfp.Sym = Lookup(".fp")
  2453  }
  2454  
  2455  var lexn = map[int]string{
  2456  	LANDAND:    "ANDAND",
  2457  	LANDNOT:    "ANDNOT",
  2458  	LASOP:      "ASOP",
  2459  	LBREAK:     "BREAK",
  2460  	LCASE:      "CASE",
  2461  	LCHAN:      "CHAN",
  2462  	LCOLAS:     "COLAS",
  2463  	LCOMM:      "<-",
  2464  	LCONST:     "CONST",
  2465  	LCONTINUE:  "CONTINUE",
  2466  	LDDD:       "...",
  2467  	LDEC:       "DEC",
  2468  	LDEFAULT:   "DEFAULT",
  2469  	LDEFER:     "DEFER",
  2470  	LELSE:      "ELSE",
  2471  	LEQ:        "EQ",
  2472  	LFALL:      "FALL",
  2473  	LFOR:       "FOR",
  2474  	LFUNC:      "FUNC",
  2475  	LGE:        "GE",
  2476  	LGO:        "GO",
  2477  	LGOTO:      "GOTO",
  2478  	LGT:        "GT",
  2479  	LIF:        "IF",
  2480  	LIMPORT:    "IMPORT",
  2481  	LINC:       "INC",
  2482  	LINTERFACE: "INTERFACE",
  2483  	LLE:        "LE",
  2484  	LLITERAL:   "LITERAL",
  2485  	LLSH:       "LSH",
  2486  	LLT:        "LT",
  2487  	LMAP:       "MAP",
  2488  	LNAME:      "NAME",
  2489  	LNE:        "NE",
  2490  	LOROR:      "OROR",
  2491  	LPACKAGE:   "PACKAGE",
  2492  	LRANGE:     "RANGE",
  2493  	LRETURN:    "RETURN",
  2494  	LRSH:       "RSH",
  2495  	LSELECT:    "SELECT",
  2496  	LSTRUCT:    "STRUCT",
  2497  	LSWITCH:    "SWITCH",
  2498  	LTYPE:      "TYPE",
  2499  	LVAR:       "VAR",
  2500  }
  2501  
  2502  func lexname(lex int) string {
  2503  	if s, ok := lexn[lex]; ok {
  2504  		return s
  2505  	}
  2506  	return fmt.Sprintf("LEX-%d", lex)
  2507  }
  2508  
  2509  func pkgnotused(lineno int, path string, name string) {
  2510  	// If the package was imported with a name other than the final
  2511  	// import path element, show it explicitly in the error message.
  2512  	// Note that this handles both renamed imports and imports of
  2513  	// packages containing unconventional package declarations.
  2514  	// Note that this uses / always, even on Windows, because Go import
  2515  	// paths always use forward slashes.
  2516  	elem := path
  2517  	if i := strings.LastIndex(elem, "/"); i >= 0 {
  2518  		elem = elem[i+1:]
  2519  	}
  2520  	if name == "" || elem == name {
  2521  		yyerrorl(int(lineno), "imported and not used: %q", path)
  2522  	} else {
  2523  		yyerrorl(int(lineno), "imported and not used: %q as %s", path, name)
  2524  	}
  2525  }
  2526  
  2527  func mkpackage(pkgname string) {
  2528  	if localpkg.Name == "" {
  2529  		if pkgname == "_" {
  2530  			Yyerror("invalid package name _")
  2531  		}
  2532  		localpkg.Name = pkgname
  2533  	} else {
  2534  		if pkgname != localpkg.Name {
  2535  			Yyerror("package %s; expected %s", pkgname, localpkg.Name)
  2536  		}
  2537  		for _, s := range localpkg.Syms {
  2538  			if s.Def == nil {
  2539  				continue
  2540  			}
  2541  			if s.Def.Op == OPACK {
  2542  				// throw away top-level package name leftover
  2543  				// from previous file.
  2544  				// leave s->block set to cause redeclaration
  2545  				// errors if a conflicting top-level name is
  2546  				// introduced by a different file.
  2547  				if !s.Def.Used && nsyntaxerrors == 0 {
  2548  					pkgnotused(int(s.Def.Lineno), s.Def.Name.Pkg.Path, s.Name)
  2549  				}
  2550  				s.Def = nil
  2551  				continue
  2552  			}
  2553  
  2554  			if s.Def.Sym != s {
  2555  				// throw away top-level name left over
  2556  				// from previous import . "x"
  2557  				if s.Def.Name != nil && s.Def.Name.Pack != nil && !s.Def.Name.Pack.Used && nsyntaxerrors == 0 {
  2558  					pkgnotused(int(s.Def.Name.Pack.Lineno), s.Def.Name.Pack.Name.Pkg.Path, "")
  2559  					s.Def.Name.Pack.Used = true
  2560  				}
  2561  
  2562  				s.Def = nil
  2563  				continue
  2564  			}
  2565  		}
  2566  	}
  2567  
  2568  	if outfile == "" {
  2569  		p := infile
  2570  		if i := strings.LastIndex(p, "/"); i >= 0 {
  2571  			p = p[i+1:]
  2572  		}
  2573  		if Ctxt.Windows != 0 {
  2574  			if i := strings.LastIndex(p, `\`); i >= 0 {
  2575  				p = p[i+1:]
  2576  			}
  2577  		}
  2578  		if i := strings.LastIndex(p, "."); i >= 0 {
  2579  			p = p[:i]
  2580  		}
  2581  		suffix := ".o"
  2582  		if writearchive > 0 {
  2583  			suffix = ".a"
  2584  		}
  2585  		outfile = p + suffix
  2586  	}
  2587  }