aboutsummaryrefslogtreecommitdiffstats
path: root/prog/encoding.go
diff options
context:
space:
mode:
Diffstat (limited to 'prog/encoding.go')
-rw-r--r--prog/encoding.go99
1 files changed, 53 insertions, 46 deletions
diff --git a/prog/encoding.go b/prog/encoding.go
index 4478bc834..6e3203984 100644
--- a/prog/encoding.go
+++ b/prog/encoding.go
@@ -183,8 +183,7 @@ func (target *Target) Deserialize(data []byte) (prog *Prog, err error) {
prog = &Prog{
Target: target,
}
- p := newParser(data)
- vars := make(map[string]*ResultArg)
+ p := newParser(target, data)
comment := ""
for p.Scan() {
if p.EOF() {
@@ -222,14 +221,14 @@ func (target *Target) Deserialize(data []byte) (prog *Prog, err error) {
p.Parse('(')
for i := 0; p.Char() != ')'; i++ {
if i >= len(meta.Args) {
- eatExcessive(p, false)
+ p.eatExcessive(false)
break
}
typ := meta.Args[i]
if IsPad(typ) {
return nil, fmt.Errorf("padding in syscall %v arguments", name)
}
- arg, err := target.parseArg(typ, p, vars)
+ arg, err := p.parseArg(typ)
if err != nil {
return nil, err
}
@@ -256,7 +255,7 @@ func (target *Target) Deserialize(data []byte) (prog *Prog, err error) {
return nil, fmt.Errorf("wrong call arg count: %v, want %v", len(c.Args), len(meta.Args))
}
if r != "" && c.Ret != nil {
- vars[r] = c.Ret
+ p.vars[r] = c.Ret
}
comment = ""
}
@@ -278,7 +277,7 @@ func (target *Target) Deserialize(data []byte) (prog *Prog, err error) {
return
}
-func (target *Target) parseArg(typ Type, p *parser, vars map[string]*ResultArg) (Arg, error) {
+func (p *parser) parseArg(typ Type) (Arg, error) {
r := ""
if p.Char() == '<' {
p.Parse('<')
@@ -286,7 +285,7 @@ func (target *Target) parseArg(typ Type, p *parser, vars map[string]*ResultArg)
p.Parse('=')
p.Parse('>')
}
- arg, err := target.parseArgImpl(typ, p, vars)
+ arg, err := p.parseArgImpl(typ)
if err != nil {
return nil, err
}
@@ -299,28 +298,28 @@ func (target *Target) parseArg(typ Type, p *parser, vars map[string]*ResultArg)
}
if r != "" {
if res, ok := arg.(*ResultArg); ok {
- vars[r] = res
+ p.vars[r] = res
}
}
return arg, nil
}
-func (target *Target) parseArgImpl(typ Type, p *parser, vars map[string]*ResultArg) (Arg, error) {
+func (p *parser) parseArgImpl(typ Type) (Arg, error) {
switch p.Char() {
case '0':
- return target.parseArgInt(typ, p)
+ return p.parseArgInt(typ)
case 'r':
- return target.parseArgRes(typ, p, vars)
+ return p.parseArgRes(typ)
case '&':
- return target.parseArgAddr(typ, p, vars)
+ return p.parseArgAddr(typ)
case '"', '\'':
- return target.parseArgString(typ, p)
+ return p.parseArgString(typ)
case '{':
- return target.parseArgStruct(typ, p, vars)
+ return p.parseArgStruct(typ)
case '[':
- return target.parseArgArray(typ, p, vars)
+ return p.parseArgArray(typ)
case '@':
- return target.parseArgUnion(typ, p, vars)
+ return p.parseArgUnion(typ)
case 'n':
p.Parse('n')
p.Parse('i')
@@ -333,7 +332,7 @@ func (target *Target) parseArgImpl(typ Type, p *parser, vars map[string]*ResultA
}
}
-func (target *Target) parseArgInt(typ Type, p *parser) (Arg, error) {
+func (p *parser) parseArgInt(typ Type) (Arg, error) {
val := p.Ident()
v, err := strconv.ParseUint(val, 0, 64)
if err != nil {
@@ -345,15 +344,15 @@ func (target *Target) parseArgInt(typ Type, p *parser) (Arg, error) {
case *ResourceType:
return MakeResultArg(typ, nil, v), nil
case *PtrType, *VmaType:
- index := -v % uint64(len(target.SpecialPointers))
+ index := -v % uint64(len(p.target.SpecialPointers))
return MakeSpecialPointerArg(typ, index), nil
default:
- eatExcessive(p, true)
+ p.eatExcessive(true)
return typ.DefaultArg(), nil
}
}
-func (target *Target) parseArgRes(typ Type, p *parser, vars map[string]*ResultArg) (Arg, error) {
+func (p *parser) parseArgRes(typ Type) (Arg, error) {
id := p.Ident()
var div, add uint64
if p.Char() == '/' {
@@ -374,7 +373,7 @@ func (target *Target) parseArgRes(typ Type, p *parser, vars map[string]*ResultAr
}
add = v
}
- v := vars[id]
+ v := p.vars[id]
if v == nil {
return typ.DefaultArg(), nil
}
@@ -384,18 +383,18 @@ func (target *Target) parseArgRes(typ Type, p *parser, vars map[string]*ResultAr
return arg, nil
}
-func (target *Target) parseArgAddr(typ Type, p *parser, vars map[string]*ResultArg) (Arg, error) {
+func (p *parser) parseArgAddr(typ Type) (Arg, error) {
var typ1 Type
switch t1 := typ.(type) {
case *PtrType:
typ1 = t1.Type
case *VmaType:
default:
- eatExcessive(p, true)
+ p.eatExcessive(true)
return typ.DefaultArg(), nil
}
p.Parse('&')
- addr, vmaSize, err := target.parseAddr(p)
+ addr, vmaSize, err := p.parseAddr()
if err != nil {
return nil, err
}
@@ -407,10 +406,10 @@ func (target *Target) parseArgAddr(typ Type, p *parser, vars map[string]*ResultA
p.Parse('N')
p.Parse('Y')
p.Parse('=')
- typ = target.makeAnyPtrType(typ.Size(), typ.FieldName())
- typ1 = target.any.array
+ typ = p.target.makeAnyPtrType(typ.Size(), typ.FieldName())
+ typ1 = p.target.any.array
}
- inner, err = target.parseArg(typ1, p, vars)
+ inner, err = p.parseArg(typ1)
if err != nil {
return nil, err
}
@@ -424,12 +423,12 @@ func (target *Target) parseArgAddr(typ Type, p *parser, vars map[string]*ResultA
return MakePointerArg(typ, addr, inner), nil
}
-func (target *Target) parseArgString(typ Type, p *parser) (Arg, error) {
+func (p *parser) parseArgString(typ Type) (Arg, error) {
if _, ok := typ.(*BufferType); !ok {
- eatExcessive(p, true)
+ p.eatExcessive(true)
return typ.DefaultArg(), nil
}
- data, err := deserializeData(p)
+ data, err := p.deserializeData()
if err != nil {
return nil, err
}
@@ -457,25 +456,25 @@ func (target *Target) parseArgString(typ Type, p *parser) (Arg, error) {
return MakeDataArg(typ, data), nil
}
-func (target *Target) parseArgStruct(typ Type, p *parser, vars map[string]*ResultArg) (Arg, error) {
+func (p *parser) parseArgStruct(typ Type) (Arg, error) {
p.Parse('{')
t1, ok := typ.(*StructType)
if !ok {
- eatExcessive(p, false)
+ p.eatExcessive(false)
p.Parse('}')
return typ.DefaultArg(), nil
}
var inner []Arg
for i := 0; p.Char() != '}'; i++ {
if i >= len(t1.Fields) {
- eatExcessive(p, false)
+ p.eatExcessive(false)
break
}
fld := t1.Fields[i]
if IsPad(fld) {
inner = append(inner, MakeConstArg(fld, 0))
} else {
- arg, err := target.parseArg(fld, p, vars)
+ arg, err := p.parseArg(fld)
if err != nil {
return nil, err
}
@@ -492,17 +491,17 @@ func (target *Target) parseArgStruct(typ Type, p *parser, vars map[string]*Resul
return MakeGroupArg(typ, inner), nil
}
-func (target *Target) parseArgArray(typ Type, p *parser, vars map[string]*ResultArg) (Arg, error) {
+func (p *parser) parseArgArray(typ Type) (Arg, error) {
p.Parse('[')
t1, ok := typ.(*ArrayType)
if !ok {
- eatExcessive(p, false)
+ p.eatExcessive(false)
p.Parse(']')
return typ.DefaultArg(), nil
}
var inner []Arg
for i := 0; p.Char() != ']'; i++ {
- arg, err := target.parseArg(t1.Type, p, vars)
+ arg, err := p.parseArg(t1.Type)
if err != nil {
return nil, err
}
@@ -521,10 +520,10 @@ func (target *Target) parseArgArray(typ Type, p *parser, vars map[string]*Result
return MakeGroupArg(typ, inner), nil
}
-func (target *Target) parseArgUnion(typ Type, p *parser, vars map[string]*ResultArg) (Arg, error) {
+func (p *parser) parseArgUnion(typ Type) (Arg, error) {
t1, ok := typ.(*UnionType)
if !ok {
- eatExcessive(p, true)
+ p.eatExcessive(true)
return typ.DefaultArg(), nil
}
p.Parse('@')
@@ -537,14 +536,14 @@ func (target *Target) parseArgUnion(typ Type, p *parser, vars map[string]*Result
}
}
if optType == nil {
- eatExcessive(p, true)
+ p.eatExcessive(true)
return typ.DefaultArg(), nil
}
var opt Arg
if p.Char() == '=' {
p.Parse('=')
var err error
- opt, err = target.parseArg(optType, p, vars)
+ opt, err = p.parseArg(optType)
if err != nil {
return nil, err
}
@@ -555,7 +554,7 @@ func (target *Target) parseArgUnion(typ Type, p *parser, vars map[string]*Result
}
// Eats excessive call arguments and struct fields to recover after description changes.
-func eatExcessive(p *parser, stopAtComma bool) {
+func (p *parser) eatExcessive(stopAtComma bool) {
paren, brack, brace := 0, 0, 0
for !p.EOF() && p.e == nil {
ch := p.Char()
@@ -611,7 +610,7 @@ func (target *Target) serializeAddr(arg *PointerArg) string {
return fmt.Sprintf("(0x%x%v)", encodingAddrBase+arg.Address, ssize)
}
-func (target *Target) parseAddr(p *parser) (uint64, uint64, error) {
+func (p *parser) parseAddr() (uint64, uint64, error) {
p.Parse('(')
pstr := p.Ident()
addr, err := strconv.ParseUint(pstr, 0, 64)
@@ -641,6 +640,7 @@ func (target *Target) parseAddr(p *parser) (uint64, uint64, error) {
}
addr += off
}
+ target := p.target
maxMem := target.NumPages * target.PageSize
var vmaSize uint64
if p.Char() == '/' {
@@ -713,7 +713,7 @@ func serializeData(buf *bytes.Buffer, data []byte) {
buf.WriteByte('\'')
}
-func deserializeData(p *parser) ([]byte, error) {
+func (p *parser) deserializeData() ([]byte, error) {
var data []byte
if p.Char() == '"' {
p.Parse('"')
@@ -775,6 +775,9 @@ func deserializeData(p *parser) ([]byte, error) {
}
type parser struct {
+ target *Target
+ vars map[string]*ResultArg
+
r *bufio.Scanner
s string
i int
@@ -782,8 +785,12 @@ type parser struct {
e error
}
-func newParser(data []byte) *parser {
- p := &parser{r: bufio.NewScanner(bytes.NewReader(data))}
+func newParser(target *Target, data []byte) *parser {
+ p := &parser{
+ target: target,
+ vars: make(map[string]*ResultArg),
+ r: bufio.NewScanner(bytes.NewReader(data)),
+ }
p.r.Buffer(nil, maxLineLen)
return p
}