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