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