2015-02-13 14:40:36 -05:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
2015-02-24 12:19:01 -05:00
|
|
|
//go:generate go tool yacc go.y
|
2015-02-27 17:40:34 +09:00
|
|
|
//go:generate go run mkbuiltin.go runtime unsafe
|
2015-02-24 12:19:01 -05:00
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
package gc
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
|
|
|
|
"cmd/internal/obj"
|
|
|
|
|
"flag"
|
|
|
|
|
"fmt"
|
|
|
|
|
"io"
|
|
|
|
|
"log"
|
|
|
|
|
"os"
|
|
|
|
|
"path"
|
|
|
|
|
"strconv"
|
|
|
|
|
"strings"
|
|
|
|
|
"unicode"
|
|
|
|
|
"unicode/utf8"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var yychar_lex int
|
|
|
|
|
|
|
|
|
|
var yyprev int
|
|
|
|
|
|
|
|
|
|
var yylast int
|
|
|
|
|
|
|
|
|
|
var imported_unsafe int
|
|
|
|
|
|
|
|
|
|
var goos string
|
|
|
|
|
|
|
|
|
|
var goarch string
|
|
|
|
|
|
|
|
|
|
var goroot string
|
|
|
|
|
|
|
|
|
|
// Debug arguments.
|
|
|
|
|
// These can be specified with the -d flag, as in "-d nil"
|
|
|
|
|
// to set the debug_checknil variable. In general the list passed
|
|
|
|
|
// to -d can be comma-separated.
|
|
|
|
|
var debugtab = []struct {
|
|
|
|
|
name string
|
|
|
|
|
val *int
|
|
|
|
|
}{struct {
|
|
|
|
|
name string
|
|
|
|
|
val *int
|
|
|
|
|
}{"nil", &Debug_checknil}}
|
|
|
|
|
|
|
|
|
|
// Our own isdigit, isspace, isalpha, isalnum that take care
|
|
|
|
|
// of EOF and other out of range arguments.
|
|
|
|
|
func yy_isdigit(c int) bool {
|
|
|
|
|
return c >= 0 && c <= 0xFF && isdigit(c)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func yy_isspace(c int) bool {
|
|
|
|
|
return c == ' ' || c == '\t' || c == '\n' || c == '\r'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func yy_isalpha(c int) bool {
|
|
|
|
|
return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func yy_isalnum(c int) bool {
|
|
|
|
|
return c >= 0 && c <= 0xFF && isalnum(c)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Disallow use of isdigit etc.
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
EOF = -1
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func usage() {
|
|
|
|
|
fmt.Printf("usage: %cg [options] file.go...\n", Thearch.Thechar)
|
|
|
|
|
obj.Flagprint(1)
|
2015-02-23 10:22:26 -05:00
|
|
|
Exit(2)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 14:02:27 -05:00
|
|
|
func hidePanic() {
|
2015-02-13 14:40:36 -05:00
|
|
|
if nsavederrors+nerrors > 0 {
|
2015-02-23 14:02:27 -05:00
|
|
|
// If we've already complained about things
|
|
|
|
|
// in the program, don't bother complaining
|
|
|
|
|
// about a panic too; let the user clean up
|
|
|
|
|
// the code and try again.
|
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func doversion() {
|
2015-02-23 16:07:24 -05:00
|
|
|
p := obj.Expstring()
|
2015-02-13 14:40:36 -05:00
|
|
|
if p == "X:none" {
|
|
|
|
|
p = ""
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
sep := ""
|
2015-02-23 14:02:27 -05:00
|
|
|
if p != "" {
|
2015-02-13 14:40:36 -05:00
|
|
|
sep = " "
|
|
|
|
|
}
|
|
|
|
|
fmt.Printf("%cg version %s%s%s\n", Thearch.Thechar, obj.Getgoversion(), sep, p)
|
|
|
|
|
os.Exit(0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func Main() {
|
2015-02-23 14:02:27 -05:00
|
|
|
defer hidePanic()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
// Allow GOARCH=thearch.thestring or GOARCH=thearch.thestringsuffix,
|
|
|
|
|
// but not other values.
|
2015-02-23 16:07:24 -05:00
|
|
|
p := obj.Getgoarch()
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if !strings.HasPrefix(p, Thearch.Thestring) {
|
|
|
|
|
log.Fatalf("cannot use %cg with GOARCH=%s", Thearch.Thechar, p)
|
|
|
|
|
}
|
|
|
|
|
goarch = p
|
|
|
|
|
|
|
|
|
|
Thearch.Linkarchinit()
|
|
|
|
|
Ctxt = obj.Linknew(Thearch.Thelinkarch)
|
|
|
|
|
Ctxt.Diag = Yyerror
|
|
|
|
|
Ctxt.Bso = &bstdout
|
|
|
|
|
bstdout = *obj.Binitw(os.Stdout)
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
localpkg = mkpkg("")
|
2015-02-13 14:40:36 -05:00
|
|
|
localpkg.Prefix = "\"\""
|
|
|
|
|
|
|
|
|
|
// pseudo-package, for scoping
|
2015-03-02 16:03:26 -05:00
|
|
|
builtinpkg = mkpkg("go.builtin")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
builtinpkg.Prefix = "go.builtin" // not go%2ebuiltin
|
|
|
|
|
|
|
|
|
|
// pseudo-package, accessed by import "unsafe"
|
2015-03-02 16:03:26 -05:00
|
|
|
unsafepkg = mkpkg("unsafe")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
unsafepkg.Name = "unsafe"
|
|
|
|
|
|
|
|
|
|
// real package, referred to by generated runtime calls
|
2015-03-02 16:03:26 -05:00
|
|
|
Runtimepkg = mkpkg("runtime")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
Runtimepkg.Name = "runtime"
|
|
|
|
|
|
|
|
|
|
// pseudo-packages used in symbol tables
|
2015-03-02 16:03:26 -05:00
|
|
|
gostringpkg = mkpkg("go.string")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
gostringpkg.Name = "go.string"
|
|
|
|
|
gostringpkg.Prefix = "go.string" // not go%2estring
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
itabpkg = mkpkg("go.itab")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
itabpkg.Name = "go.itab"
|
|
|
|
|
itabpkg.Prefix = "go.itab" // not go%2eitab
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
weaktypepkg = mkpkg("go.weak.type")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
weaktypepkg.Name = "go.weak.type"
|
|
|
|
|
weaktypepkg.Prefix = "go.weak.type" // not go%2eweak%2etype
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
typelinkpkg = mkpkg("go.typelink")
|
2015-02-13 14:40:36 -05:00
|
|
|
typelinkpkg.Name = "go.typelink"
|
|
|
|
|
typelinkpkg.Prefix = "go.typelink" // not go%2etypelink
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
trackpkg = mkpkg("go.track")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
trackpkg.Name = "go.track"
|
|
|
|
|
trackpkg.Prefix = "go.track" // not go%2etrack
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
typepkg = mkpkg("type")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
typepkg.Name = "type"
|
|
|
|
|
|
|
|
|
|
goroot = obj.Getgoroot()
|
|
|
|
|
goos = obj.Getgoos()
|
|
|
|
|
|
|
|
|
|
Nacl = goos == "nacl"
|
|
|
|
|
if Nacl {
|
|
|
|
|
flag_largemodel = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
outfile = ""
|
|
|
|
|
obj.Flagcount("+", "compiling runtime", &compiling_runtime)
|
|
|
|
|
obj.Flagcount("%", "debug non-static initializers", &Debug['%'])
|
|
|
|
|
obj.Flagcount("A", "for bootstrapping, allow 'any' type", &Debug['A'])
|
|
|
|
|
obj.Flagcount("B", "disable bounds checking", &Debug['B'])
|
|
|
|
|
obj.Flagstr("D", "path: set relative path for local imports", &localimport)
|
|
|
|
|
obj.Flagcount("E", "debug symbol export", &Debug['E'])
|
|
|
|
|
obj.Flagfn1("I", "dir: add dir to import search path", addidir)
|
|
|
|
|
obj.Flagcount("K", "debug missing line numbers", &Debug['K'])
|
|
|
|
|
obj.Flagcount("L", "use full (long) path in error messages", &Debug['L'])
|
|
|
|
|
obj.Flagcount("M", "debug move generation", &Debug['M'])
|
|
|
|
|
obj.Flagcount("N", "disable optimizations", &Debug['N'])
|
|
|
|
|
obj.Flagcount("P", "debug peephole optimizer", &Debug['P'])
|
|
|
|
|
obj.Flagcount("R", "debug register optimizer", &Debug['R'])
|
|
|
|
|
obj.Flagcount("S", "print assembly listing", &Debug['S'])
|
|
|
|
|
obj.Flagfn0("V", "print compiler version", doversion)
|
|
|
|
|
obj.Flagcount("W", "debug parse tree after type checking", &Debug['W'])
|
|
|
|
|
obj.Flagstr("asmhdr", "file: write assembly header to named file", &asmhdr)
|
|
|
|
|
obj.Flagcount("complete", "compiling complete package (no C or assembly)", &pure_go)
|
|
|
|
|
obj.Flagstr("d", "list: print debug information about items in list", &debugstr)
|
|
|
|
|
obj.Flagcount("e", "no limit on number of errors reported", &Debug['e'])
|
|
|
|
|
obj.Flagcount("f", "debug stack frames", &Debug['f'])
|
|
|
|
|
obj.Flagcount("g", "debug code generation", &Debug['g'])
|
|
|
|
|
obj.Flagcount("h", "halt on error", &Debug['h'])
|
|
|
|
|
obj.Flagcount("i", "debug line number stack", &Debug['i'])
|
|
|
|
|
obj.Flagstr("installsuffix", "pkg directory suffix", &flag_installsuffix)
|
|
|
|
|
obj.Flagcount("j", "debug runtime-initialized variables", &Debug['j'])
|
|
|
|
|
obj.Flagcount("l", "disable inlining", &Debug['l'])
|
|
|
|
|
obj.Flagcount("live", "debug liveness analysis", &debuglive)
|
|
|
|
|
obj.Flagcount("m", "print optimization decisions", &Debug['m'])
|
|
|
|
|
obj.Flagcount("nolocalimports", "reject local (relative) imports", &nolocalimports)
|
|
|
|
|
obj.Flagstr("o", "obj: set output file", &outfile)
|
|
|
|
|
obj.Flagstr("p", "path: set expected package import path", &myimportpath)
|
|
|
|
|
obj.Flagcount("pack", "write package file instead of object file", &writearchive)
|
|
|
|
|
obj.Flagcount("r", "debug generated wrappers", &Debug['r'])
|
|
|
|
|
obj.Flagcount("race", "enable race detector", &flag_race)
|
|
|
|
|
obj.Flagcount("s", "warn about composite literals that can be simplified", &Debug['s'])
|
|
|
|
|
obj.Flagstr("trimpath", "prefix: remove prefix from recorded source file paths", &Ctxt.Trimpath)
|
|
|
|
|
obj.Flagcount("u", "reject unsafe code", &safemode)
|
|
|
|
|
obj.Flagcount("v", "increase debug verbosity", &Debug['v'])
|
|
|
|
|
obj.Flagcount("w", "debug type checking", &Debug['w'])
|
|
|
|
|
use_writebarrier = 1
|
|
|
|
|
obj.Flagcount("wb", "enable write barrier", &use_writebarrier)
|
|
|
|
|
obj.Flagcount("x", "debug lexer", &Debug['x'])
|
|
|
|
|
obj.Flagcount("y", "debug declarations in canned imports (with -d)", &Debug['y'])
|
2015-02-10 15:56:32 +13:00
|
|
|
var flag_shared int
|
2015-02-13 14:40:36 -05:00
|
|
|
if Thearch.Thechar == '6' {
|
|
|
|
|
obj.Flagcount("largemodel", "generate code that assumes a large memory model", &flag_largemodel)
|
2015-02-10 15:56:32 +13:00
|
|
|
obj.Flagcount("shared", "generate code that can be linked into a shared library", &flag_shared)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 10:22:26 -05:00
|
|
|
obj.Flagstr("cpuprofile", "file: write cpu profile to file", &cpuprofile)
|
|
|
|
|
obj.Flagstr("memprofile", "file: write memory profile to file", &memprofile)
|
2015-02-13 14:40:36 -05:00
|
|
|
obj.Flagparse(usage)
|
2015-02-10 15:56:32 +13:00
|
|
|
Ctxt.Flag_shared = int32(flag_shared)
|
2015-02-13 14:40:36 -05:00
|
|
|
Ctxt.Debugasm = int32(Debug['S'])
|
|
|
|
|
Ctxt.Debugvlog = int32(Debug['v'])
|
|
|
|
|
|
|
|
|
|
if flag.NArg() < 1 {
|
|
|
|
|
usage()
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 10:22:26 -05:00
|
|
|
startProfile()
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
if flag_race != 0 {
|
2015-03-02 16:03:26 -05:00
|
|
|
racepkg = mkpkg("runtime/race")
|
2015-02-13 14:40:36 -05:00
|
|
|
racepkg.Name = "race"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// parse -d argument
|
|
|
|
|
if debugstr != "" {
|
|
|
|
|
var j int
|
|
|
|
|
f := strings.Split(debugstr, ",")
|
|
|
|
|
for i := range f {
|
|
|
|
|
if f[i] == "" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
for j = 0; j < len(debugtab); j++ {
|
|
|
|
|
if debugtab[j].name == f[i] {
|
|
|
|
|
if debugtab[j].val != nil {
|
|
|
|
|
*debugtab[j].val = 1
|
|
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if j >= len(debugtab) {
|
|
|
|
|
log.Fatalf("unknown debug information -d '%s'\n", f[i])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// enable inlining. for now:
|
|
|
|
|
// default: inlining on. (debug['l'] == 1)
|
|
|
|
|
// -l: inlining off (debug['l'] == 0)
|
|
|
|
|
// -ll, -lll: inlining on again, with extra debugging (debug['l'] > 1)
|
|
|
|
|
if Debug['l'] <= 1 {
|
|
|
|
|
Debug['l'] = 1 - Debug['l']
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if Thearch.Thechar == '8' {
|
2015-02-23 16:07:24 -05:00
|
|
|
p := obj.Getgo386()
|
2015-02-13 14:40:36 -05:00
|
|
|
if p == "387" {
|
|
|
|
|
Use_sse = 0
|
|
|
|
|
} else if p == "sse2" {
|
|
|
|
|
Use_sse = 1
|
|
|
|
|
} else {
|
|
|
|
|
log.Fatalf("unsupported setting GO386=%s", p)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Thearch.Betypeinit()
|
|
|
|
|
if Widthptr == 0 {
|
|
|
|
|
Fatal("betypeinit failed")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lexinit()
|
|
|
|
|
typeinit()
|
|
|
|
|
lexinit1()
|
|
|
|
|
// TODO(rsc): Restore yytinit?
|
|
|
|
|
|
|
|
|
|
blockgen = 1
|
|
|
|
|
dclcontext = PEXTERN
|
|
|
|
|
nerrors = 0
|
|
|
|
|
lexlineno = 1
|
|
|
|
|
|
|
|
|
|
for _, infile = range flag.Args() {
|
|
|
|
|
linehist(infile, 0, 0)
|
|
|
|
|
|
|
|
|
|
curio.infile = infile
|
|
|
|
|
var err error
|
|
|
|
|
curio.bin, err = obj.Bopenr(infile)
|
|
|
|
|
if err != nil {
|
|
|
|
|
fmt.Printf("open %s: %v\n", infile, err)
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
curio.peekc = 0
|
|
|
|
|
curio.peekc1 = 0
|
|
|
|
|
curio.nlsemi = 0
|
|
|
|
|
curio.eofnl = 0
|
|
|
|
|
curio.last = 0
|
|
|
|
|
|
|
|
|
|
// Skip initial BOM if present.
|
|
|
|
|
if obj.Bgetrune(curio.bin) != obj.BOM {
|
|
|
|
|
obj.Bungetrune(curio.bin)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
block = 1
|
|
|
|
|
iota_ = -1000000
|
|
|
|
|
|
|
|
|
|
imported_unsafe = 0
|
|
|
|
|
|
|
|
|
|
yyparse()
|
|
|
|
|
if nsyntaxerrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
linehist("<pop>", 0, 0)
|
|
|
|
|
if curio.bin != nil {
|
|
|
|
|
obj.Bterm(curio.bin)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
testdclstack()
|
|
|
|
|
mkpackage(localpkg.Name) // final import not used checks
|
|
|
|
|
lexfini()
|
|
|
|
|
|
|
|
|
|
typecheckok = 1
|
|
|
|
|
if Debug['f'] != 0 {
|
|
|
|
|
frame(1)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Process top-level declarations in phases.
|
|
|
|
|
|
|
|
|
|
// Phase 1: const, type, and names and types of funcs.
|
|
|
|
|
// This will gather all the information about types
|
|
|
|
|
// and methods but doesn't depend on any of it.
|
|
|
|
|
defercheckwidth()
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op != ODCL && l.N.Op != OAS {
|
|
|
|
|
typecheck(&l.N, Etop)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 2: Variable assignments.
|
|
|
|
|
// To check interface assignments, depends on phase 1.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ODCL || l.N.Op == OAS {
|
|
|
|
|
typecheck(&l.N, Etop)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
resumecheckwidth()
|
|
|
|
|
|
|
|
|
|
// Phase 3: Type check function bodies.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ODCLFUNC || l.N.Op == OCLOSURE {
|
|
|
|
|
Curfn = l.N
|
|
|
|
|
decldepth = 1
|
|
|
|
|
saveerrors()
|
|
|
|
|
typechecklist(l.N.Nbody, Etop)
|
|
|
|
|
checkreturn(l.N)
|
|
|
|
|
if nerrors != 0 {
|
|
|
|
|
l.N.Nbody = nil // type errors; do not compile
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 4: Decide how to capture closed variables.
|
|
|
|
|
// This needs to run before escape analysis,
|
|
|
|
|
// because variables captured by value do not escape.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ODCLFUNC && l.N.Closure != nil {
|
|
|
|
|
Curfn = l.N
|
|
|
|
|
capturevars(l.N)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Curfn = nil
|
|
|
|
|
|
|
|
|
|
if nsavederrors+nerrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 5: Inlining
|
|
|
|
|
if Debug['l'] > 1 {
|
|
|
|
|
// Typecheck imported function bodies if debug['l'] > 1,
|
|
|
|
|
// otherwise lazily when used or re-exported.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := importlist; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Inl != nil {
|
|
|
|
|
saveerrors()
|
|
|
|
|
typecheckinl(l.N)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nsavederrors+nerrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if Debug['l'] != 0 {
|
|
|
|
|
// Find functions that can be inlined and clone them before walk expands them.
|
2015-02-24 12:19:01 -05:00
|
|
|
visitBottomUp(xtop, func(list *NodeList, recursive bool) {
|
|
|
|
|
for l := list; l != nil; l = l.Next {
|
|
|
|
|
if l.N.Op == ODCLFUNC {
|
|
|
|
|
caninl(l.N)
|
|
|
|
|
inlcalls(l.N)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-24 12:19:01 -05:00
|
|
|
})
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 6: Escape analysis.
|
|
|
|
|
// Required for moving heap allocations onto stack,
|
|
|
|
|
// which in turn is required by the closure implementation,
|
|
|
|
|
// which stores the addresses of stack variables into the closure.
|
|
|
|
|
// If the closure does not escape, it needs to be on the stack
|
|
|
|
|
// or else the stack copier will not update it.
|
|
|
|
|
escapes(xtop)
|
|
|
|
|
|
|
|
|
|
// Escape analysis moved escaped values off stack.
|
|
|
|
|
// Move large values off stack too.
|
|
|
|
|
movelarge(xtop)
|
|
|
|
|
|
|
|
|
|
// Phase 7: Transform closure bodies to properly reference captured variables.
|
|
|
|
|
// This needs to happen before walk, because closures must be transformed
|
|
|
|
|
// before walk reaches a call of a closure.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ODCLFUNC && l.N.Closure != nil {
|
|
|
|
|
Curfn = l.N
|
|
|
|
|
transformclosure(l.N)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Curfn = nil
|
|
|
|
|
|
|
|
|
|
// Phase 8: Compile top level functions.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := xtop; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ODCLFUNC {
|
|
|
|
|
funccompile(l.N)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nsavederrors+nerrors == 0 {
|
|
|
|
|
fninit(xtop)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Phase 9: Check external declarations.
|
2015-02-23 16:07:24 -05:00
|
|
|
for l := externdcl; l != nil; l = l.Next {
|
2015-02-13 14:40:36 -05:00
|
|
|
if l.N.Op == ONAME {
|
|
|
|
|
typecheck(&l.N, Erv)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nerrors+nsavederrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dumpobj()
|
|
|
|
|
|
|
|
|
|
if asmhdr != "" {
|
|
|
|
|
dumpasmhdr()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if nerrors+nsavederrors != 0 {
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Flusherrors()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func saveerrors() {
|
|
|
|
|
nsavederrors += nerrors
|
|
|
|
|
nerrors = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func arsize(b *obj.Biobuf, name string) int {
|
|
|
|
|
var buf [ArhdrSize]byte
|
|
|
|
|
if _, err := io.ReadFull(b, buf[:]); err != nil {
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
aname := strings.Trim(string(buf[0:16]), " ")
|
|
|
|
|
if !strings.HasPrefix(aname, name) {
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
asize := strings.Trim(string(buf[48:58]), " ")
|
|
|
|
|
i, _ := strconv.Atoi(asize)
|
|
|
|
|
return i
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func skiptopkgdef(b *obj.Biobuf) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
/* archive header */
|
2015-02-23 16:07:24 -05:00
|
|
|
p := obj.Brdline(b, '\n')
|
2015-02-13 14:40:36 -05:00
|
|
|
if p == "" {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if obj.Blinelen(b) != 8 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if p != "!<arch>\n" {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* symbol table may be first; skip it */
|
2015-02-23 16:07:24 -05:00
|
|
|
sz := arsize(b, "__.GOSYMDEF")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if sz >= 0 {
|
|
|
|
|
obj.Bseek(b, int64(sz), 1)
|
|
|
|
|
} else {
|
|
|
|
|
obj.Bseek(b, 8, 0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* package export block is next */
|
|
|
|
|
sz = arsize(b, "__.PKGDEF")
|
|
|
|
|
|
|
|
|
|
if sz <= 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func addidir(dir string) {
|
|
|
|
|
if dir == "" {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var pp **Idir
|
2015-02-13 14:40:36 -05:00
|
|
|
for pp = &idirs; *pp != nil; pp = &(*pp).link {
|
|
|
|
|
}
|
|
|
|
|
*pp = new(Idir)
|
|
|
|
|
(*pp).link = nil
|
|
|
|
|
(*pp).dir = dir
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// is this path a local name? begins with ./ or ../ or /
|
2015-03-02 16:03:26 -05:00
|
|
|
func islocalname(name string) bool {
|
|
|
|
|
return strings.HasPrefix(name, "/") ||
|
|
|
|
|
Ctxt.Windows != 0 && len(name) >= 3 && yy_isalpha(int(name[0])) && name[1] == ':' && name[2] == '/' ||
|
|
|
|
|
strings.HasPrefix(name, "./") || name == "." ||
|
|
|
|
|
strings.HasPrefix(name, "../") || name == ".."
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
func findpkg(name string) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
if islocalname(name) {
|
|
|
|
|
if safemode != 0 || nolocalimports != 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// try .a before .6. important for building libraries:
|
|
|
|
|
// if there is an array.6 in the array.a library,
|
|
|
|
|
// want to find all of array.a, not just array.6.
|
2015-03-02 16:03:26 -05:00
|
|
|
namebuf = fmt.Sprintf("%s.a", name)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if obj.Access(namebuf, 0) >= 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-02 16:03:26 -05:00
|
|
|
namebuf = fmt.Sprintf("%s.%c", name, Thearch.Thechar)
|
2015-02-13 14:40:36 -05:00
|
|
|
if obj.Access(namebuf, 0) >= 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// local imports should be canonicalized already.
|
|
|
|
|
// don't want to see "encoding/../encoding/base64"
|
|
|
|
|
// as different from "encoding/base64".
|
2015-02-23 16:07:24 -05:00
|
|
|
var q string
|
2015-02-13 14:40:36 -05:00
|
|
|
_ = q
|
2015-03-02 16:03:26 -05:00
|
|
|
if path.Clean(name) != name {
|
|
|
|
|
Yyerror("non-canonical import path %q (should be %q)", name, q)
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
for p := idirs; p != nil; p = p.link {
|
2015-03-02 16:03:26 -05:00
|
|
|
namebuf = fmt.Sprintf("%s/%s.a", p.dir, name)
|
2015-02-13 14:40:36 -05:00
|
|
|
if obj.Access(namebuf, 0) >= 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-02 16:03:26 -05:00
|
|
|
namebuf = fmt.Sprintf("%s/%s.%c", p.dir, name, Thearch.Thechar)
|
2015-02-13 14:40:36 -05:00
|
|
|
if obj.Access(namebuf, 0) >= 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if goroot != "" {
|
2015-02-23 16:07:24 -05:00
|
|
|
suffix := ""
|
|
|
|
|
suffixsep := ""
|
2015-02-13 14:40:36 -05:00
|
|
|
if flag_installsuffix != "" {
|
|
|
|
|
suffixsep = "_"
|
|
|
|
|
suffix = flag_installsuffix
|
|
|
|
|
} else if flag_race != 0 {
|
|
|
|
|
suffixsep = "_"
|
|
|
|
|
suffix = "race"
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
namebuf = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.a", goroot, goos, goarch, suffixsep, suffix, name)
|
2015-02-13 14:40:36 -05:00
|
|
|
if obj.Access(namebuf, 0) >= 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-02 16:03:26 -05:00
|
|
|
namebuf = fmt.Sprintf("%s/pkg/%s_%s%s%s/%s.%c", goroot, goos, goarch, suffixsep, suffix, name, Thearch.Thechar)
|
2015-02-13 14:40:36 -05:00
|
|
|
if obj.Access(namebuf, 0) >= 0 {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func fakeimport() {
|
2015-03-02 16:03:26 -05:00
|
|
|
importpkg = mkpkg("fake")
|
2015-02-13 14:40:36 -05:00
|
|
|
cannedimports("fake.6", "$$\n")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func importfile(f *Val, line int) {
|
|
|
|
|
if f.Ctype != CTSTR {
|
|
|
|
|
Yyerror("import statement not a string")
|
|
|
|
|
fakeimport()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
if len(f.U.Sval) == 0 {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("import path is empty")
|
|
|
|
|
fakeimport()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if isbadimport(f.U.Sval) {
|
|
|
|
|
fakeimport()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The package name main is no longer reserved,
|
|
|
|
|
// but we reserve the import path "main" to identify
|
|
|
|
|
// the main package, just as we reserve the import
|
|
|
|
|
// path "math" to identify the standard math package.
|
2015-03-02 16:03:26 -05:00
|
|
|
if f.U.Sval == "main" {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("cannot import \"main\"")
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
if myimportpath != "" && f.U.Sval == myimportpath {
|
|
|
|
|
Yyerror("import %q while compiling that package (import cycle)", f.U.Sval)
|
2015-02-13 14:40:36 -05:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
if f.U.Sval == "unsafe" {
|
2015-02-13 14:40:36 -05:00
|
|
|
if safemode != 0 {
|
|
|
|
|
Yyerror("cannot import package unsafe")
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
importpkg = mkpkg(f.U.Sval)
|
|
|
|
|
cannedimports("unsafe.6", unsafeimport)
|
|
|
|
|
imported_unsafe = 1
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
path_ := f.U.Sval
|
2015-02-13 14:40:36 -05:00
|
|
|
if islocalname(path_) {
|
2015-03-02 16:03:26 -05:00
|
|
|
if path_[0] == '/' {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("import path cannot be absolute path")
|
|
|
|
|
fakeimport()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
prefix := Ctxt.Pathname
|
2015-02-13 14:40:36 -05:00
|
|
|
if localimport != "" {
|
|
|
|
|
prefix = localimport
|
|
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
cleanbuf := prefix
|
2015-02-13 14:40:36 -05:00
|
|
|
cleanbuf += "/"
|
2015-03-02 16:03:26 -05:00
|
|
|
cleanbuf += path_
|
2015-02-13 14:40:36 -05:00
|
|
|
cleanbuf = path.Clean(cleanbuf)
|
2015-03-02 16:03:26 -05:00
|
|
|
path_ = cleanbuf
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if isbadimport(path_) {
|
|
|
|
|
fakeimport()
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if !findpkg(path_) {
|
2015-03-02 16:03:26 -05:00
|
|
|
Yyerror("can't find import: %q", f.U.Sval)
|
2015-02-13 14:40:36 -05:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
importpkg = mkpkg(path_)
|
|
|
|
|
|
|
|
|
|
// If we already saw that package, feed a dummy statement
|
|
|
|
|
// to the lexer to avoid parsing export data twice.
|
|
|
|
|
if importpkg.Imported != 0 {
|
2015-02-23 16:07:24 -05:00
|
|
|
file := namebuf
|
|
|
|
|
tag := ""
|
2015-02-13 14:40:36 -05:00
|
|
|
if importpkg.Safe {
|
|
|
|
|
tag = "safe"
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
p := fmt.Sprintf("package %s %s\n$$\n", importpkg.Name, tag)
|
2015-02-13 14:40:36 -05:00
|
|
|
cannedimports(file, p)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
importpkg.Imported = 1
|
|
|
|
|
|
|
|
|
|
var err error
|
2015-02-23 16:07:24 -05:00
|
|
|
var imp *obj.Biobuf
|
2015-02-13 14:40:36 -05:00
|
|
|
imp, err = obj.Bopenr(namebuf)
|
|
|
|
|
if err != nil {
|
2015-03-02 16:03:26 -05:00
|
|
|
Yyerror("can't open import: %q: %v", f.U.Sval, err)
|
2015-02-13 14:40:36 -05:00
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
file := namebuf
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
n := len(namebuf)
|
2015-02-13 14:40:36 -05:00
|
|
|
if n > 2 && namebuf[n-2] == '.' && namebuf[n-1] == 'a' {
|
2015-02-17 22:13:49 -05:00
|
|
|
if !skiptopkgdef(imp) {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("import %s: not a package file", file)
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// check object header
|
2015-02-23 16:07:24 -05:00
|
|
|
p := obj.Brdstr(imp, '\n', 1)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if p != "empty archive" {
|
|
|
|
|
if !strings.HasPrefix(p, "go object ") {
|
|
|
|
|
Yyerror("import %s: not a go object file", file)
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
q := fmt.Sprintf("%s %s %s %s", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion(), obj.Expstring())
|
2015-02-13 14:40:36 -05:00
|
|
|
if p[10:] != q {
|
|
|
|
|
Yyerror("import %s: object is [%s] expected [%s]", file, p[10:], q)
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// assume files move (get installed)
|
|
|
|
|
// so don't record the full path.
|
2015-03-02 16:03:26 -05:00
|
|
|
linehist(file[n-len(path_)-2:], -1, 1) // acts as #pragma lib
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* position the input right
|
|
|
|
|
* after $$ and return
|
|
|
|
|
*/
|
|
|
|
|
pushedio = curio
|
|
|
|
|
|
|
|
|
|
curio.bin = imp
|
|
|
|
|
curio.peekc = 0
|
|
|
|
|
curio.peekc1 = 0
|
|
|
|
|
curio.infile = file
|
|
|
|
|
curio.nlsemi = 0
|
|
|
|
|
typecheckok = 1
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
var c int32
|
2015-02-13 14:40:36 -05:00
|
|
|
for {
|
|
|
|
|
c = int32(getc())
|
|
|
|
|
if c == EOF {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if c != '$' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
c = int32(getc())
|
|
|
|
|
if c == EOF {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if c != '$' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
Yyerror("no import in %q", f.U.Sval)
|
2015-02-13 14:40:36 -05:00
|
|
|
unimportfile()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func unimportfile() {
|
|
|
|
|
if curio.bin != nil {
|
|
|
|
|
obj.Bterm(curio.bin)
|
|
|
|
|
curio.bin = nil
|
|
|
|
|
} else {
|
|
|
|
|
lexlineno-- // re correct sys.6 line number
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
curio = pushedio
|
|
|
|
|
|
|
|
|
|
pushedio.bin = nil
|
|
|
|
|
incannedimport = 0
|
|
|
|
|
typecheckok = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func cannedimports(file string, cp string) {
|
|
|
|
|
lexlineno++ // if sys.6 is included on line 1,
|
|
|
|
|
|
|
|
|
|
pushedio = curio
|
|
|
|
|
|
|
|
|
|
curio.bin = nil
|
|
|
|
|
curio.peekc = 0
|
|
|
|
|
curio.peekc1 = 0
|
|
|
|
|
curio.infile = file
|
|
|
|
|
curio.cp = cp
|
|
|
|
|
curio.nlsemi = 0
|
|
|
|
|
curio.importsafe = false
|
|
|
|
|
|
|
|
|
|
typecheckok = 1
|
|
|
|
|
incannedimport = 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func isfrog(c int) bool {
|
|
|
|
|
// complain about possibly invisible control characters
|
|
|
|
|
if c < ' ' {
|
|
|
|
|
return !yy_isspace(c) // exclude good white space
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if 0x7f <= c && c <= 0xa0 { // DEL, unicode block including unbreakable space.
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Loophack struct {
|
|
|
|
|
v int
|
|
|
|
|
next *Loophack
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var _yylex_lstk *Loophack
|
|
|
|
|
|
|
|
|
|
func _yylex(yylval *yySymType) int32 {
|
|
|
|
|
var c1 int
|
|
|
|
|
var escflag int
|
|
|
|
|
var v int64
|
|
|
|
|
var cp *bytes.Buffer
|
|
|
|
|
var rune_ uint
|
|
|
|
|
var s *Sym
|
|
|
|
|
var h *Loophack
|
2015-02-24 20:54:57 +00:00
|
|
|
var str string
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
prevlineno = lineno
|
|
|
|
|
|
|
|
|
|
l0:
|
2015-03-02 12:35:15 -05:00
|
|
|
c := getc()
|
2015-02-13 14:40:36 -05:00
|
|
|
if yy_isspace(c) {
|
|
|
|
|
if c == '\n' && curio.nlsemi != 0 {
|
|
|
|
|
ungetc(c)
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: implicit semi\n")
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
return ';'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto l0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
lineno = lexlineno /* start of token */
|
|
|
|
|
|
|
|
|
|
if c >= utf8.RuneSelf {
|
|
|
|
|
/* all multibyte runes are alpha */
|
|
|
|
|
cp = &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
|
|
|
|
|
goto talph
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if yy_isalpha(c) {
|
|
|
|
|
cp = &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
goto talph
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if yy_isdigit(c) {
|
2015-03-02 12:35:15 -05:00
|
|
|
cp = &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
if c != '0' {
|
|
|
|
|
for {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
if yy_isdigit(c) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if c == '.' {
|
|
|
|
|
goto casedot
|
|
|
|
|
}
|
|
|
|
|
if c == 'e' || c == 'E' || c == 'p' || c == 'P' {
|
|
|
|
|
goto caseep
|
|
|
|
|
}
|
|
|
|
|
if c == 'i' {
|
|
|
|
|
goto casei
|
|
|
|
|
}
|
|
|
|
|
goto ncu
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
if c == 'x' || c == 'X' {
|
|
|
|
|
for {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
if yy_isdigit(c) {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if c >= 'a' && c <= 'f' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if c >= 'A' && c <= 'F' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if lexbuf.Len() == 2 {
|
|
|
|
|
Yyerror("malformed hex constant")
|
|
|
|
|
}
|
|
|
|
|
if c == 'p' {
|
|
|
|
|
goto caseep
|
|
|
|
|
}
|
|
|
|
|
goto ncu
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == 'p' { // 0p begins floating point zero
|
|
|
|
|
goto caseep
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c1 = 0
|
|
|
|
|
for {
|
|
|
|
|
if !yy_isdigit(c) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if c < '0' || c > '7' {
|
|
|
|
|
c1 = 1 // not octal
|
|
|
|
|
}
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == '.' {
|
|
|
|
|
goto casedot
|
|
|
|
|
}
|
|
|
|
|
if c == 'e' || c == 'E' {
|
|
|
|
|
goto caseep
|
|
|
|
|
}
|
|
|
|
|
if c == 'i' {
|
|
|
|
|
goto casei
|
|
|
|
|
}
|
|
|
|
|
if c1 != 0 {
|
|
|
|
|
Yyerror("malformed octal constant")
|
|
|
|
|
}
|
|
|
|
|
goto ncu
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch c {
|
|
|
|
|
case EOF:
|
|
|
|
|
lineno = prevlineno
|
|
|
|
|
ungetc(EOF)
|
|
|
|
|
return -1
|
|
|
|
|
|
|
|
|
|
case '_':
|
|
|
|
|
cp = &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
goto talph
|
|
|
|
|
|
|
|
|
|
case '.':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if yy_isdigit(c1) {
|
|
|
|
|
cp = &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = c1
|
|
|
|
|
goto casedot
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '.' {
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '.' {
|
|
|
|
|
c = LDDD
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ungetc(c1)
|
|
|
|
|
c1 = '.'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* "..." */
|
|
|
|
|
case '"':
|
|
|
|
|
lexbuf.Reset()
|
|
|
|
|
lexbuf.WriteString(`"<string>"`)
|
|
|
|
|
|
|
|
|
|
cp = &strbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
|
|
|
|
|
for {
|
2015-02-17 22:13:49 -05:00
|
|
|
if escchar('"', &escflag, &v) {
|
2015-02-13 14:40:36 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if v < utf8.RuneSelf || escflag != 0 {
|
|
|
|
|
cp.WriteByte(byte(v))
|
|
|
|
|
} else {
|
|
|
|
|
rune_ = uint(v)
|
|
|
|
|
cp.WriteRune(rune(rune_))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto strlit
|
|
|
|
|
|
|
|
|
|
/* `...` */
|
|
|
|
|
case '`':
|
|
|
|
|
lexbuf.Reset()
|
|
|
|
|
lexbuf.WriteString("`<string>`")
|
|
|
|
|
|
|
|
|
|
cp = &strbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
c = int(getr())
|
|
|
|
|
if c == '\r' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if c == EOF {
|
|
|
|
|
Yyerror("eof in string")
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == '`' {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
cp.WriteRune(rune(c))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto strlit
|
|
|
|
|
|
|
|
|
|
/* '.' */
|
|
|
|
|
case '\'':
|
2015-02-17 22:13:49 -05:00
|
|
|
if escchar('\'', &escflag, &v) {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("empty character literal or unescaped ' in character literal")
|
|
|
|
|
v = '\''
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
if !escchar('\'', &escflag, &v) {
|
2015-02-13 14:40:36 -05:00
|
|
|
Yyerror("missing '")
|
|
|
|
|
ungetc(int(v))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yylval.val.U.Xval = new(Mpint)
|
|
|
|
|
Mpmovecfix(yylval.val.U.Xval, v)
|
|
|
|
|
yylval.val.Ctype = CTRUNE
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: codepoint literal\n")
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
litbuf = "string literal"
|
|
|
|
|
return LLITERAL
|
|
|
|
|
|
|
|
|
|
case '/':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '*' {
|
2015-02-23 16:07:24 -05:00
|
|
|
nl := 0
|
2015-02-13 14:40:36 -05:00
|
|
|
for {
|
|
|
|
|
c = int(getr())
|
|
|
|
|
if c == '\n' {
|
|
|
|
|
nl = 1
|
|
|
|
|
}
|
|
|
|
|
for c == '*' {
|
|
|
|
|
c = int(getr())
|
|
|
|
|
if c == '/' {
|
|
|
|
|
if nl != 0 {
|
|
|
|
|
ungetc('\n')
|
|
|
|
|
}
|
|
|
|
|
goto l0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == '\n' {
|
|
|
|
|
nl = 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == EOF {
|
|
|
|
|
Yyerror("eof in comment")
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '/' {
|
|
|
|
|
c = getlinepragma()
|
|
|
|
|
for {
|
|
|
|
|
if c == '\n' || c == EOF {
|
|
|
|
|
ungetc(c)
|
|
|
|
|
goto l0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c = int(getr())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = ODIV
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ':':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = LCOLAS
|
|
|
|
|
yylval.i = int(lexlineno)
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '*':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OMUL
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '%':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OMOD
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '+':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '+' {
|
|
|
|
|
c = LINC
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OADD
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '-':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '-' {
|
|
|
|
|
c = LDEC
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OSUB
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '>':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '>' {
|
|
|
|
|
c = LRSH
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = ORSH
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = LGE
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c = LGT
|
|
|
|
|
|
|
|
|
|
case '<':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '<' {
|
|
|
|
|
c = LLSH
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OLSH
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = LLE
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '-' {
|
|
|
|
|
c = LCOMM
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c = LLT
|
|
|
|
|
|
|
|
|
|
case '=':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = LEQ
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '!':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = LNE
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '&':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '&' {
|
|
|
|
|
c = LANDAND
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '^' {
|
|
|
|
|
c = LANDNOT
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OANDNOT
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OAND
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '|':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '|' {
|
|
|
|
|
c = LOROR
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OOR
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case '^':
|
|
|
|
|
c1 = getc()
|
|
|
|
|
if c1 == '=' {
|
|
|
|
|
c = OXOR
|
|
|
|
|
goto asop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* clumsy dance:
|
|
|
|
|
* to implement rule that disallows
|
|
|
|
|
* if T{1}[0] { ... }
|
|
|
|
|
* but allows
|
|
|
|
|
* if (T{1}[0]) { ... }
|
|
|
|
|
* the block bodies for if/for/switch/select
|
|
|
|
|
* begin with an LBODY token, not '{'.
|
|
|
|
|
*
|
|
|
|
|
* when we see the keyword, the next
|
|
|
|
|
* non-parenthesized '{' becomes an LBODY.
|
|
|
|
|
* loophack is normally 0.
|
|
|
|
|
* a keyword makes it go up to 1.
|
|
|
|
|
* parens push loophack onto a stack and go back to 0.
|
|
|
|
|
* a '{' with loophack == 1 becomes LBODY and disables loophack.
|
|
|
|
|
*
|
|
|
|
|
* i said it was clumsy.
|
|
|
|
|
*/
|
|
|
|
|
case '(',
|
|
|
|
|
'[':
|
|
|
|
|
if loophack != 0 || _yylex_lstk != nil {
|
|
|
|
|
h = new(Loophack)
|
|
|
|
|
if h == nil {
|
|
|
|
|
Flusherrors()
|
|
|
|
|
Yyerror("out of memory")
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
h.v = loophack
|
|
|
|
|
h.next = _yylex_lstk
|
|
|
|
|
_yylex_lstk = h
|
|
|
|
|
loophack = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto lx
|
|
|
|
|
|
|
|
|
|
case ')',
|
|
|
|
|
']':
|
|
|
|
|
if _yylex_lstk != nil {
|
|
|
|
|
h = _yylex_lstk
|
|
|
|
|
loophack = h.v
|
|
|
|
|
_yylex_lstk = h.next
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto lx
|
|
|
|
|
|
|
|
|
|
case '{':
|
|
|
|
|
if loophack == 1 {
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("%v lex: LBODY\n", Ctxt.Line(int(lexlineno)))
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
loophack = 0
|
|
|
|
|
return LBODY
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
goto lx
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
goto lx
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ungetc(c1)
|
|
|
|
|
|
|
|
|
|
lx:
|
|
|
|
|
if c > 0xff {
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("%v lex: TOKEN %s\n", Ctxt.Line(int(lexlineno)), lexname(c))
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("%v lex: TOKEN '%c'\n", Ctxt.Line(int(lexlineno)), c)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if isfrog(c) {
|
|
|
|
|
Yyerror("illegal character 0x%x", uint(c))
|
|
|
|
|
goto l0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if importpkg == nil && (c == '#' || c == '$' || c == '?' || c == '@' || c == '\\') {
|
|
|
|
|
Yyerror("%s: unexpected %c", "syntax error", c)
|
|
|
|
|
goto l0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return int32(c)
|
|
|
|
|
|
|
|
|
|
asop:
|
|
|
|
|
yylval.i = c // rathole to hold which asop
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: TOKEN ASOP %c\n", c)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
return LASOP
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* cp is set to lexbuf and some
|
|
|
|
|
* prefix has been stored
|
|
|
|
|
*/
|
|
|
|
|
talph:
|
|
|
|
|
for {
|
|
|
|
|
if c >= utf8.RuneSelf {
|
|
|
|
|
ungetc(c)
|
|
|
|
|
rune_ = uint(getr())
|
|
|
|
|
|
|
|
|
|
// 0xb7 · is used for internal names
|
|
|
|
|
if !unicode.IsLetter(rune(rune_)) && !unicode.IsDigit(rune(rune_)) && (importpkg == nil || rune_ != 0xb7) {
|
|
|
|
|
Yyerror("invalid identifier character U+%04x", rune_)
|
|
|
|
|
}
|
|
|
|
|
cp.WriteRune(rune(rune_))
|
|
|
|
|
} else if !yy_isalnum(c) && c != '_' {
|
|
|
|
|
break
|
|
|
|
|
} else {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
}
|
|
|
|
|
c = getc()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cp = nil
|
|
|
|
|
ungetc(c)
|
|
|
|
|
|
2015-03-02 16:21:15 -05:00
|
|
|
s = LookupBytes(lexbuf.Bytes())
|
2015-02-13 14:40:36 -05:00
|
|
|
switch s.Lexical {
|
|
|
|
|
case LIGNORE:
|
|
|
|
|
goto l0
|
|
|
|
|
|
|
|
|
|
case LFOR,
|
|
|
|
|
LIF,
|
|
|
|
|
LSWITCH,
|
|
|
|
|
LSELECT:
|
|
|
|
|
loophack = 1 // see comment about loophack above
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: %s %s\n", Sconv(s, 0), lexname(int(s.Lexical)))
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
yylval.sym = s
|
|
|
|
|
return int32(s.Lexical)
|
|
|
|
|
|
|
|
|
|
ncu:
|
|
|
|
|
cp = nil
|
|
|
|
|
ungetc(c)
|
|
|
|
|
|
2015-02-24 20:54:57 +00:00
|
|
|
str = lexbuf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
yylval.val.U.Xval = new(Mpint)
|
2015-02-24 20:54:57 +00:00
|
|
|
mpatofix(yylval.val.U.Xval, str)
|
2015-02-13 14:40:36 -05:00
|
|
|
if yylval.val.U.Xval.Ovf != 0 {
|
|
|
|
|
Yyerror("overflow in constant")
|
|
|
|
|
Mpmovecfix(yylval.val.U.Xval, 0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yylval.val.Ctype = CTINT
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: integer literal\n")
|
|
|
|
|
}
|
2015-02-24 20:54:57 +00:00
|
|
|
litbuf = "literal " + str
|
2015-02-13 14:40:36 -05:00
|
|
|
return LLITERAL
|
|
|
|
|
|
|
|
|
|
casedot:
|
|
|
|
|
for {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
if !yy_isdigit(c) {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == 'i' {
|
|
|
|
|
goto casei
|
|
|
|
|
}
|
|
|
|
|
if c != 'e' && c != 'E' {
|
|
|
|
|
goto caseout
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
caseep:
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
if c == '+' || c == '-' {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if !yy_isdigit(c) {
|
|
|
|
|
Yyerror("malformed fp constant exponent")
|
|
|
|
|
}
|
|
|
|
|
for yy_isdigit(c) {
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
c = getc()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c == 'i' {
|
|
|
|
|
goto casei
|
|
|
|
|
}
|
|
|
|
|
goto caseout
|
|
|
|
|
|
|
|
|
|
// imaginary constant
|
|
|
|
|
casei:
|
|
|
|
|
cp = nil
|
|
|
|
|
|
2015-02-24 20:54:57 +00:00
|
|
|
str = lexbuf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
yylval.val.U.Cval = new(Mpcplx)
|
|
|
|
|
Mpmovecflt(&yylval.val.U.Cval.Real, 0.0)
|
2015-02-24 20:54:57 +00:00
|
|
|
mpatoflt(&yylval.val.U.Cval.Imag, str)
|
2015-02-13 14:40:36 -05:00
|
|
|
if yylval.val.U.Cval.Imag.Val.Ovf != 0 {
|
|
|
|
|
Yyerror("overflow in imaginary constant")
|
|
|
|
|
Mpmovecflt(&yylval.val.U.Cval.Real, 0.0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yylval.val.Ctype = CTCPLX
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: imaginary literal\n")
|
|
|
|
|
}
|
2015-02-24 20:54:57 +00:00
|
|
|
litbuf = "literal " + str
|
2015-02-13 14:40:36 -05:00
|
|
|
return LLITERAL
|
|
|
|
|
|
|
|
|
|
caseout:
|
|
|
|
|
cp = nil
|
|
|
|
|
ungetc(c)
|
|
|
|
|
|
2015-02-24 20:54:57 +00:00
|
|
|
str = lexbuf.String()
|
2015-02-13 14:40:36 -05:00
|
|
|
yylval.val.U.Fval = new(Mpflt)
|
2015-02-24 20:54:57 +00:00
|
|
|
mpatoflt(yylval.val.U.Fval, str)
|
2015-02-13 14:40:36 -05:00
|
|
|
if yylval.val.U.Fval.Val.Ovf != 0 {
|
|
|
|
|
Yyerror("overflow in float constant")
|
|
|
|
|
Mpmovecflt(yylval.val.U.Fval, 0.0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
yylval.val.Ctype = CTFLT
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: floating literal\n")
|
|
|
|
|
}
|
2015-02-24 20:54:57 +00:00
|
|
|
litbuf = "literal " + str
|
2015-02-13 14:40:36 -05:00
|
|
|
return LLITERAL
|
|
|
|
|
|
|
|
|
|
strlit:
|
2015-03-02 16:03:26 -05:00
|
|
|
yylval.val.U.Sval = internString(cp.Bytes())
|
2015-02-13 14:40:36 -05:00
|
|
|
yylval.val.Ctype = CTSTR
|
2015-02-23 17:34:49 -05:00
|
|
|
if Debug['x'] != 0 {
|
|
|
|
|
fmt.Printf("lex: string literal\n")
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
litbuf = "string literal"
|
|
|
|
|
return LLITERAL
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
var internedStrings = map[string]string{}
|
|
|
|
|
|
|
|
|
|
func internString(b []byte) string {
|
|
|
|
|
s, ok := internedStrings[string(b)] // string(b) here doesn't allocate
|
|
|
|
|
if ok {
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
s = string(b)
|
|
|
|
|
internedStrings[s] = s
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
func more(pp *string) bool {
|
|
|
|
|
p := *pp
|
|
|
|
|
for p != "" && yy_isspace(int(p[0])) {
|
|
|
|
|
p = p[1:]
|
|
|
|
|
}
|
|
|
|
|
*pp = p
|
|
|
|
|
return p != ""
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* read and interpret syntax that looks like
|
|
|
|
|
* //line parse.y:15
|
|
|
|
|
* as a discontinuity in sequential line numbers.
|
|
|
|
|
* the next line of input comes from parse.y:15
|
|
|
|
|
*/
|
|
|
|
|
func getlinepragma() int {
|
|
|
|
|
var cmd, verb, name string
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
c := int(getr())
|
2015-02-13 14:40:36 -05:00
|
|
|
if c == 'g' {
|
2015-03-02 12:35:15 -05:00
|
|
|
cp := &lexbuf
|
|
|
|
|
cp.Reset()
|
|
|
|
|
cp.WriteByte('g') // already read
|
|
|
|
|
for {
|
|
|
|
|
c = int(getr())
|
|
|
|
|
if c == EOF || c >= utf8.RuneSelf {
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
if c == '\n' {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cp = nil
|
|
|
|
|
|
|
|
|
|
if strings.HasPrefix(lexbuf.String(), "go:cgo_") {
|
|
|
|
|
pragcgo(lexbuf.String())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd = lexbuf.String()
|
|
|
|
|
verb = cmd
|
|
|
|
|
if i := strings.Index(verb, " "); i >= 0 {
|
|
|
|
|
verb = verb[:i]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "go:linkname" {
|
|
|
|
|
if imported_unsafe == 0 {
|
|
|
|
|
Yyerror("//go:linkname only allowed in Go files that import \"unsafe\"")
|
|
|
|
|
}
|
|
|
|
|
f := strings.Fields(cmd)
|
|
|
|
|
if len(f) != 3 {
|
|
|
|
|
Yyerror("usage: //go:linkname localname linkname")
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Lookup(f[1]).Linkname = f[2]
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "go:nointerface" && obj.Fieldtrack_enabled != 0 {
|
|
|
|
|
nointerface = true
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "go:noescape" {
|
|
|
|
|
noescape = true
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "go:nosplit" {
|
|
|
|
|
nosplit = true
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "go:nowritebarrier" {
|
|
|
|
|
if compiling_runtime == 0 {
|
|
|
|
|
Yyerror("//go:nowritebarrier only allowed in runtime")
|
|
|
|
|
}
|
|
|
|
|
nowritebarrier = true
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if c != 'l' {
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-02-23 16:07:24 -05:00
|
|
|
for i := 1; i < 5; i++ {
|
2015-02-13 14:40:36 -05:00
|
|
|
c = int(getr())
|
|
|
|
|
if c != int("line "[i]) {
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
cp := &lexbuf
|
2015-02-13 14:40:36 -05:00
|
|
|
cp.Reset()
|
2015-03-02 12:35:15 -05:00
|
|
|
linep := 0
|
2015-02-13 14:40:36 -05:00
|
|
|
for {
|
|
|
|
|
c = int(getr())
|
|
|
|
|
if c == EOF {
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
if c == '\n' {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
if c == ' ' {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if c == ':' {
|
|
|
|
|
linep = cp.Len() + 1
|
|
|
|
|
}
|
|
|
|
|
cp.WriteByte(byte(c))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cp = nil
|
|
|
|
|
|
|
|
|
|
if linep == 0 {
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-02 12:35:15 -05:00
|
|
|
n := 0
|
2015-02-13 14:40:36 -05:00
|
|
|
for _, c := range lexbuf.String()[linep:] {
|
|
|
|
|
if c < '0' || c > '9' {
|
|
|
|
|
goto out
|
|
|
|
|
}
|
|
|
|
|
n = n*10 + int(c) - '0'
|
|
|
|
|
if n > 1e8 {
|
|
|
|
|
Yyerror("line number out of range")
|
|
|
|
|
errorexit()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n <= 0 {
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// try to avoid allocating file name over and over
|
|
|
|
|
name = lexbuf.String()[:linep-1]
|
2015-02-23 16:07:24 -05:00
|
|
|
for h := Ctxt.Hist; h != nil; h = h.Link {
|
2015-02-13 14:40:36 -05:00
|
|
|
if h.Name != "" && h.Name == name {
|
|
|
|
|
linehist(h.Name, int32(n), 0)
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
linehist(name, int32(n), 0)
|
2015-03-02 12:35:15 -05:00
|
|
|
return c
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
out:
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getimpsym(pp *string) string {
|
|
|
|
|
more(pp) // skip spaces
|
|
|
|
|
p := *pp
|
|
|
|
|
if p == "" || p[0] == '"' {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
i := 0
|
|
|
|
|
for i < len(p) && !yy_isspace(int(p[i])) && p[i] != '"' {
|
|
|
|
|
i++
|
|
|
|
|
}
|
|
|
|
|
sym := p[:i]
|
|
|
|
|
*pp = p[i:]
|
|
|
|
|
return sym
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getquoted(pp *string) (string, bool) {
|
|
|
|
|
more(pp) // skip spaces
|
|
|
|
|
p := *pp
|
|
|
|
|
if p == "" || p[0] != '"' {
|
|
|
|
|
return "", false
|
|
|
|
|
}
|
|
|
|
|
p = p[1:]
|
|
|
|
|
i := strings.Index(p, `"`)
|
|
|
|
|
if i < 0 {
|
|
|
|
|
return "", false
|
|
|
|
|
}
|
|
|
|
|
*pp = p[i+1:]
|
|
|
|
|
return p[:i], true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copied nearly verbatim from the C compiler's #pragma parser.
|
|
|
|
|
// TODO: Rewrite more cleanly once the compiler is written in Go.
|
|
|
|
|
func pragcgo(text string) {
|
|
|
|
|
var q string
|
|
|
|
|
|
|
|
|
|
if i := strings.Index(text, " "); i >= 0 {
|
|
|
|
|
text, q = text[:i], text[i:]
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
verb := text[3:] // skip "go:"
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if verb == "cgo_dynamic_linker" || verb == "dynlinker" {
|
|
|
|
|
var ok bool
|
2015-02-23 16:07:24 -05:00
|
|
|
var p string
|
2015-02-13 14:40:36 -05:00
|
|
|
p, ok = getquoted(&q)
|
|
|
|
|
if !ok {
|
2015-03-02 12:35:15 -05:00
|
|
|
Yyerror("usage: //go:cgo_dynamic_linker \"path\"")
|
|
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_dynamic_linker %v\n", plan9quote(p))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "dynexport" {
|
|
|
|
|
verb = "cgo_export_dynamic"
|
|
|
|
|
}
|
|
|
|
|
if verb == "cgo_export_static" || verb == "cgo_export_dynamic" {
|
2015-02-23 16:07:24 -05:00
|
|
|
local := getimpsym(&q)
|
|
|
|
|
var remote string
|
2015-02-13 14:40:36 -05:00
|
|
|
if local == "" {
|
|
|
|
|
goto err2
|
|
|
|
|
}
|
|
|
|
|
if !more(&q) {
|
|
|
|
|
pragcgobuf += fmt.Sprintf("%s %v\n", verb, plan9quote(local))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remote = getimpsym(&q)
|
|
|
|
|
if remote == "" {
|
|
|
|
|
goto err2
|
|
|
|
|
}
|
|
|
|
|
pragcgobuf += fmt.Sprintf("%s %v %v\n", verb, plan9quote(local), plan9quote(remote))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
err2:
|
|
|
|
|
Yyerror("usage: //go:%s local [remote]", verb)
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "cgo_import_dynamic" || verb == "dynimport" {
|
|
|
|
|
var ok bool
|
2015-02-23 16:07:24 -05:00
|
|
|
local := getimpsym(&q)
|
|
|
|
|
var p string
|
|
|
|
|
var remote string
|
2015-02-13 14:40:36 -05:00
|
|
|
if local == "" {
|
|
|
|
|
goto err3
|
|
|
|
|
}
|
|
|
|
|
if !more(&q) {
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v\n", plan9quote(local))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
remote = getimpsym(&q)
|
|
|
|
|
if remote == "" {
|
|
|
|
|
goto err3
|
|
|
|
|
}
|
|
|
|
|
if !more(&q) {
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v\n", plan9quote(local), plan9quote(remote))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p, ok = getquoted(&q)
|
|
|
|
|
if !ok {
|
|
|
|
|
goto err3
|
|
|
|
|
}
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_import_dynamic %v %v %v\n", plan9quote(local), plan9quote(remote), plan9quote(p))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
err3:
|
|
|
|
|
Yyerror("usage: //go:cgo_import_dynamic local [remote [\"library\"]]")
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "cgo_import_static" {
|
2015-02-23 16:07:24 -05:00
|
|
|
local := getimpsym(&q)
|
2015-02-13 14:40:36 -05:00
|
|
|
if local == "" || more(&q) {
|
2015-03-02 12:35:15 -05:00
|
|
|
Yyerror("usage: //go:cgo_import_static local")
|
|
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_import_static %v\n", plan9quote(local))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if verb == "cgo_ldflag" {
|
|
|
|
|
var ok bool
|
2015-02-23 16:07:24 -05:00
|
|
|
var p string
|
2015-02-13 14:40:36 -05:00
|
|
|
p, ok = getquoted(&q)
|
|
|
|
|
if !ok {
|
2015-03-02 12:35:15 -05:00
|
|
|
Yyerror("usage: //go:cgo_ldflag \"arg\"")
|
|
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
pragcgobuf += fmt.Sprintf("cgo_ldflag %v\n", plan9quote(p))
|
2015-03-02 12:35:15 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type yy struct{}
|
|
|
|
|
|
|
|
|
|
var yymsg []struct {
|
|
|
|
|
yystate, yychar int
|
|
|
|
|
msg string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (yy) Lex(v *yySymType) int {
|
|
|
|
|
return int(yylex(v))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (yy) Error(msg string) {
|
|
|
|
|
Yyerror("%s", msg)
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-23 14:02:27 -05:00
|
|
|
var theparser yyParser
|
|
|
|
|
var parsing bool
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
func yyparse() {
|
2015-02-23 14:02:27 -05:00
|
|
|
theparser = yyNewParser()
|
|
|
|
|
parsing = true
|
|
|
|
|
theparser.Parse(yy{})
|
|
|
|
|
parsing = false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func yylex(yylval *yySymType) int32 {
|
2015-02-23 16:07:24 -05:00
|
|
|
lx := int(_yylex(yylval))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
if curio.nlsemi != 0 && lx == EOF {
|
|
|
|
|
// Treat EOF as "end of line" for the purposes
|
|
|
|
|
// of inserting a semicolon.
|
|
|
|
|
lx = ';'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch lx {
|
|
|
|
|
case LNAME,
|
|
|
|
|
LLITERAL,
|
|
|
|
|
LBREAK,
|
|
|
|
|
LCONTINUE,
|
|
|
|
|
LFALL,
|
|
|
|
|
LRETURN,
|
|
|
|
|
LINC,
|
|
|
|
|
LDEC,
|
|
|
|
|
')',
|
|
|
|
|
'}',
|
|
|
|
|
']':
|
|
|
|
|
curio.nlsemi = 1
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
curio.nlsemi = 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Track last two tokens returned by yylex.
|
|
|
|
|
yyprev = yylast
|
|
|
|
|
|
|
|
|
|
yylast = lx
|
|
|
|
|
return int32(lx)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getc() int {
|
2015-02-23 16:07:24 -05:00
|
|
|
c := curio.peekc
|
2015-02-13 14:40:36 -05:00
|
|
|
if c != 0 {
|
|
|
|
|
curio.peekc = curio.peekc1
|
|
|
|
|
curio.peekc1 = 0
|
|
|
|
|
goto check
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if curio.bin == nil {
|
|
|
|
|
if len(curio.cp) == 0 {
|
|
|
|
|
c = 0
|
|
|
|
|
} else {
|
|
|
|
|
c = int(curio.cp[0])
|
|
|
|
|
curio.cp = curio.cp[1:]
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2015-02-23 16:07:24 -05:00
|
|
|
var c1 int
|
|
|
|
|
var c2 int
|
2015-02-13 14:40:36 -05:00
|
|
|
loop:
|
|
|
|
|
c = obj.Bgetc(curio.bin)
|
|
|
|
|
if c == 0xef {
|
|
|
|
|
c1 = obj.Bgetc(curio.bin)
|
|
|
|
|
c2 = obj.Bgetc(curio.bin)
|
|
|
|
|
if c1 == 0xbb && c2 == 0xbf {
|
|
|
|
|
yyerrorl(int(lexlineno), "Unicode (UTF-8) BOM in middle of file")
|
|
|
|
|
goto loop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
obj.Bungetc(curio.bin)
|
|
|
|
|
obj.Bungetc(curio.bin)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
check:
|
|
|
|
|
switch c {
|
|
|
|
|
case 0:
|
|
|
|
|
if curio.bin != nil {
|
|
|
|
|
Yyerror("illegal NUL byte")
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
// insert \n at EOF
|
|
|
|
|
case EOF:
|
|
|
|
|
if curio.eofnl != 0 || curio.last == '\n' {
|
|
|
|
|
return EOF
|
|
|
|
|
}
|
|
|
|
|
curio.eofnl = 1
|
|
|
|
|
c = '\n'
|
|
|
|
|
fallthrough
|
|
|
|
|
|
|
|
|
|
case '\n':
|
|
|
|
|
if pushedio.bin == nil {
|
|
|
|
|
lexlineno++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
curio.last = c
|
|
|
|
|
return c
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func ungetc(c int) {
|
|
|
|
|
curio.peekc1 = curio.peekc
|
|
|
|
|
curio.peekc = c
|
|
|
|
|
if c == '\n' && pushedio.bin == nil {
|
|
|
|
|
lexlineno--
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getr() int32 {
|
|
|
|
|
var buf [utf8.UTFMax]byte
|
|
|
|
|
|
|
|
|
|
for i := 0; ; i++ {
|
|
|
|
|
c := getc()
|
|
|
|
|
if i == 0 && c < utf8.RuneSelf {
|
|
|
|
|
return int32(c)
|
|
|
|
|
}
|
|
|
|
|
buf[i] = byte(c)
|
|
|
|
|
if i+1 == len(buf) || utf8.FullRune(buf[:i+1]) {
|
|
|
|
|
r, w := utf8.DecodeRune(buf[:i+1])
|
|
|
|
|
if r == utf8.RuneError && w == 1 {
|
|
|
|
|
lineno = lexlineno
|
2015-03-02 15:22:19 -05:00
|
|
|
// The string conversion here makes a copy for passing
|
|
|
|
|
// to fmt.Printf, so that buf itself does not escape and can
|
|
|
|
|
// be allocated on the stack.
|
|
|
|
|
Yyerror("illegal UTF-8 sequence % x", string(buf[:i+1]))
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
return int32(r)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-17 22:13:49 -05:00
|
|
|
func escchar(e int, escflg *int, val *int64) bool {
|
2015-02-13 14:40:36 -05:00
|
|
|
*escflg = 0
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
c := int(getr())
|
2015-02-13 14:40:36 -05:00
|
|
|
switch c {
|
|
|
|
|
case EOF:
|
|
|
|
|
Yyerror("eof in string")
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case '\n':
|
|
|
|
|
Yyerror("newline in string")
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case '\\':
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if c == e {
|
2015-02-17 22:13:49 -05:00
|
|
|
return true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
*val = int64(c)
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-23 16:07:24 -05:00
|
|
|
u := 0
|
2015-02-13 14:40:36 -05:00
|
|
|
c = int(getr())
|
2015-02-23 16:07:24 -05:00
|
|
|
var i int
|
2015-02-13 14:40:36 -05:00
|
|
|
switch c {
|
|
|
|
|
case 'x':
|
|
|
|
|
*escflg = 1 // it's a byte
|
|
|
|
|
i = 2
|
|
|
|
|
goto hex
|
|
|
|
|
|
|
|
|
|
case 'u':
|
|
|
|
|
i = 4
|
|
|
|
|
u = 1
|
|
|
|
|
goto hex
|
|
|
|
|
|
|
|
|
|
case 'U':
|
|
|
|
|
i = 8
|
|
|
|
|
u = 1
|
|
|
|
|
goto hex
|
|
|
|
|
|
|
|
|
|
case '0',
|
|
|
|
|
'1',
|
|
|
|
|
'2',
|
|
|
|
|
'3',
|
|
|
|
|
'4',
|
|
|
|
|
'5',
|
|
|
|
|
'6',
|
|
|
|
|
'7':
|
|
|
|
|
*escflg = 1 // it's a byte
|
2015-03-02 12:35:15 -05:00
|
|
|
l := int64(c) - '0'
|
|
|
|
|
for i := 2; i > 0; i-- {
|
|
|
|
|
c = getc()
|
|
|
|
|
if c >= '0' && c <= '7' {
|
|
|
|
|
l = l*8 + int64(c) - '0'
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Yyerror("non-octal character in escape sequence: %c", c)
|
|
|
|
|
ungetc(c)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if l > 255 {
|
|
|
|
|
Yyerror("octal escape value > 255: %d", l)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*val = l
|
|
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case 'a':
|
|
|
|
|
c = '\a'
|
|
|
|
|
case 'b':
|
|
|
|
|
c = '\b'
|
|
|
|
|
case 'f':
|
|
|
|
|
c = '\f'
|
|
|
|
|
case 'n':
|
|
|
|
|
c = '\n'
|
|
|
|
|
case 'r':
|
|
|
|
|
c = '\r'
|
|
|
|
|
case 't':
|
|
|
|
|
c = '\t'
|
|
|
|
|
case 'v':
|
|
|
|
|
c = '\v'
|
|
|
|
|
case '\\':
|
|
|
|
|
c = '\\'
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
if c != e {
|
|
|
|
|
Yyerror("unknown escape sequence: %c", c)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*val = int64(c)
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
hex:
|
2015-03-02 12:35:15 -05:00
|
|
|
l := int64(0)
|
2015-02-13 14:40:36 -05:00
|
|
|
for ; i > 0; i-- {
|
|
|
|
|
c = getc()
|
|
|
|
|
if c >= '0' && c <= '9' {
|
|
|
|
|
l = l*16 + int64(c) - '0'
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c >= 'a' && c <= 'f' {
|
|
|
|
|
l = l*16 + int64(c) - 'a' + 10
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if c >= 'A' && c <= 'F' {
|
|
|
|
|
l = l*16 + int64(c) - 'A' + 10
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Yyerror("non-hex character in escape sequence: %c", c)
|
|
|
|
|
ungetc(c)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if u != 0 && (l > utf8.MaxRune || (0xd800 <= l && l < 0xe000)) {
|
|
|
|
|
Yyerror("invalid Unicode code point in escape sequence: %#x", l)
|
|
|
|
|
l = utf8.RuneError
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*val = l
|
2015-02-17 22:13:49 -05:00
|
|
|
return false
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var syms = []struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{
|
|
|
|
|
/* name lexical etype op
|
|
|
|
|
*/
|
|
|
|
|
/* basic types */
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"int8", LNAME, TINT8, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"int16", LNAME, TINT16, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"int32", LNAME, TINT32, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"int64", LNAME, TINT64, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"uint8", LNAME, TUINT8, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"uint16", LNAME, TUINT16, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"uint32", LNAME, TUINT32, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"uint64", LNAME, TUINT64, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"float32", LNAME, TFLOAT32, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"float64", LNAME, TFLOAT64, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"complex64", LNAME, TCOMPLEX64, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"complex128", LNAME, TCOMPLEX128, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"bool", LNAME, TBOOL, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"string", LNAME, TSTRING, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"any", LNAME, TANY, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"break", LBREAK, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"case", LCASE, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"chan", LCHAN, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"const", LCONST, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"continue", LCONTINUE, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"default", LDEFAULT, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"else", LELSE, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"defer", LDEFER, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"fallthrough", LFALL, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"for", LFOR, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"func", LFUNC, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"go", LGO, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"goto", LGOTO, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"if", LIF, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"import", LIMPORT, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"interface", LINTERFACE, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"map", LMAP, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"package", LPACKAGE, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"range", LRANGE, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"return", LRETURN, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"select", LSELECT, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"struct", LSTRUCT, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"switch", LSWITCH, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"type", LTYPE, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"var", LVAR, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"append", LNAME, Txxx, OAPPEND},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"cap", LNAME, Txxx, OCAP},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"close", LNAME, Txxx, OCLOSE},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"complex", LNAME, Txxx, OCOMPLEX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"copy", LNAME, Txxx, OCOPY},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"delete", LNAME, Txxx, ODELETE},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"imag", LNAME, Txxx, OIMAG},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"len", LNAME, Txxx, OLEN},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"make", LNAME, Txxx, OMAKE},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"new", LNAME, Txxx, ONEW},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"panic", LNAME, Txxx, OPANIC},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"print", LNAME, Txxx, OPRINT},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"println", LNAME, Txxx, OPRINTN},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"real", LNAME, Txxx, OREAL},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"recover", LNAME, Txxx, ORECOVER},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"notwithstanding", LIGNORE, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"thetruthofthematter", LIGNORE, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"despiteallobjections", LIGNORE, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"whereas", LIGNORE, Txxx, OXXX},
|
|
|
|
|
struct {
|
|
|
|
|
name string
|
|
|
|
|
lexical int
|
|
|
|
|
etype int
|
|
|
|
|
op int
|
|
|
|
|
}{"insofaras", LIGNORE, Txxx, OXXX},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func lexinit() {
|
|
|
|
|
var lex int
|
|
|
|
|
var s *Sym
|
|
|
|
|
var s1 *Sym
|
|
|
|
|
var t *Type
|
|
|
|
|
var etype int
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* initialize basic types array
|
|
|
|
|
* initialize known symbols
|
|
|
|
|
*/
|
2015-02-23 16:07:24 -05:00
|
|
|
for i := 0; i < len(syms); i++ {
|
2015-02-13 14:40:36 -05:00
|
|
|
lex = syms[i].lexical
|
|
|
|
|
s = Lookup(syms[i].name)
|
|
|
|
|
s.Lexical = uint16(lex)
|
|
|
|
|
|
|
|
|
|
etype = syms[i].etype
|
|
|
|
|
if etype != Txxx {
|
|
|
|
|
if etype < 0 || etype >= len(Types) {
|
|
|
|
|
Fatal("lexinit: %s bad etype", s.Name)
|
|
|
|
|
}
|
|
|
|
|
s1 = Pkglookup(syms[i].name, builtinpkg)
|
|
|
|
|
t = Types[etype]
|
|
|
|
|
if t == nil {
|
|
|
|
|
t = typ(etype)
|
|
|
|
|
t.Sym = s1
|
|
|
|
|
|
|
|
|
|
if etype != TANY && etype != TSTRING {
|
|
|
|
|
dowidth(t)
|
|
|
|
|
}
|
|
|
|
|
Types[etype] = t
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s1.Lexical = LNAME
|
|
|
|
|
s1.Def = typenod(t)
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
etype = syms[i].op
|
|
|
|
|
if etype != OXXX {
|
|
|
|
|
s1 = Pkglookup(syms[i].name, builtinpkg)
|
|
|
|
|
s1.Lexical = LNAME
|
|
|
|
|
s1.Def = Nod(ONAME, nil, nil)
|
|
|
|
|
s1.Def.Sym = s1
|
|
|
|
|
s1.Def.Etype = uint8(etype)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// logically, the type of a string literal.
|
|
|
|
|
// types[TSTRING] is the named type string
|
|
|
|
|
// (the type of x in var x string or var x = "hello").
|
|
|
|
|
// this is the ideal form
|
|
|
|
|
// (the type of x in const x = "hello").
|
|
|
|
|
idealstring = typ(TSTRING)
|
|
|
|
|
|
|
|
|
|
idealbool = typ(TBOOL)
|
|
|
|
|
|
|
|
|
|
s = Pkglookup("true", builtinpkg)
|
2015-02-17 22:13:49 -05:00
|
|
|
s.Def = Nodbool(true)
|
2015-02-13 14:40:36 -05:00
|
|
|
s.Def.Sym = Lookup("true")
|
|
|
|
|
s.Def.Type = idealbool
|
|
|
|
|
|
|
|
|
|
s = Pkglookup("false", builtinpkg)
|
2015-02-17 22:13:49 -05:00
|
|
|
s.Def = Nodbool(false)
|
2015-02-13 14:40:36 -05:00
|
|
|
s.Def.Sym = Lookup("false")
|
|
|
|
|
s.Def.Type = idealbool
|
|
|
|
|
|
|
|
|
|
s = Lookup("_")
|
|
|
|
|
s.Block = -100
|
|
|
|
|
s.Def = Nod(ONAME, nil, nil)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
Types[TBLANK] = typ(TBLANK)
|
|
|
|
|
s.Def.Type = Types[TBLANK]
|
|
|
|
|
nblank = s.Def
|
|
|
|
|
|
|
|
|
|
s = Pkglookup("_", builtinpkg)
|
|
|
|
|
s.Block = -100
|
|
|
|
|
s.Def = Nod(ONAME, nil, nil)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
Types[TBLANK] = typ(TBLANK)
|
|
|
|
|
s.Def.Type = Types[TBLANK]
|
|
|
|
|
|
|
|
|
|
Types[TNIL] = typ(TNIL)
|
|
|
|
|
s = Pkglookup("nil", builtinpkg)
|
2015-02-23 16:07:24 -05:00
|
|
|
var v Val
|
2015-02-13 14:40:36 -05:00
|
|
|
v.Ctype = CTNIL
|
|
|
|
|
s.Def = nodlit(v)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func lexinit1() {
|
|
|
|
|
// t = interface { Error() string }
|
2015-02-23 16:07:24 -05:00
|
|
|
rcvr := typ(TSTRUCT)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
rcvr.Type = typ(TFIELD)
|
|
|
|
|
rcvr.Type.Type = Ptrto(typ(TSTRUCT))
|
|
|
|
|
rcvr.Funarg = 1
|
2015-02-23 16:07:24 -05:00
|
|
|
in := typ(TSTRUCT)
|
2015-02-13 14:40:36 -05:00
|
|
|
in.Funarg = 1
|
2015-02-23 16:07:24 -05:00
|
|
|
out := typ(TSTRUCT)
|
2015-02-13 14:40:36 -05:00
|
|
|
out.Type = typ(TFIELD)
|
|
|
|
|
out.Type.Type = Types[TSTRING]
|
|
|
|
|
out.Funarg = 1
|
2015-02-23 16:07:24 -05:00
|
|
|
f := typ(TFUNC)
|
2015-02-13 14:40:36 -05:00
|
|
|
*getthis(f) = rcvr
|
|
|
|
|
*Getoutarg(f) = out
|
|
|
|
|
*getinarg(f) = in
|
|
|
|
|
f.Thistuple = 1
|
|
|
|
|
f.Intuple = 0
|
|
|
|
|
f.Outnamed = 0
|
|
|
|
|
f.Outtuple = 1
|
2015-02-23 16:07:24 -05:00
|
|
|
t := typ(TINTER)
|
2015-02-13 14:40:36 -05:00
|
|
|
t.Type = typ(TFIELD)
|
|
|
|
|
t.Type.Sym = Lookup("Error")
|
|
|
|
|
t.Type.Type = f
|
|
|
|
|
|
|
|
|
|
// error type
|
2015-02-23 16:07:24 -05:00
|
|
|
s := Lookup("error")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
s.Lexical = LNAME
|
2015-02-23 16:07:24 -05:00
|
|
|
s1 := Pkglookup("error", builtinpkg)
|
2015-02-13 14:40:36 -05:00
|
|
|
errortype = t
|
|
|
|
|
errortype.Sym = s1
|
|
|
|
|
s1.Lexical = LNAME
|
|
|
|
|
s1.Def = typenod(errortype)
|
|
|
|
|
|
|
|
|
|
// byte alias
|
|
|
|
|
s = Lookup("byte")
|
|
|
|
|
|
|
|
|
|
s.Lexical = LNAME
|
|
|
|
|
s1 = Pkglookup("byte", builtinpkg)
|
|
|
|
|
bytetype = typ(TUINT8)
|
|
|
|
|
bytetype.Sym = s1
|
|
|
|
|
s1.Lexical = LNAME
|
|
|
|
|
s1.Def = typenod(bytetype)
|
|
|
|
|
|
|
|
|
|
// rune alias
|
|
|
|
|
s = Lookup("rune")
|
|
|
|
|
|
|
|
|
|
s.Lexical = LNAME
|
|
|
|
|
s1 = Pkglookup("rune", builtinpkg)
|
|
|
|
|
runetype = typ(TINT32)
|
|
|
|
|
runetype.Sym = s1
|
|
|
|
|
s1.Lexical = LNAME
|
|
|
|
|
s1.Def = typenod(runetype)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func lexfini() {
|
|
|
|
|
var s *Sym
|
|
|
|
|
var lex int
|
|
|
|
|
var etype int
|
|
|
|
|
var i int
|
|
|
|
|
|
|
|
|
|
for i = 0; i < len(syms); i++ {
|
|
|
|
|
lex = syms[i].lexical
|
|
|
|
|
if lex != LNAME {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
s = Lookup(syms[i].name)
|
|
|
|
|
s.Lexical = uint16(lex)
|
|
|
|
|
|
|
|
|
|
etype = syms[i].etype
|
|
|
|
|
if etype != Txxx && (etype != TANY || Debug['A'] != 0) && s.Def == nil {
|
|
|
|
|
s.Def = typenod(Types[etype])
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
etype = syms[i].op
|
|
|
|
|
if etype != OXXX && s.Def == nil {
|
|
|
|
|
s.Def = Nod(ONAME, nil, nil)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
s.Def.Etype = uint8(etype)
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// backend-specific builtin types (e.g. int).
|
|
|
|
|
for i = range Thearch.Typedefs {
|
|
|
|
|
s = Lookup(Thearch.Typedefs[i].Name)
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
s.Def = typenod(Types[Thearch.Typedefs[i].Etype])
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// there's only so much table-driven we can handle.
|
|
|
|
|
// these are special cases.
|
|
|
|
|
s = Lookup("byte")
|
|
|
|
|
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
s.Def = typenod(bytetype)
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("error")
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
s.Def = typenod(errortype)
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("rune")
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
s.Def = typenod(runetype)
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("nil")
|
|
|
|
|
if s.Def == nil {
|
2015-02-23 16:07:24 -05:00
|
|
|
var v Val
|
2015-02-13 14:40:36 -05:00
|
|
|
v.Ctype = CTNIL
|
|
|
|
|
s.Def = nodlit(v)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("iota")
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
s.Def = Nod(OIOTA, nil, nil)
|
|
|
|
|
s.Def.Sym = s
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("true")
|
|
|
|
|
if s.Def == nil {
|
2015-02-17 22:13:49 -05:00
|
|
|
s.Def = Nodbool(true)
|
2015-02-13 14:40:36 -05:00
|
|
|
s.Def.Sym = s
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = Lookup("false")
|
|
|
|
|
if s.Def == nil {
|
2015-02-17 22:13:49 -05:00
|
|
|
s.Def = Nodbool(false)
|
2015-02-13 14:40:36 -05:00
|
|
|
s.Def.Sym = s
|
|
|
|
|
s.Origpkg = builtinpkg
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nodfp = Nod(ONAME, nil, nil)
|
|
|
|
|
nodfp.Type = Types[TINT32]
|
|
|
|
|
nodfp.Xoffset = 0
|
|
|
|
|
nodfp.Class = PPARAM
|
|
|
|
|
nodfp.Sym = Lookup(".fp")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var lexn = []struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LANDAND, "ANDAND"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LANDNOT, "ANDNOT"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LASOP, "ASOP"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LBREAK, "BREAK"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LCASE, "CASE"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LCHAN, "CHAN"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LCOLAS, "COLAS"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LCOMM, "<-"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LCONST, "CONST"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LCONTINUE, "CONTINUE"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LDDD, "..."},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LDEC, "DEC"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LDEFAULT, "DEFAULT"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LDEFER, "DEFER"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LELSE, "ELSE"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LEQ, "EQ"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LFALL, "FALL"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LFOR, "FOR"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LFUNC, "FUNC"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LGE, "GE"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LGO, "GO"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LGOTO, "GOTO"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LGT, "GT"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LIF, "IF"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LIMPORT, "IMPORT"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LINC, "INC"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LINTERFACE, "INTERFACE"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LLE, "LE"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LLITERAL, "LITERAL"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LLSH, "LSH"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LLT, "LT"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LMAP, "MAP"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LNAME, "NAME"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LNE, "NE"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LOROR, "OROR"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LPACKAGE, "PACKAGE"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LRANGE, "RANGE"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LRETURN, "RETURN"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LRSH, "RSH"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LSELECT, "SELECT"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LSTRUCT, "STRUCT"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LSWITCH, "SWITCH"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LTYPE, "TYPE"},
|
|
|
|
|
struct {
|
|
|
|
|
lex int
|
|
|
|
|
name string
|
|
|
|
|
}{LVAR, "VAR"},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var lexname_buf string
|
|
|
|
|
|
|
|
|
|
func lexname(lex int) string {
|
2015-02-23 16:07:24 -05:00
|
|
|
for i := 0; i < len(lexn); i++ {
|
2015-02-13 14:40:36 -05:00
|
|
|
if lexn[i].lex == lex {
|
|
|
|
|
return lexn[i].name
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
lexname_buf = fmt.Sprintf("LEX-%d", lex)
|
|
|
|
|
return lexname_buf
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var yytfix = []struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"$end", "EOF"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LLITERAL", "literal"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LASOP", "op="},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LBREAK", "break"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LCASE", "case"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LCHAN", "chan"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LCOLAS", ":="},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LCONST", "const"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LCONTINUE", "continue"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LDDD", "..."},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LDEFAULT", "default"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LDEFER", "defer"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LELSE", "else"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LFALL", "fallthrough"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LFOR", "for"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LFUNC", "func"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LGO", "go"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LGOTO", "goto"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LIF", "if"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LIMPORT", "import"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LINTERFACE", "interface"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LMAP", "map"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LNAME", "name"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LPACKAGE", "package"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LRANGE", "range"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LRETURN", "return"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LSELECT", "select"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LSTRUCT", "struct"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LSWITCH", "switch"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LTYPE", "type"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LVAR", "var"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LANDAND", "&&"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LANDNOT", "&^"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LBODY", "{"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LCOMM", "<-"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LDEC", "--"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LINC", "++"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LEQ", "=="},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LGE", ">="},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LGT", ">"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LLE", "<="},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LLT", "<"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LLSH", "<<"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LRSH", ">>"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LOROR", "||"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"LNE", "!="},
|
|
|
|
|
// spell out to avoid confusion with punctuation in error messages
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"';'", "semicolon or newline"},
|
|
|
|
|
struct {
|
|
|
|
|
have string
|
|
|
|
|
want string
|
|
|
|
|
}{"','", "comma"},
|
|
|
|
|
}
|
|
|
|
|
|
2015-03-02 16:03:26 -05:00
|
|
|
func pkgnotused(lineno int, path string, name string) {
|
2015-02-13 14:40:36 -05:00
|
|
|
// If the package was imported with a name other than the final
|
|
|
|
|
// import path element, show it explicitly in the error message.
|
|
|
|
|
// Note that this handles both renamed imports and imports of
|
|
|
|
|
// packages containing unconventional package declarations.
|
|
|
|
|
// Note that this uses / always, even on Windows, because Go import
|
|
|
|
|
// paths always use forward slashes.
|
2015-03-02 16:03:26 -05:00
|
|
|
elem := path
|
2015-02-13 14:40:36 -05:00
|
|
|
if i := strings.LastIndex(elem, "/"); i >= 0 {
|
|
|
|
|
elem = elem[i+1:]
|
|
|
|
|
}
|
|
|
|
|
if name == "" || elem == name {
|
2015-03-02 16:03:26 -05:00
|
|
|
yyerrorl(int(lineno), "imported and not used: %q", path)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2015-03-02 16:03:26 -05:00
|
|
|
yyerrorl(int(lineno), "imported and not used: %q as %s", path, name)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func mkpackage(pkgname string) {
|
|
|
|
|
if localpkg.Name == "" {
|
|
|
|
|
if pkgname == "_" {
|
|
|
|
|
Yyerror("invalid package name _")
|
|
|
|
|
}
|
|
|
|
|
localpkg.Name = pkgname
|
|
|
|
|
} else {
|
|
|
|
|
if pkgname != localpkg.Name {
|
|
|
|
|
Yyerror("package %s; expected %s", pkgname, localpkg.Name)
|
|
|
|
|
}
|
2015-03-02 16:21:15 -05:00
|
|
|
for _, s := range localpkg.Syms {
|
|
|
|
|
if s.Def == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if s.Def.Op == OPACK {
|
|
|
|
|
// throw away top-level package name leftover
|
|
|
|
|
// from previous file.
|
|
|
|
|
// leave s->block set to cause redeclaration
|
|
|
|
|
// errors if a conflicting top-level name is
|
|
|
|
|
// introduced by a different file.
|
2015-03-06 21:18:41 +11:00
|
|
|
if !s.Def.Used && nsyntaxerrors == 0 {
|
2015-03-02 16:21:15 -05:00
|
|
|
pkgnotused(int(s.Def.Lineno), s.Def.Pkg.Path, s.Name)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-02 16:21:15 -05:00
|
|
|
s.Def = nil
|
|
|
|
|
continue
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-03-02 16:21:15 -05:00
|
|
|
if s.Def.Sym != s {
|
|
|
|
|
// throw away top-level name left over
|
|
|
|
|
// from previous import . "x"
|
2015-03-06 21:18:41 +11:00
|
|
|
if s.Def.Pack != nil && !s.Def.Pack.Used && nsyntaxerrors == 0 {
|
2015-03-02 16:21:15 -05:00
|
|
|
pkgnotused(int(s.Def.Pack.Lineno), s.Def.Pack.Pkg.Path, "")
|
2015-03-06 21:18:41 +11:00
|
|
|
s.Def.Pack.Used = true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2015-03-02 16:21:15 -05:00
|
|
|
|
|
|
|
|
s.Def = nil
|
|
|
|
|
continue
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if outfile == "" {
|
2015-02-23 16:07:24 -05:00
|
|
|
p := infile
|
2015-02-13 14:40:36 -05:00
|
|
|
if i := strings.LastIndex(p, "/"); i >= 0 {
|
|
|
|
|
p = p[i+1:]
|
|
|
|
|
}
|
|
|
|
|
if Ctxt.Windows != 0 {
|
|
|
|
|
if i := strings.LastIndex(p, `\`); i >= 0 {
|
|
|
|
|
p = p[i+1:]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
namebuf = p
|
|
|
|
|
if i := strings.LastIndex(namebuf, "."); i >= 0 {
|
|
|
|
|
namebuf = namebuf[:i]
|
|
|
|
|
}
|
|
|
|
|
outfile = fmt.Sprintf("%s.%c", namebuf, Thearch.Thechar)
|
|
|
|
|
}
|
|
|
|
|
}
|