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