Updates #10510.
Change-Id: Ib4d39943969d18517b373292b83d87650d5df12a
Reviewed-on: https://go-review.googlesource.com/12787
Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
+++ /dev/null
-// Inferno utils/6a/a.h and lex.c.
-// http://code.google.com/p/inferno-os/source/browse/utils/6a/a.h
-// http://code.google.com/p/inferno-os/source/browse/utils/6a/lex.c
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-// Package asm holds code shared among the assemblers.
-package asm
-
-import (
- "flag"
- "fmt"
- "log"
- "os"
- "path/filepath"
- "strconv"
- "strings"
-
- "cmd/internal/obj"
-)
-
-// Initialized by client.
-var (
- LSCONST int
- LCONST int
- LFCONST int
- LNAME int
- LVAR int
- LLAB int
-
- Thechar rune
- Thestring string
- Thelinkarch *obj.LinkArch
-
- Arches map[string]*obj.LinkArch
-
- Cclean func()
- Yyparse func()
- Syminit func(*Sym)
-
- Lexinit []Lextab
-)
-
-type Lextab struct {
- Name string
- Type int
- Value int64
-}
-
-const (
- MAXALIGN = 7
- FPCHIP = 1
- NSYMB = 500
- BUFSIZ = 8192
- HISTSZ = 20
- EOF = -1
- IGN = -2
- NHASH = 503
- NMACRO = 10
-)
-
-const (
- CLAST = iota
- CMACARG
- CMACRO
- CPREPROC
-)
-
-type Macro struct {
- Text string
- Narg int
- Dots bool
-}
-
-type Sym struct {
- Link *Sym
- Ref *Ref
- Macro *Macro
- Value int64
- Type int
- Name string
- Labelname string
- Sym int8
-}
-
-type Ref struct {
- Class int
-}
-
-type Io struct {
- Link *Io
- P []byte
- F *os.File
- B [1024]byte
-}
-
-var fi struct {
- P []byte
-}
-
-var (
- debug [256]int
- hash = map[string]*Sym{}
- Dlist []string
- newflag int
- hunk string
- include []string
- iofree *Io
- ionext *Io
- iostack *Io
- Lineno int32
- nerrors int
- nhunk int32
- ninclude int
- nsymb int32
- nullgen obj.Addr
- outfile string
- Pass int
- PC int32
- peekc int = IGN
- sym int
- symb string
- thunk int32
- obuf obj.Biobuf
- Ctxt *obj.Link
- bstdout obj.Biobuf
-)
-
-func dodef(p string) {
- Dlist = append(Dlist, p)
-}
-
-func usage() {
- fmt.Printf("usage: %ca [options] file.c...\n", Thechar)
- flag.PrintDefaults()
- errorexit()
-}
-
-func Main() {
- // Allow GOARCH=Thestring or GOARCH=Thestringsuffix,
- // but not other values.
- p := obj.Getgoarch()
-
- if !strings.HasPrefix(p, Thestring) {
- log.Fatalf("cannot use %cc with GOARCH=%s", Thechar, p)
- }
- if p != Thestring {
- Thelinkarch = Arches[p]
- if Thelinkarch == nil {
- log.Fatalf("unknown arch %s", p)
- }
- }
-
- Ctxt = obj.Linknew(Thelinkarch)
- Ctxt.Diag = Yyerror
- Ctxt.Bso = &bstdout
- Ctxt.Enforce_data_order = 1
- bstdout = *obj.Binitw(os.Stdout)
-
- debug = [256]int{}
- cinit()
- outfile = ""
- setinclude(".")
-
- flag.Var(flagFn(dodef), "D", "name[=value]: add #define")
- flag.Var(flagFn(setinclude), "I", "dir: add dir to include path")
- flag.Var((*count)(&debug['S']), "S", "print assembly and machine code")
- flag.Var((*count)(&debug['m']), "m", "debug preprocessor macros")
- flag.StringVar(&outfile, "o", "", "file: set output file")
- flag.StringVar(&Ctxt.LineHist.TrimPathPrefix, "trimpath", "", "prefix: remove prefix from recorded source file paths")
-
- flag.Parse()
-
- Ctxt.Debugasm = int32(debug['S'])
-
- if flag.NArg() < 1 {
- usage()
- }
- if flag.NArg() > 1 {
- fmt.Printf("can't assemble multiple files\n")
- errorexit()
- }
-
- if assemble(flag.Arg(0)) != 0 {
- errorexit()
- }
- bstdout.Flush()
- if nerrors > 0 {
- errorexit()
- }
-}
-
-func assemble(file string) int {
- if outfile == "" {
- outfile = strings.TrimSuffix(filepath.Base(file), ".s") + "." + string(Thechar)
- }
-
- of, err := os.Create(outfile)
- if err != nil {
- Yyerror("%ca: cannot create %s", Thechar, outfile)
- errorexit()
- }
-
- obuf = *obj.Binitw(of)
- fmt.Fprintf(&obuf, "go object %s %s %s\n", obj.Getgoos(), obj.Getgoarch(), obj.Getgoversion())
- fmt.Fprintf(&obuf, "!\n")
-
- var i int
- for Pass = 1; Pass <= 2; Pass++ {
- pinit(file)
- for i = 0; i < len(Dlist); i++ {
- dodefine(Dlist[i])
- }
- Yyparse()
- Cclean()
- if nerrors != 0 {
- return nerrors
- }
- }
-
- obj.Writeobjdirect(Ctxt, &obuf)
- obuf.Flush()
- return 0
-}
-
-func cinit() {
- for i := 0; i < len(Lexinit); i++ {
- s := Lookup(Lexinit[i].Name)
- if s.Type != LNAME {
- Yyerror("double initialization %s", Lexinit[i].Name)
- }
- s.Type = Lexinit[i].Type
- s.Value = Lexinit[i].Value
- }
-}
-
-func syminit(s *Sym) {
- s.Type = LNAME
- s.Value = 0
-}
-
-type flagFn func(string)
-
-func (flagFn) String() string {
- return "<arg>"
-}
-
-func (f flagFn) Set(s string) error {
- f(s)
- return nil
-}
-
-type yyImpl struct{}
-
-// count is a flag.Value that is like a flag.Bool and a flag.Int.
-// If used as -name, it increments the count, but -name=x sets the count.
-// Used for verbose flag -v.
-type count int
-
-func (c *count) String() string {
- return fmt.Sprint(int(*c))
-}
-
-func (c *count) Set(s string) error {
- switch s {
- case "true":
- *c++
- case "false":
- *c = 0
- default:
- n, err := strconv.Atoi(s)
- if err != nil {
- return fmt.Errorf("invalid count %q", s)
- }
- *c = count(n)
- }
- return nil
-}
-
-func (c *count) IsBoolFlag() bool {
- return true
-}
+++ /dev/null
-// Inferno utils/cc/lexbody
-// http://code.Google.Com/p/inferno-os/source/browse/utils/cc/lexbody
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.Net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.Vitanuova.Com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.Net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package asm
-
-import (
- "bytes"
- "fmt"
- "os"
- "strconv"
- "strings"
- "unicode/utf8"
-
- "cmd/internal/obj"
-)
-
-/*
- * common code for all the assemblers
- */
-func pragpack() {
- for getnsc() != '\n' {
- }
-}
-
-func pragvararg() {
- for getnsc() != '\n' {
- }
-}
-
-func pragcgo(name string) {
- for getnsc() != '\n' {
- }
-}
-
-func pragfpround() {
- for getnsc() != '\n' {
- }
-}
-
-func pragtextflag() {
- for getnsc() != '\n' {
- }
-}
-
-func pragdataflag() {
- for getnsc() != '\n' {
- }
-}
-
-func pragprofile() {
- for getnsc() != '\n' {
- }
-}
-
-func pragincomplete() {
- for getnsc() != '\n' {
- }
-}
-
-func setinclude(p string) {
- if p == "" {
- return
- }
- for i := 1; i < len(include); i++ {
- if p == include[i] {
- return
- }
- }
-
- include = append(include, p)
-}
-
-func errorexit() {
- bstdout.Flush()
- if outfile != "" {
- os.Remove(outfile)
- }
- os.Exit(2)
-}
-
-func pushio() {
- i := iostack
- if i == nil {
- Yyerror("botch in pushio")
- errorexit()
- }
-
- i.P = fi.P
-}
-
-func newio() {
- var pushdepth int = 0
-
- i := iofree
- if i == nil {
- pushdepth++
- if pushdepth > 1000 {
- Yyerror("macro/io expansion too deep")
- errorexit()
- }
- i = new(Io)
- } else {
- iofree = i.Link
- }
- i.F = nil
- i.P = nil
- ionext = i
-}
-
-func newfile(s string, f *os.File) {
- i := ionext
- i.Link = iostack
- iostack = i
- i.F = f
- if f == nil {
- var err error
- i.F, err = os.Open(s)
- if err != nil {
- Yyerror("%ca: %v", Thechar, err)
- errorexit()
- }
- }
-
- fi.P = nil
- Ctxt.LineHist.Push(int(Lineno), s)
-}
-
-var thetext *obj.LSym
-
-func Settext(s *obj.LSym) {
- thetext = s
-}
-
-func LabelLookup(s *Sym) *Sym {
- if thetext == nil {
- s.Labelname = s.Name
- return s
- }
-
- p := string(fmt.Sprintf("%s.%s", thetext.Name, s.Name))
- lab := Lookup(p)
-
- lab.Labelname = s.Name
- return lab
-}
-
-func Lookup(symb string) *Sym {
- // turn leading · into ""·
- if strings.HasPrefix(symb, "·") {
- symb = `""` + symb
- }
-
- // turn · (U+00B7) into .
- // turn ∕ (U+2215) into /
- symb = strings.Replace(symb, "·", ".", -1)
- symb = strings.Replace(symb, "∕", "/", -1)
-
- s := hash[symb]
- if s != nil {
- return s
- }
-
- s = new(Sym)
- s.Name = symb
- syminit(s)
- hash[symb] = s
- return s
-}
-
-func isalnum(c int) bool {
- return isalpha(c) || isdigit(c)
-}
-
-func isalpha(c int) bool {
- return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z'
-}
-
-func isspace(c int) bool {
- return c == ' ' || c == '\t' || c == '\r' || c == '\n'
-}
-
-func ISALPHA(c int) bool {
- if isalpha(c) {
- return true
- }
- if c >= utf8.RuneSelf {
- return true
- }
- return false
-}
-
-var yybuf bytes.Buffer
-
-func (yyImpl) Error(s string) {
- Yyerror("%s", s)
-}
-
-type Yylval struct {
- Sym *Sym
- Lval int64
- Sval string
- Dval float64
-}
-
-func Yylex(yylval *Yylval) int {
- var c1 int
- var s *Sym
-
- c := peekc
- if c != IGN {
- peekc = IGN
- goto l1
- }
-
-l0:
- c = GETC()
-
-l1:
- if c == EOF {
- peekc = EOF
- return -1
- }
-
- if isspace(c) {
- if c == '\n' {
- Lineno++
- return ';'
- }
-
- goto l0
- }
-
- if ISALPHA(c) {
- yybuf.Reset()
- goto aloop
- }
- if isdigit(c) {
- yybuf.Reset()
- if c != '0' {
- goto dc
- }
- yybuf.WriteByte(byte(c))
- c = GETC()
- c1 = 3
- if c == 'x' || c == 'X' {
- c1 = 4
- c = GETC()
- } else if c < '0' || c > '7' {
- goto dc
- }
- yylval.Lval = 0
- for {
- if c >= '0' && c <= '9' {
- if c > '7' && c1 == 3 {
- break
- }
- yylval.Lval = int64(uint64(yylval.Lval) << uint(c1))
- yylval.Lval += int64(c) - '0'
- c = GETC()
- continue
- }
-
- if c1 == 3 {
- break
- }
- if c >= 'A' && c <= 'F' {
- c += 'a' - 'A'
- }
- if c >= 'a' && c <= 'f' {
- yylval.Lval = int64(uint64(yylval.Lval) << uint(c1))
- yylval.Lval += int64(c) - 'a' + 10
- c = GETC()
- continue
- }
-
- break
- }
-
- goto ncu
- }
- switch c {
- case '\n':
- Lineno++
- return ';'
-
- case '#':
- domacro()
- goto l0
-
- case '.':
- c = GETC()
- if ISALPHA(c) {
- yybuf.Reset()
- yybuf.WriteByte('.')
- goto aloop
- }
-
- if isdigit(c) {
- yybuf.Reset()
- yybuf.WriteByte('.')
- goto casedot
- }
-
- peekc = c
- return '.'
-
- case '_',
- '@':
- yybuf.Reset()
- goto aloop
-
- case '"':
- var buf bytes.Buffer
- c1 = 0
- for {
- c = escchar('"')
- if c == EOF {
- break
- }
- buf.WriteByte(byte(c))
- }
- yylval.Sval = buf.String()
- return LSCONST
-
- case '\'':
- c = escchar('\'')
- if c == EOF {
- c = '\''
- }
- if escchar('\'') != EOF {
- Yyerror("missing '")
- }
- yylval.Lval = int64(c)
- return LCONST
-
- case '/':
- c1 = GETC()
- if c1 == '/' {
- for {
- c = GETC()
- if c == '\n' {
- goto l1
- }
- if c == EOF {
- Yyerror("eof in comment")
- errorexit()
- }
- }
- }
-
- if c1 == '*' {
- for {
- c = GETC()
- for c == '*' {
- c = GETC()
- if c == '/' {
- goto l0
- }
- }
-
- if c == EOF {
- Yyerror("eof in comment")
- errorexit()
- }
-
- if c == '\n' {
- Lineno++
- }
- }
- }
-
- default:
- return int(c)
- }
-
- peekc = c1
- return int(c)
-
-casedot:
- for {
- yybuf.WriteByte(byte(c))
- c = GETC()
- if !(isdigit(c)) {
- break
- }
- }
-
- if c == 'e' || c == 'E' {
- goto casee
- }
- goto caseout
-
-casee:
- yybuf.WriteByte('e')
- c = GETC()
- if c == '+' || c == '-' {
- yybuf.WriteByte(byte(c))
- c = GETC()
- }
-
- for isdigit(c) {
- yybuf.WriteByte(byte(c))
- c = GETC()
- }
-
-caseout:
- peekc = c
- if FPCHIP != 0 /*TypeKind(100016)*/ {
- last = yybuf.String()
- yylval.Dval = atof(last)
- return LFCONST
- }
-
- Yyerror("assembler cannot interpret fp constants")
- yylval.Lval = 1
- return LCONST
-
-aloop:
- yybuf.WriteByte(byte(c))
- c = GETC()
- if ISALPHA(c) || isdigit(c) || c == '_' || c == '$' {
- goto aloop
- }
- peekc = c
- last = yybuf.String()
- s = Lookup(last)
- if s.Macro != nil {
- newio()
- ionext.P = macexpand(s)
- pushio()
- ionext.Link = iostack
- iostack = ionext
- fi.P = ionext.P
- if peekc != IGN {
- fi.P = append(fi.P, byte(peekc))
- peekc = IGN
- }
-
- goto l0
- }
-
- if s.Type == 0 {
- s.Type = LNAME
- }
- if s.Type == LNAME || s.Type == LVAR || s.Type == LLAB {
- yylval.Sym = s
- yylval.Sval = last
- return int(s.Type)
- }
-
- yylval.Lval = s.Value
- yylval.Sval = last
- return int(s.Type)
-
-dc:
- for {
- if !(isdigit(c)) {
- break
- }
- yybuf.WriteByte(byte(c))
- c = GETC()
- }
-
- if c == '.' {
- goto casedot
- }
- if c == 'e' || c == 'E' {
- goto casee
- }
- last = yybuf.String()
- yylval.Lval = strtoll(last, nil, 10)
-
-ncu:
- for c == 'U' || c == 'u' || c == 'l' || c == 'L' {
- c = GETC()
- }
- peekc = c
- return LCONST
-}
-
-func getc() int {
- c := peekc
- if c != IGN {
- peekc = IGN
- if c == '\n' {
- Lineno++
- }
- return c
- }
-
- c = GETC()
- if c == '\n' {
- Lineno++
- }
- if c == EOF {
- Yyerror("End of file")
- errorexit()
- }
-
- return c
-}
-
-func getnsc() int {
- var c int
-
- for {
- c = getc()
- if !isspace(c) || c == '\n' {
- return c
- }
- }
-}
-
-func unget(c int) {
- peekc = c
- if c == '\n' {
- Lineno--
- }
-}
-
-func escchar(e int) int {
- var l int
-
-loop:
- c := getc()
- if c == '\n' {
- Yyerror("newline in string")
- return EOF
- }
-
- if c != '\\' {
- if c == e {
- return EOF
- }
- return c
- }
-
- c = getc()
- if c >= '0' && c <= '7' {
- l = c - '0'
- c = getc()
- if c >= '0' && c <= '7' {
- l = l*8 + c - '0'
- c = getc()
- if c >= '0' && c <= '7' {
- l = l*8 + c - '0'
- return l
- }
- }
-
- peekc = c
- unget(c)
- return l
- }
-
- switch c {
- case '\n':
- goto loop
- case 'n':
- return '\n'
- case 't':
- return '\t'
- case 'b':
- return '\b'
- case 'r':
- return '\r'
- case 'f':
- return '\f'
- case 'a':
- return 0x07
- case 'v':
- return 0x0b
- case 'z':
- return 0x00
- }
-
- return c
-}
-
-func pinit(f string) {
- Lineno = 1
- newio()
- newfile(f, nil)
- PC = 0
- peekc = IGN
- sym = 1
- for _, s := range hash {
- s.Macro = nil
- }
-}
-
-func filbuf() int {
- var n int
-
-loop:
- i := iostack
- if i == nil {
- return EOF
- }
- if i.F == nil {
- goto pop
- }
- n, _ = i.F.Read(i.B[:])
- if n == 0 {
- i.F.Close()
- Ctxt.LineHist.Pop(int(Lineno))
- goto pop
- }
- fi.P = i.B[1:n]
- return int(i.B[0]) & 0xff
-
-pop:
- iostack = i.Link
- i.Link = iofree
- iofree = i
- i = iostack
- if i == nil {
- return EOF
- }
- fi.P = i.P
- if len(fi.P) == 0 {
- goto loop
- }
- tmp8 := fi.P
- fi.P = fi.P[1:]
- return int(tmp8[0]) & 0xff
-}
-
-var last string
-
-func Yyerror(a string, args ...interface{}) {
- /*
- * hack to intercept message from yaccpar
- */
- if a == "syntax error" || len(args) == 1 && a == "%s" && args[0] == "syntax error" {
- Yyerror("syntax error, last name: %s", last)
- return
- }
-
- prfile(Lineno)
- fmt.Printf("%s\n", fmt.Sprintf(a, args...))
- nerrors++
- if nerrors > 10 {
- fmt.Printf("too many errors\n")
- errorexit()
- }
-}
-
-func prfile(l int32) {
- obj.Linkprfile(Ctxt, int(l))
-}
-
-func GETC() int {
- if len(fi.P) == 0 {
- return filbuf()
- }
- c := int(fi.P[0])
- fi.P = fi.P[1:]
- return c
-}
-
-func isdigit(c int) bool {
- return '0' <= c && c <= '9'
-}
-
-func strtoll(s string, p *byte, base int) int64 {
- if p != nil {
- panic("strtoll")
- }
- n, err := strconv.ParseInt(s, base, 64)
- if err != nil {
- return 0
- }
- return n
-}
-
-func atof(s string) float64 {
- f, err := strconv.ParseFloat(s, 64)
- if err != nil {
- return 0
- }
- return f
-}
+++ /dev/null
-// Inferno utils/cc/macbody
-// http://code.Google.Com/p/inferno-os/source/browse/utils/cc/macbody
-//
-// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
-// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.Net)
-// Portions Copyright © 1997-1999 Vita Nuova Limited
-// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.Vitanuova.Com)
-// Portions Copyright © 2004,2006 Bruce Ellis
-// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.Net)
-// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
-// Portions Copyright © 2009 The Go Authors. All rights reserved.
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-package asm
-
-import (
- "bytes"
- "fmt"
- "os"
- "strings"
-)
-
-const (
- VARMAC = 0x80
-)
-
-func getnsn() int32 {
- c := getnsc()
- if c < '0' || c > '9' {
- return -1
- }
- n := int32(0)
- for c >= '0' && c <= '9' {
- n = n*10 + int32(c) - '0'
- c = getc()
- }
-
- unget(c)
- return n
-}
-
-func getsym() *Sym {
- c := getnsc()
- if !isalpha(c) && c != '_' && c < 0x80 {
- unget(c)
- return nil
- }
-
- var buf bytes.Buffer
- for {
- buf.WriteByte(byte(c))
- c = getc()
- if isalnum(c) || c == '_' || c >= 0x80 {
- continue
- }
- unget(c)
- break
- }
- last = buf.String()
- return Lookup(last)
-}
-
-func getsymdots(dots *int) *Sym {
- s := getsym()
- if s != nil {
- return s
- }
-
- c := getnsc()
- if c != '.' {
- unget(c)
- return nil
- }
-
- if getc() != '.' || getc() != '.' {
- Yyerror("bad dots in macro")
- }
- *dots = 1
- return Lookup("__VA_ARGS__")
-}
-
-func getcom() int {
- var c int
-
- for {
- c = getnsc()
- if c != '/' {
- break
- }
- c = getc()
- if c == '/' {
- for c != '\n' {
- c = getc()
- }
- break
- }
-
- if c != '*' {
- break
- }
- c = getc()
- for {
- if c == '*' {
- c = getc()
- if c != '/' {
- continue
- }
- c = getc()
- break
- }
-
- if c == '\n' {
- Yyerror("comment across newline")
- break
- }
-
- c = getc()
- }
-
- if c == '\n' {
- break
- }
- }
-
- return c
-}
-
-func dodefine(cp string) {
- var s *Sym
-
- if i := strings.Index(cp, "="); i >= 0 {
- p := cp[i+1:]
- cp = cp[:i]
- s = Lookup(cp)
- s.Macro = &Macro{Text: p}
- } else {
- s = Lookup(cp)
- s.Macro = &Macro{Text: "1"}
- }
-
- if debug['m'] != 0 {
- fmt.Printf("#define (-D) %s %s\n", s.Name, s.Macro.Text)
- }
-}
-
-var mactab = []struct {
- Macname string
- Macf func()
-}{
- {"ifdef", nil}, /* macif(0) */
- {"ifndef", nil}, /* macif(1) */
- {"else", nil}, /* macif(2) */
- {"line", maclin},
- {"define", macdef},
- {"include", macinc},
- {"undef", macund},
- {"pragma", macprag},
- {"endif", macend},
-}
-
-func domacro() {
- s := getsym()
- if s == nil {
- s = Lookup("endif")
- }
- for i := 0; i < len(mactab); i++ {
- if s.Name == mactab[i].Macname {
- if mactab[i].Macf != nil {
- mactab[i].Macf()
- } else {
- macif(i)
- }
- return
- }
- }
-
- Yyerror("unknown #: %s", s.Name)
- macend()
-}
-
-func macund() {
- s := getsym()
- macend()
- if s == nil {
- Yyerror("syntax in #undef")
- return
- }
-
- s.Macro = nil
-}
-
-const (
- NARG = 25
-)
-
-func macdef() {
- var args [NARG]string
- var n int
- var i int
- var c int
- var dots int
- var ischr int
- var base bytes.Buffer
-
- s := getsym()
- if s == nil {
- goto bad
- }
- if s.Macro != nil {
- Yyerror("macro redefined: %s", s.Name)
- }
- c = getc()
- n = -1
- dots = 0
- if c == '(' {
- n++
- c = getnsc()
- if c != ')' {
- unget(c)
- var a *Sym
- var c int
- for {
- a = getsymdots(&dots)
- if a == nil {
- goto bad
- }
- if n >= NARG {
- Yyerror("too many arguments in #define: %s", s.Name)
- goto bad
- }
-
- args[n] = a.Name
- n++
- c = getnsc()
- if c == ')' {
- break
- }
- if c != ',' || dots != 0 {
- goto bad
- }
- }
- }
-
- c = getc()
- }
-
- if isspace(c) {
- if c != '\n' {
- c = getnsc()
- }
- }
- ischr = 0
- for {
- if isalpha(c) || c == '_' {
- var buf bytes.Buffer
- buf.WriteByte(byte(c))
- c = getc()
- for isalnum(c) || c == '_' {
- buf.WriteByte(byte(c))
- c = getc()
- }
-
- symb := buf.String()
- for i = 0; i < n; i++ {
- if symb == args[i] {
- break
- }
- }
- if i >= n {
- base.WriteString(symb)
- continue
- }
-
- base.WriteByte('#')
- base.WriteByte(byte('a' + i))
- continue
- }
-
- if ischr != 0 {
- if c == '\\' {
- base.WriteByte(byte(c))
- c = getc()
- } else if c == ischr {
- ischr = 0
- }
- } else {
- if c == '"' || c == '\'' {
- base.WriteByte(byte(c))
- ischr = c
- c = getc()
- continue
- }
-
- if c == '/' {
- c = getc()
- if c == '/' {
- c = getc()
- for {
- if c == '\n' {
- break
- }
- c = getc()
- }
-
- continue
- }
-
- if c == '*' {
- c = getc()
- for {
- if c == '*' {
- c = getc()
- if c != '/' {
- continue
- }
- c = getc()
- break
- }
-
- if c == '\n' {
- Yyerror("comment and newline in define: %s", s.Name)
- break
- }
-
- c = getc()
- }
-
- continue
- }
-
- base.WriteByte('/')
- continue
- }
- }
-
- if c == '\\' {
- c = getc()
- if c == '\n' {
- c = getc()
- continue
- } else if c == '\r' {
- c = getc()
- if c == '\n' {
- c = getc()
- continue
- }
- }
-
- base.WriteByte('\\')
- continue
- }
-
- if c == '\n' {
- break
- }
- if c == '#' {
- if n > 0 {
- base.WriteByte(byte(c))
- }
- }
-
- base.WriteByte(byte(c))
- c = GETC()
- if c == '\n' {
- Lineno++
- }
- if c == -1 {
- Yyerror("eof in a macro: %s", s.Name)
- break
- }
- }
-
- s.Macro = &Macro{
- Text: base.String(),
- Narg: n + 1,
- Dots: dots != 0,
- }
- if debug['m'] != 0 {
- fmt.Printf("#define %s %s\n", s.Name, s.Macro.Text)
- }
- return
-
-bad:
- if s == nil {
- Yyerror("syntax in #define")
- } else {
- Yyerror("syntax in #define: %s", s.Name)
- }
- macend()
-}
-
-func macexpand(s *Sym) []byte {
- if s.Macro.Narg == 0 {
- if debug['m'] != 0 {
- fmt.Printf("#expand %s %s\n", s.Name, s.Macro.Text)
- }
- return []byte(s.Macro.Text)
- }
-
- nargs := s.Macro.Narg - 1
- dots := s.Macro.Dots
-
- c := getnsc()
- var arg []string
- var cp string
- var out bytes.Buffer
- if c != '(' {
- goto bad
- }
- c = getc()
- if c != ')' {
- unget(c)
- l := 0
- var buf bytes.Buffer
- var c int
- for {
- c = getc()
- if c == '"' {
- for {
- buf.WriteByte(byte(c))
- c = getc()
- if c == '\\' {
- buf.WriteByte(byte(c))
- c = getc()
- continue
- }
-
- if c == '\n' {
- goto bad
- }
- if c == '"' {
- break
- }
- }
- }
-
- if c == '\'' {
- for {
- buf.WriteByte(byte(c))
- c = getc()
- if c == '\\' {
- buf.WriteByte(byte(c))
- c = getc()
- continue
- }
-
- if c == '\n' {
- goto bad
- }
- if c == '\'' {
- break
- }
- }
- }
-
- if c == '/' {
- c = getc()
- switch c {
- case '*':
- for {
- c = getc()
- if c == '*' {
- c = getc()
- if c == '/' {
- break
- }
- }
- }
-
- buf.WriteByte(' ')
- continue
-
- case '/':
- for {
- c = getc()
- if !(c != '\n') {
- break
- }
- }
-
- default:
- unget(c)
- c = '/'
- }
- }
-
- if l == 0 {
- if c == ',' {
- if len(arg) == nargs-1 && dots {
- buf.WriteByte(',')
- continue
- }
-
- arg = append(arg, buf.String())
- buf.Reset()
- continue
- }
-
- if c == ')' {
- arg = append(arg, buf.String())
- break
- }
- }
-
- if c == '\n' {
- c = ' '
- }
- buf.WriteByte(byte(c))
- if c == '(' {
- l++
- }
- if c == ')' {
- l--
- }
- }
- }
-
- if len(arg) != nargs {
- Yyerror("argument mismatch expanding: %s", s.Name)
- return nil
- }
-
- cp = s.Macro.Text
- for i := 0; i < len(cp); i++ {
- c = int(cp[i])
- if c == '\n' {
- c = ' '
- }
- if c != '#' {
- out.WriteByte(byte(c))
- continue
- }
-
- i++
- if i >= len(cp) {
- goto bad
- }
- c = int(cp[i])
- if c == '#' {
- out.WriteByte(byte(c))
- continue
- }
-
- c -= 'a'
- if c < 0 || c >= len(arg) {
- continue
- }
- out.WriteString(arg[c])
- }
-
- if debug['m'] != 0 {
- fmt.Printf("#expand %s %s\n", s.Name, out.String())
- }
- return out.Bytes()
-
-bad:
- Yyerror("syntax in macro expansion: %s", s.Name)
- return nil
-}
-
-func macinc() {
- var c int
- var buf bytes.Buffer
- var f *os.File
- var hp string
- var str string
- var symb string
-
- c0 := getnsc()
- if c0 != '"' {
- c = c0
- if c0 != '<' {
- goto bad
- }
- c0 = '>'
- }
-
- for {
- c = getc()
- if c == c0 {
- break
- }
- if c == '\n' {
- goto bad
- }
- buf.WriteByte(byte(c))
- }
- str = buf.String()
-
- c = getcom()
- if c != '\n' {
- goto bad
- }
-
- for i := 0; i < len(include); i++ {
- if i == 0 && c0 == '>' {
- continue
- }
- symb = include[i]
- symb += "/"
- if symb == "./" {
- symb = ""
- }
- symb += str
- var err error
- f, err = os.Open(symb)
- if err == nil {
- break
- }
- }
-
- if f == nil {
- symb = str
- }
- hp = symb
- newio()
- pushio()
- newfile(hp, f)
- return
-
-bad:
- unget(c)
- Yyerror("syntax in #include")
- macend()
-}
-
-func maclin() {
- var buf bytes.Buffer
- var symb string
-
- n := getnsn()
- c := getc()
- if n < 0 {
- goto bad
- }
- for {
- if c == ' ' || c == '\t' {
- c = getc()
- continue
- }
-
- if c == '"' {
- break
- }
- if c == '\n' {
- symb = "<noname>"
- goto nn
- }
-
- goto bad
- }
-
- for {
- c = getc()
- if c == '"' {
- break
- }
- buf.WriteByte(byte(c))
- }
- symb = buf.String()
-
- c = getcom()
- if c != '\n' {
- goto bad
- }
-
-nn:
- Ctxt.LineHist.Update(int(Lineno), symb, int(n))
- return
-
-bad:
- unget(c)
- Yyerror("syntax in #line")
- macend()
-}
-
-func macif(f int) {
- var c int
- var l int
- var bol int
- var s *Sym
-
- if f == 2 {
- goto skip
- }
- s = getsym()
- if s == nil {
- goto bad
- }
- if getcom() != '\n' {
- goto bad
- }
- if (s.Macro != nil) != (f != 0) {
- return
- }
-
-skip:
- bol = 1
- l = 0
- for {
- c = getc()
- if c != '#' {
- if !isspace(c) {
- bol = 0
- }
- if c == '\n' {
- bol = 1
- }
- continue
- }
-
- if !(bol != 0) {
- continue
- }
- s = getsym()
- if s == nil {
- continue
- }
- if s.Name == "endif" {
- if l != 0 {
- l--
- continue
- }
-
- macend()
- return
- }
-
- if s.Name == "ifdef" || s.Name == "ifndef" {
- l++
- continue
- }
-
- if l == 0 && f != 2 && s.Name == "else" {
- macend()
- return
- }
- }
-
-bad:
- Yyerror("syntax in #if(n)def")
- macend()
-}
-
-func macprag() {
- var c int
-
- s := getsym()
-
- if s != nil && s.Name == "lib" {
- c0 := getnsc()
- if c0 != '"' {
- c = c0
- if c0 != '<' {
- goto bad
- }
- c0 = '>'
- }
-
- var buf bytes.Buffer
- for {
- c = getc()
- if c == c0 {
- break
- }
- if c == '\n' {
- goto bad
- }
- buf.WriteByte(byte(c))
- }
- symb := buf.String()
-
- c = getcom()
- if c != '\n' {
- goto bad
- }
-
- /*
- * put pragma-line in as a funny history
- */
- Ctxt.AddImport(symb)
- return
- }
- if s != nil && s.Name == "pack" {
- pragpack()
- return
- }
-
- if s != nil && s.Name == "fpround" {
- pragfpround()
- return
- }
-
- if s != nil && s.Name == "textflag" {
- pragtextflag()
- return
- }
-
- if s != nil && s.Name == "dataflag" {
- pragdataflag()
- return
- }
-
- if s != nil && s.Name == "varargck" {
- pragvararg()
- return
- }
-
- if s != nil && s.Name == "incomplete" {
- pragincomplete()
- return
- }
-
- if s != nil && (strings.HasPrefix(s.Name, "cgo_") || strings.HasPrefix(s.Name, "dyn")) {
- pragcgo(s.Name)
- return
- }
-
- for getnsc() != '\n' {
- }
- return
-
-bad:
- unget(c)
- Yyerror("syntax in #pragma lib")
- macend()
-}
-
-func macend() {
- var c int
-
- for {
- c = getnsc()
- if c < 0 || c == '\n' {
- return
- }
- }
-}