github.com/rsc/tmp@v0.0.0-20240517235954-6deaab19748b/bootstrap/internal/gc/lex.go (about)

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