github.com/jonasi/go@v0.0.0-20150930005915-e78e654c1de0/src/cmd/compile/internal/gc/lex.go (about)

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