From 5cdae5950c357564300c0ee3fb4dc9e7bbf4946b Mon Sep 17 00:00:00 2001 From: "Andrew Gallant (Ocelot)" Date: Thu, 3 May 2012 01:00:01 -0400 Subject: holy toldeo... things might actually be working --- nexgb/xgbgen/context.go | 21 ++++++ nexgb/xgbgen/expression.go | 73 +++++++++++--------- nexgb/xgbgen/field.go | 75 ++++++++++++++++++--- nexgb/xgbgen/go.go | 53 ++++++++++----- nexgb/xgbgen/go_error.go | 88 +++++++++++++++++++++--- nexgb/xgbgen/go_event.go | 15 +++-- nexgb/xgbgen/go_list.go | 97 ++++++++++++++++++--------- nexgb/xgbgen/go_reply.go | 19 ------ nexgb/xgbgen/go_request_reply.go | 140 +++++++++++++++++++++++++++++++++++++++ nexgb/xgbgen/go_single_field.go | 62 ++++++++--------- nexgb/xgbgen/go_struct.go | 19 ++++-- nexgb/xgbgen/go_union.go | 17 ++--- nexgb/xgbgen/representation.go | 19 +++++- nexgb/xgbgen/translation.go | 17 ++--- nexgb/xgbgen/type.go | 12 ++++ 15 files changed, 545 insertions(+), 182 deletions(-) delete mode 100644 nexgb/xgbgen/go_reply.go create mode 100644 nexgb/xgbgen/go_request_reply.go (limited to 'nexgb/xgbgen') diff --git a/nexgb/xgbgen/context.go b/nexgb/xgbgen/context.go index 33641b3..3e484f3 100644 --- a/nexgb/xgbgen/context.go +++ b/nexgb/xgbgen/context.go @@ -5,6 +5,7 @@ import ( "encoding/xml" "fmt" "log" + "time" ) type Context struct { @@ -47,6 +48,26 @@ func (c *Context) Morph(xmlBytes []byte) { // Translate XML types to nice types c.protocol = parsedXml.Translate() + // Start with Go header. + c.Putln("package xgb") + c.Putln("") + c.Putln("/*") + c.Putln("\tThis file was generated by %s.xml on %s.", + c.protocol.Name, time.Now().Format("Jan 2 2006 3:04:05pm MST")) + c.Putln("\tThis file is automatically generated. Edit at your peril!") + c.Putln("*/") + c.Putln("") + + // Write imports in comments + if len(c.protocol.Imports) > 0 { + c.Putln("// Imports are not necessary for XGB because everything is ") + c.Putln("// in one package. They are still listed here for reference.") + for _, imp := range c.protocol.Imports { + c.Putln("// import \"%s\"", imp.Name) + } + c.Putln("") + } + // Now write Go source code for _, typ := range c.protocol.Types { typ.Define(c) diff --git a/nexgb/xgbgen/expression.go b/nexgb/xgbgen/expression.go index a975320..12bcb19 100644 --- a/nexgb/xgbgen/expression.go +++ b/nexgb/xgbgen/expression.go @@ -8,7 +8,7 @@ import ( type Expression interface { Concrete() bool Eval() uint - Reduce(prefix, fun string) string + Reduce(prefix string) string String() string Initialize(p *Protocol) } @@ -29,12 +29,12 @@ func (e *Function) Eval() uint { panic("unreachable") } -func (e *Function) Reduce(prefix, fun string) string { - return fmt.Sprintf("%s(%s)", e.Name, e.Expr.Reduce(prefix, fun)) +func (e *Function) Reduce(prefix string) string { + return fmt.Sprintf("%s(%s)", e.Name, e.Expr.Reduce(prefix)) } func (e *Function) String() string { - return e.Reduce("", "") + return e.Reduce("") } func (e *Function) Initialize(p *Protocol) { @@ -89,16 +89,34 @@ func (e *BinaryOp) Eval() uint { panic("unreachable") } -func (e *BinaryOp) Reduce(prefix, fun string) string { +func (e *BinaryOp) Reduce(prefix string) string { if e.Concrete() { return fmt.Sprintf("%d", e.Eval()) } + + // An incredibly dirty hack to make sure any time we perform an operation + // on a field, we're dealing with ints... + expr1, expr2 := e.Expr1, e.Expr2 + switch expr1.(type) { + case *FieldRef: + expr1 = &Function{ + Name: "int", + Expr: expr1, + } + } + switch expr2.(type) { + case *FieldRef: + expr2 = &Function{ + Name: "int", + Expr: expr2, + } + } return fmt.Sprintf("(%s %s %s)", - e.Expr1.Reduce(prefix, fun), e.Op, e.Expr2.Reduce(prefix, fun)) + expr1.Reduce(prefix), e.Op, expr2.Reduce(prefix)) } func (e *BinaryOp) String() string { - return e.Reduce("", "") + return e.Reduce("") } func (e *BinaryOp) Initialize(p *Protocol) { @@ -125,15 +143,15 @@ func (e *UnaryOp) Eval() uint { panic("unreachable") } -func (e *UnaryOp) Reduce(prefix, fun string) string { +func (e *UnaryOp) Reduce(prefix string) string { if e.Concrete() { return fmt.Sprintf("%d", e.Eval()) } - return fmt.Sprintf("(%s (%s))", e.Op, e.Expr.Reduce(prefix, fun)) + return fmt.Sprintf("(%s (%s))", e.Op, e.Expr.Reduce(prefix)) } func (e *UnaryOp) String() string { - return e.Reduce("", "") + return e.Reduce("") } func (e *UnaryOp) Initialize(p *Protocol) { @@ -152,15 +170,15 @@ func (e *PopCount) Eval() uint { return popCount(e.Expr.Eval()) } -func (e *PopCount) Reduce(prefix, fun string) string { +func (e *PopCount) Reduce(prefix string) string { if e.Concrete() { return fmt.Sprintf("%d", e.Eval()) } - return fmt.Sprintf("popCount(%s)", e.Expr.Reduce(prefix, fun)) + return fmt.Sprintf("popCount(%s)", e.Expr.Reduce(prefix)) } func (e *PopCount) String() string { - return e.Reduce("", "") + return e.Reduce("") } func (e *PopCount) Initialize(p *Protocol) { @@ -179,12 +197,12 @@ func (e *Value) Eval() uint { return e.v } -func (e *Value) Reduce(prefix, fun string) string { +func (e *Value) Reduce(prefix string) string { return fmt.Sprintf("%d", e.v) } func (e *Value) String() string { - return e.Reduce("", "") + return e.Reduce("") } func (e *Value) Initialize(p *Protocol) {} @@ -201,12 +219,12 @@ func (e *Bit) Eval() uint { return 1 << e.b } -func (e *Bit) Reduce(prefix, fun string) string { +func (e *Bit) Reduce(prefix string) string { return fmt.Sprintf("%d", e.Eval()) } func (e *Bit) String() string { - return e.Reduce("", "") + return e.Reduce("") } func (e *Bit) Initialize(p *Protocol) {} @@ -224,19 +242,16 @@ func (e *FieldRef) Eval() uint { panic("unreachable") } -func (e *FieldRef) Reduce(prefix, fun string) string { +func (e *FieldRef) Reduce(prefix string) string { val := e.Name if len(prefix) > 0 { val = fmt.Sprintf("%s%s", prefix, val) } - if len(fun) > 0 { - val = fmt.Sprintf("%s(%s)", fun, val) - } return val } func (e *FieldRef) String() string { - return e.Reduce("", "") + return e.Reduce("") } func (e *FieldRef) Initialize(p *Protocol) { @@ -257,16 +272,12 @@ func (e *EnumRef) Eval() uint { panic("unreachable") } -func (e *EnumRef) Reduce(prefix, fun string) string { - val := fmt.Sprintf("%s%s", e.EnumKind, e.EnumItem) - if len(fun) > 0 { - val = fmt.Sprintf("%s(%s)", fun, val) - } - return val +func (e *EnumRef) Reduce(prefix string) string { + return fmt.Sprintf("%s%s", e.EnumKind, e.EnumItem) } func (e *EnumRef) String() string { - return e.Reduce("", "") + return e.Reduce("") } func (e *EnumRef) Initialize(p *Protocol) { @@ -287,7 +298,7 @@ func (e *SumOf) Eval() uint { panic("unreachable") } -func (e *SumOf) Reduce(prefix, fun string) string { +func (e *SumOf) Reduce(prefix string) string { if len(prefix) > 0 { return fmt.Sprintf("sum(%s%s)", prefix, e.Name) } @@ -295,7 +306,7 @@ func (e *SumOf) Reduce(prefix, fun string) string { } func (e *SumOf) String() string { - return e.Reduce("", "") + return e.Reduce("") } func (e *SumOf) Initialize(p *Protocol) { diff --git a/nexgb/xgbgen/field.go b/nexgb/xgbgen/field.go index 8d8412c..ddc2028 100644 --- a/nexgb/xgbgen/field.go +++ b/nexgb/xgbgen/field.go @@ -3,6 +3,7 @@ package main import ( "fmt" "log" + "strings" ) type Field interface { @@ -13,8 +14,8 @@ type Field interface { Size() Size Define(c *Context) - Read(c *Context) - Write(c *Context) + Read(c *Context, prefix string) + Write(c *Context, prefix string) } func (pad *PadField) Initialize(p *Protocol) {} @@ -32,7 +33,7 @@ func (p *PadField) XmlName() string { } func (f *PadField) SrcType() string { - panic("it is illegal to call SrcType on a SwitchField field") + panic("it is illegal to call SrcType on a PadField field") } func (p *PadField) Size() Size { @@ -82,22 +83,48 @@ func (f *ListField) XmlName() string { } func (f *ListField) SrcType() string { + if strings.ToLower(f.Type.XmlName()) == "char" { + return fmt.Sprintf("string") + } return fmt.Sprintf("[]%s", f.Type.SrcName()) } +func (f *ListField) Length() Size { + if f.LengthExpr == nil { + return newExpressionSize(&Function{ + Name: "len", + Expr: &FieldRef{ + Name: f.SrcName(), + }, + }) + } + return newExpressionSize(f.LengthExpr) +} + func (f *ListField) Size() Size { simpleLen := &Function{ Name: "pad", - Expr: newBinaryOp("*", f.LengthExpr, f.Type.Size().Expression), + Expr: newBinaryOp("*", f.Length().Expression, f.Type.Size().Expression), } - switch f.Type.(type) { + switch field := f.Type.(type) { case *Struct: - sizeFun := &Function{ - Name: fmt.Sprintf("%sListSize", f.Type.SrcName()), - Expr: &FieldRef{Name: f.SrcName()}, + if field.HasList() { + sizeFun := &Function{ + Name: fmt.Sprintf("%sListSize", f.Type.SrcName()), + Expr: &FieldRef{Name: f.SrcName()}, + } + return newExpressionSize(sizeFun) + } else { + return newExpressionSize(simpleLen) } - return newExpressionSize(sizeFun) + case *Union: + return newExpressionSize(simpleLen) + // sizeFun := &Function{ + // Name: fmt.Sprintf("%sListSize", f.Type.SrcName()), + // Expr: &FieldRef{Name: f.SrcName()}, + // } + // return newExpressionSize(sizeFun) case *Base: return newExpressionSize(simpleLen) case *Resource: @@ -152,6 +179,7 @@ func (f *ExprField) Initialize(p *Protocol) { } type ValueField struct { + Parent interface{} MaskType Type MaskName string ListName string @@ -170,7 +198,34 @@ func (f *ValueField) SrcType() string { } func (f *ValueField) Size() Size { - return f.MaskType.Size() + maskSize := f.MaskType.Size() + listSize := newExpressionSize(&Function{ + Name: "pad", + Expr: &BinaryOp{ + Op: "*", + Expr1: &Value{v: 4}, + Expr2: &PopCount{ + Expr: &Function{ + Name: "int", + Expr: &FieldRef{ + Name: f.MaskName, + }, + }, + }, + }, + }) + return maskSize.Add(listSize) +} + +func (f *ValueField) ListLength() Size { + return newExpressionSize(&PopCount{ + Expr: &Function{ + Name: "int", + Expr: &FieldRef{ + Name: f.MaskName, + }, + }, + }) } func (f *ValueField) Initialize(p *Protocol) { diff --git a/nexgb/xgbgen/go.go b/nexgb/xgbgen/go.go index b7b153e..771cfcf 100644 --- a/nexgb/xgbgen/go.go +++ b/nexgb/xgbgen/go.go @@ -1,5 +1,9 @@ package main +import ( + "fmt" +) + // xgbResourceIdName is the name of the type used for all resource identifiers. // As of right now, it needs to be declared somewhere manually. var xgbGenResourceIdName = "Id" @@ -94,26 +98,28 @@ func (f *PadField) Define(c *Context) { c.Putln("// padding: %d bytes", f.Bytes) } -func (f *PadField) Read(c *Context) { +func (f *PadField) Read(c *Context, prefix string) { c.Putln("b += %s // padding", f.Size()) } -func (f *PadField) Write(c *Context) { +func (f *PadField) Write(c *Context, prefix string) { c.Putln("b += %s // padding", f.Size()) } // Local fields func (f *LocalField) Define(c *Context) { c.Putln("// local field: %s %s", f.SrcName(), f.Type.SrcName()) + panic("unreachable") } -func (f *LocalField) Read(c *Context) { +func (f *LocalField) Read(c *Context, prefix string) { c.Putln("// reading local field: %s (%s) :: %s", f.SrcName(), f.Size(), f.Type.SrcName()) + panic("unreachable") } -func (f *LocalField) Write(c *Context) { - c.Putln("// writing local field: %s (%s) :: %s", +func (f *LocalField) Write(c *Context, prefix string) { + c.Putln("// skip writing local field: %s (%s) :: %s", f.SrcName(), f.Size(), f.Type.SrcName()) } @@ -121,32 +127,49 @@ func (f *LocalField) Write(c *Context) { func (f *ExprField) Define(c *Context) { c.Putln("// expression field: %s %s (%s)", f.SrcName(), f.Type.SrcName(), f.Expr) + panic("unreachable") } -func (f *ExprField) Read(c *Context) { +func (f *ExprField) Read(c *Context, prefix string) { c.Putln("// reading expression field: %s (%s) (%s) :: %s", f.SrcName(), f.Size(), f.Expr, f.Type.SrcName()) + panic("unreachable") } -func (f *ExprField) Write(c *Context) { - c.Putln("// writing expression field: %s (%s) (%s) :: %s", - f.SrcName(), f.Size(), f.Expr, f.Type.SrcName()) +func (f *ExprField) Write(c *Context, prefix string) { + // Special case for bools, grrr. + if f.Type.SrcName() == "bool" { + c.Putln("buf[b] = byte(%s)", f.Expr.Reduce(prefix)) + c.Putln("b += 1") + } else { + WriteSimpleSingleField(c, f.Expr.Reduce(prefix), f.Type) + } } // Value field func (f *ValueField) Define(c *Context) { c.Putln("// valueparam field: type: %s, mask name: %s, list name: %s", f.MaskType.SrcName(), f.MaskName, f.ListName) + panic("todo") } -func (f *ValueField) Read(c *Context) { +func (f *ValueField) Read(c *Context, prefix string) { c.Putln("// reading valueparam: type: %s, mask name: %s, list name: %s", f.MaskType.SrcName(), f.MaskName, f.ListName) + panic("todo") } -func (f *ValueField) Write(c *Context) { - c.Putln("// writing valueparam: type: %s, mask name: %s, list name: %s", - f.MaskType.SrcName(), f.MaskName, f.ListName) +func (f *ValueField) Write(c *Context, prefix string) { + // big time mofos + if rq, ok := f.Parent.(*Request); !ok || rq.SrcName() != "ConfigureWindow" { + WriteSimpleSingleField(c, + fmt.Sprintf("%s%s", prefix, f.MaskName), f.MaskType) + } + c.Putln("for i := 0; i < %s; i++ {", f.ListLength().Reduce(prefix)) + c.Putln("Put32(buf[b:], %s%s[i])", prefix, f.ListName) + c.Putln("b += 4") + c.Putln("}") + c.Putln("b = pad(b)") } // Switch field @@ -155,12 +178,12 @@ func (f *SwitchField) Define(c *Context) { panic("todo") } -func (f *SwitchField) Read(c *Context) { +func (f *SwitchField) Read(c *Context, prefix string) { c.Putln("// reading switch field: %s (%s)", f.Name, f.Expr) panic("todo") } -func (f *SwitchField) Write(c *Context) { +func (f *SwitchField) Write(c *Context, prefix string) { c.Putln("// writing switch field: %s (%s)", f.Name, f.Expr) panic("todo") } diff --git a/nexgb/xgbgen/go_error.go b/nexgb/xgbgen/go_error.go index 17c0db5..5a51064 100644 --- a/nexgb/xgbgen/go_error.go +++ b/nexgb/xgbgen/go_error.go @@ -1,5 +1,9 @@ package main +import ( + "fmt" +) + // Error types func (e *Error) Define(c *Context) { c.Putln("// Error definition %s (%d)", e.SrcName(), e.Number) @@ -20,9 +24,8 @@ func (e *Error) Define(c *Context) { // error struct. e.Read(c) - // Makes sure that this error type is an Error interface. - c.Putln("func (v %s) ImplementsError() { }", e.ErrType()) - c.Putln("") + // Makes sure this error type implements the xgb.Error interface. + e.ImplementsError(c) // Let's the XGB event loop read this error. c.Putln("func init() {") @@ -33,18 +36,18 @@ func (e *Error) Define(c *Context) { func (e *Error) Read(c *Context) { c.Putln("// Error read %s", e.SrcName()) - c.Putln("func New%s(buf []byte) %s {", e.ErrType(), e.ErrType()) + c.Putln("func New%s(buf []byte) Error {", e.ErrType()) c.Putln("v := %s{}", e.ErrType()) c.Putln("v.NiceName = \"%s\"", e.SrcName()) c.Putln("") c.Putln("b := 1 // skip error determinant") c.Putln("b += 1 // don't read error number") c.Putln("") - c.Putln("v.Sequence = get16(buf[b:])") + c.Putln("v.Sequence = Get16(buf[b:])") c.Putln("b += 2") c.Putln("") for _, field := range e.Fields { - field.Read(c) + field.Read(c, "v.") c.Putln("") } c.Putln("return v") @@ -52,6 +55,24 @@ func (e *Error) Read(c *Context) { c.Putln("") } +// ImplementsError writes functions to implement the XGB Error interface. +func (e *Error) ImplementsError(c *Context) { + c.Putln("func (err %s) ImplementsError() { }", e.ErrType()) + c.Putln("") + c.Putln("func (err %s) SequenceId() uint16 {", e.ErrType()) + c.Putln("return err.Sequence") + c.Putln("}") + c.Putln("") + c.Putln("func (err %s) BadId() Id {", e.ErrType()) + c.Putln("return Id(err.BadValue)") + c.Putln("}") + c.Putln("") + c.Putln("func (err %s) Error() string {", e.ErrType()) + FieldString(c, e.Fields, e.ErrConst()) + c.Putln("}") + c.Putln("") +} + // ErrorCopy types func (e *ErrorCopy) Define(c *Context) { c.Putln("// ErrorCopy definition %s (%d)", e.SrcName(), e.Number) @@ -65,9 +86,8 @@ func (e *ErrorCopy) Define(c *Context) { // error struct. e.Read(c) - // Makes sure that this error type is an Error interface. - c.Putln("func (err %s) ImplementsError() { }", e.ErrType()) - c.Putln("") + // Makes sure this error type implements the xgb.Error interface. + e.ImplementsError(c) // Let's the XGB know how to read this error. c.Putln("func init() {") @@ -77,8 +97,54 @@ func (e *ErrorCopy) Define(c *Context) { } func (e *ErrorCopy) Read(c *Context) { - c.Putln("func New%s(buf []byte) %s {", e.ErrType(), e.ErrType()) - c.Putln("return %s(New%s(buf))", e.ErrType(), e.Old.(*Error).ErrType()) + c.Putln("func New%s(buf []byte) Error {", e.ErrType()) + c.Putln("v := %s(New%s(buf).(%s))", + e.ErrType(), e.Old.(*Error).ErrType(), e.Old.(*Error).ErrType()) + c.Putln("v.NiceName = \"%s\"", e.SrcName()) + c.Putln("return v") + c.Putln("}") + c.Putln("") +} + +// ImplementsError writes functions to implement the XGB Error interface. +func (e *ErrorCopy) ImplementsError(c *Context) { + c.Putln("func (err %s) ImplementsError() { }", e.ErrType()) + c.Putln("") + c.Putln("func (err %s) SequenceId() uint16 {", e.ErrType()) + c.Putln("return err.Sequence") c.Putln("}") c.Putln("") + c.Putln("func (err %s) BadId() Id {", e.ErrType()) + c.Putln("return Id(err.BadValue)") + c.Putln("}") + c.Putln("") + c.Putln("func (err %s) Error() string {", e.ErrType()) + FieldString(c, e.Old.(*Error).Fields, e.ErrConst()) + c.Putln("}") + c.Putln("") +} + +// FieldString works for both Error and ErrorCopy. It assembles all of the +// fields in an error and formats them into a single string. +func FieldString(c *Context, fields []Field, errName string) { + c.Putln("fieldVals := make([]string, 0, %d)", len(fields)) + c.Putln("fieldVals = append(fieldVals, \"NiceName: \" + err.NiceName)") + c.Putln("fieldVals = append(fieldVals, " + + "sprintf(\"Sequence: %s\", err.Sequence))", "%d") + for _, field := range fields { + switch field.(type) { + case *PadField: + continue + default: + if field.SrcType() == "string" { + c.Putln("fieldVals = append(fieldVals, \"%s: \" + err.%s)", + field.SrcName(), field.SrcName()) + } else { + format := fmt.Sprintf("sprintf(\"%s: %s\", err.%s)", + field.SrcName(), "%d", field.SrcName()) + c.Putln("fieldVals = append(fieldVals, %s)", format) + } + } + } + c.Putln("return \"%s {\" + stringsJoin(fieldVals, \", \") + \"}\"", errName) } diff --git a/nexgb/xgbgen/go_event.go b/nexgb/xgbgen/go_event.go index fe2a77e..71252a7 100644 --- a/nexgb/xgbgen/go_event.go +++ b/nexgb/xgbgen/go_event.go @@ -38,17 +38,17 @@ func (e *Event) Define(c *Context) { func (e *Event) Read(c *Context) { c.Putln("// Event read %s", e.SrcName()) - c.Putln("func New%s(buf []byte) %s {", e.EvType(), e.EvType()) + c.Putln("func New%s(buf []byte) Event {", e.EvType()) c.Putln("v := %s{}", e.EvType()) c.Putln("b := 1 // don't read event number") c.Putln("") for i, field := range e.Fields { if i == 1 && !e.NoSequence { - c.Putln("v.Sequence = get16(buf[b:])") + c.Putln("v.Sequence = Get16(buf[b:])") c.Putln("b += 2") c.Putln("") } - field.Read(c) + field.Read(c, "v.") c.Putln("") } c.Putln("return v") @@ -71,7 +71,7 @@ func (e *Event) Write(c *Context) { c.Putln("b += 2 // skip sequence number") c.Putln("") } - field.Write(c) + field.Write(c, "v.") c.Putln("") } c.Putln("return buf") @@ -108,15 +108,16 @@ func (e *EventCopy) Define(c *Context) { } func (e *EventCopy) Read(c *Context) { - c.Putln("func New%s(buf []byte) %s {", e.EvType(), e.EvType()) - c.Putln("return %s(New%s(buf))", e.EvType(), e.Old.(*Event).EvType()) + c.Putln("func New%s(buf []byte) Event {", e.EvType()) + c.Putln("return %s(New%s(buf).(%s))", + e.EvType(), e.Old.(*Event).EvType(), e.Old.(*Event).EvType()) c.Putln("}") c.Putln("") } func (e *EventCopy) Write(c *Context) { c.Putln("func (v %s) Bytes() []byte {", e.EvType()) - c.Putln("return %s(ev).Bytes()", e.Old.(*Event).EvType()) + c.Putln("return %s(v).Bytes()", e.Old.(*Event).EvType()) c.Putln("}") c.Putln("") } diff --git a/nexgb/xgbgen/go_list.go b/nexgb/xgbgen/go_list.go index 67ecd34..41cfb76 100644 --- a/nexgb/xgbgen/go_list.go +++ b/nexgb/xgbgen/go_list.go @@ -3,74 +3,107 @@ package main import ( "fmt" "log" + "strings" ) // List fields func (f *ListField) Define(c *Context) { - c.Putln("%s []%s // size: %s", - f.SrcName(), f.Type.SrcName(), f.Size()) + c.Putln("%s %s // size: %s", + f.SrcName(), f.SrcType(), f.Size()) } -func (f *ListField) Read(c *Context) { +func (f *ListField) Read(c *Context, prefix string) { switch t := f.Type.(type) { case *Resource: - length := f.LengthExpr.Reduce("v.", "") - c.Putln("v.%s = make([]Id, %s)", f.SrcName(), length) - c.Putln("for i := 0; i < %s; i++ {", length) - ReadSimpleSingleField(c, fmt.Sprintf("v.%s[i]", f.SrcName()), t) + length := f.LengthExpr.Reduce(prefix) + c.Putln("%s%s = make([]Id, %s)", prefix, f.SrcName(), length) + c.Putln("for i := 0; i < int(%s); i++ {", length) + ReadSimpleSingleField(c, fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) c.Putln("}") c.Putln("b = pad(b)") case *Base: - length := f.LengthExpr.Reduce("v.", "") - c.Putln("v.%s = make([]%s, %s)", f.SrcName(), t.SrcName(), length) - if t.SrcName() == "byte" { - c.Putln("copy(v.%s[:%s], buf[b:])", f.SrcName(), length) - c.Putln("b += pad(%s)", length) + length := f.LengthExpr.Reduce(prefix) + if strings.ToLower(t.XmlName()) == "char" { + c.Putln("{") + c.Putln("byteString := make([]%s, %s)", t.SrcName(), length) + c.Putln("copy(byteString[:%s], buf[b:])", length) + c.Putln("%s%s = string(byteString)", prefix, f.SrcName()) + c.Putln("b += pad(int(%s))", length) + c.Putln("}") + } else if t.SrcName() == "byte" { + c.Putln("%s%s = make([]%s, %s)", + prefix, f.SrcName(), t.SrcName(), length) + c.Putln("copy(%s%s[:%s], buf[b:])", prefix, f.SrcName(), length) + c.Putln("b += pad(int(%s))", length) } else { - c.Putln("for i := 0; i < %s; i++ {", length) - ReadSimpleSingleField(c, fmt.Sprintf("v.%s[i]", f.SrcName()), t) + c.Putln("%s%s = make([]%s, %s)", + prefix, f.SrcName(), t.SrcName(), length) + c.Putln("for i := 0; i < int(%s); i++ {", length) + ReadSimpleSingleField(c, + fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) c.Putln("}") c.Putln("b = pad(b)") } + case *TypeDef: + length := f.LengthExpr.Reduce(prefix) + c.Putln("%s%s = make([]%s, %s)", + prefix, f.SrcName(), t.SrcName(), length) + c.Putln("for i := 0; i < int(%s); i++ {", length) + ReadSimpleSingleField(c, fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) + c.Putln("}") + c.Putln("b = pad(b)") case *Union: - c.Putln("v.%s = make([]%s, %s)", - f.SrcName(), t.SrcName(), f.LengthExpr.Reduce("v.", "")) - c.Putln("b += Read%sList(buf[b:], v.%s)", t.SrcName(), f.SrcName()) + c.Putln("%s%s = make([]%s, %s)", + prefix, f.SrcName(), t.SrcName(), f.LengthExpr.Reduce(prefix)) + c.Putln("b += Read%sList(buf[b:], %s%s)", + t.SrcName(), prefix, f.SrcName()) case *Struct: - c.Putln("v.%s = make([]%s, %s)", - f.SrcName(), t.SrcName(), f.LengthExpr.Reduce("v.", "")) - c.Putln("b += Read%sList(buf[b:], v.%s)", t.SrcName(), f.SrcName()) + c.Putln("%s%s = make([]%s, %s)", + prefix, f.SrcName(), t.SrcName(), f.LengthExpr.Reduce(prefix)) + c.Putln("b += Read%sList(buf[b:], %s%s)", + t.SrcName(), prefix, f.SrcName()) default: log.Panicf("Cannot read list field '%s' with %T type.", f.XmlName(), f.Type) } } -func (f *ListField) Write(c *Context) { +func (f *ListField) Write(c *Context, prefix string) { switch t := f.Type.(type) { case *Resource: - length := f.LengthExpr.Reduce("v.", "") - c.Putln("for i := 0; i < %s; i++", length) - WriteSimpleSingleField(c, fmt.Sprintf("v.%s[i]", f.SrcName()), t) + length := f.Length().Reduce(prefix) + c.Putln("for i := 0; i < int(%s); i++ {", length) + WriteSimpleSingleField(c, + fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) c.Putln("}") c.Putln("b = pad(b)") case *Base: - length := f.LengthExpr.Reduce("v.", "") + length := f.Length().Reduce(prefix) if t.SrcName() == "byte" { - c.Putln("copy(buf[b:], v.%s[:%s])", f.SrcName(), length) - c.Putln("b += pad(%s)", length) + c.Putln("copy(buf[b:], %s%s[:%s])", prefix, f.SrcName(), length) + c.Putln("b += pad(int(%s))", length) } else { - c.Putln("for i := 0; i < %s; i++ {", length) - WriteSimpleSingleField(c, fmt.Sprintf("v.%s[i]", f.SrcName()), t) + c.Putln("for i := 0; i < int(%s); i++ {", length) + WriteSimpleSingleField(c, + fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) c.Putln("}") c.Putln("b = pad(b)") } + case *TypeDef: + length := f.Length().Reduce(prefix) + c.Putln("for i := 0; i < int(%s); i++ {", length) + WriteSimpleSingleField(c, + fmt.Sprintf("%s%s[i]", prefix, f.SrcName()), t) + c.Putln("}") + c.Putln("b = pad(b)") case *Union: - c.Putln("b += %sListBytes(buf[b:], v.%s)", t.SrcName(), f.SrcName()) + c.Putln("b += %sListBytes(buf[b:], %s%s)", + t.SrcName(), prefix, f.SrcName()) case *Struct: - c.Putln("b += %sListBytes(buf[b:], v.%s)", t.SrcName(), f.SrcName()) + c.Putln("b += %sListBytes(buf[b:], %s%s)", + t.SrcName(), prefix, f.SrcName()) default: - log.Panicf("Cannot read list field '%s' with %T type.", + log.Panicf("Cannot write list field '%s' with %T type.", f.XmlName(), f.Type) } } diff --git a/nexgb/xgbgen/go_reply.go b/nexgb/xgbgen/go_reply.go deleted file mode 100644 index e561d9c..0000000 --- a/nexgb/xgbgen/go_reply.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -func (r *Request) Define(c *Context) { - c.Putln("// Request %s", r.SrcName()) - c.Putln("// size: %s", r.Size(c)) - c.Putln("") - if r.Reply != nil { - c.Putln("// Request reply for %s", r.SrcName()) - c.Putln("// size: %s", r.Reply.Size()) - c.Putln("type %s struct {", r.ReplyName()) - c.Putln("Sequence uint16") - for _, field := range r.Reply.Fields { - field.Define(c) - } - c.Putln("}") - c.Putln("") - } -} - diff --git a/nexgb/xgbgen/go_request_reply.go b/nexgb/xgbgen/go_request_reply.go new file mode 100644 index 0000000..e6180a1 --- /dev/null +++ b/nexgb/xgbgen/go_request_reply.go @@ -0,0 +1,140 @@ +package main + +import ( + "fmt" + "strings" +) + +func (r *Request) Define(c *Context) { + c.Putln("// Request %s", r.SrcName()) + c.Putln("// size: %s", r.Size(c)) + if r.Reply != nil { + c.Putln("func (c *Conn) %s(%s) (*%s, error) {", + r.SrcName(), r.ParamNameTypes(), r.ReplyName()) + c.Putln("return c.%s(c.%s(%s))", + r.ReplyName(), r.ReqName(), r.ParamNames()) + c.Putln("}") + c.Putln("") + + r.WriteRequest(c) + r.ReadReply(c) + } else { + c.Putln("// Write request to wire for %s", r.SrcName()) + c.Putln("func (c *Conn) %s(%s) {", r.SrcName(), r.ParamNameTypes()) + r.WriteRequestFields(c) + c.Putln("c.sendRequest(false, buf)") + c.Putln("}") + c.Putln("") + } +} + +func (r *Request) ReadReply(c *Context) { + c.Putln("// Request reply for %s", r.SrcName()) + c.Putln("// size: %s", r.Reply.Size()) + c.Putln("type %s struct {", r.ReplyName()) + c.Putln("Sequence uint16") + c.Putln("Length uint32") + for _, field := range r.Reply.Fields { + field.Define(c) + } + c.Putln("}") + c.Putln("") + + c.Putln("// Read reply %s", r.SrcName()) + c.Putln("func (c *Conn) %s(cook *Cookie) (*%s, error) {", + r.ReplyName(), r.ReplyName()) + c.Putln("buf, err := c.waitForReply(cook)") + c.Putln("if err != nil {") + c.Putln("return nil, err") + c.Putln("}") + c.Putln("") + c.Putln("v := new(%s)", r.ReplyName()) + c.Putln("b := 1 // skip reply determinant") + c.Putln("") + for i, field := range r.Reply.Fields { + if i == 1 { + c.Putln("v.Sequence = Get16(buf[b:])") + c.Putln("b += 2") + c.Putln("") + c.Putln("v.Length = Get32(buf[b:]) // 4-byte units") + c.Putln("b += 4") + c.Putln("") + } + field.Read(c, "v.") + c.Putln("") + } + c.Putln("return v, nil") + c.Putln("}") + c.Putln("") +} + +func (r *Request) WriteRequest(c *Context) { + c.Putln("// Write request to wire for %s", r.SrcName()) + c.Putln("func (c *Conn) %s(%s) *Cookie {", r.ReqName(), r.ParamNameTypes()) + r.WriteRequestFields(c) + c.Putln("return c.sendRequest(true, buf)") + c.Putln("}") + c.Putln("") +} + +func (r *Request) WriteRequestFields(c *Context) { + c.Putln("size := %s", r.Size(c)) + c.Putln("b := 0") + c.Putln("buf := make([]byte, size)") + c.Putln("") + c.Putln("buf[b] = %d // request opcode", r.Opcode) + c.Putln("b += 1") + c.Putln("") + for i, field := range r.Fields { + if i == 1 { + c.Putln("Put16(buf[b:], uint16(size / 4)) "+ + "// write request size in 4-byte units") + c.Putln("b += 2") + c.Putln("") + } + field.Write(c, "") + c.Putln("") + } +} + +func (r *Request) ParamNames() string { + names := make([]string, 0, len(r.Fields)) + for _, field := range r.Fields { + switch f := field.(type) { + case *ValueField: + names = append(names, f.MaskName) + names = append(names, f.ListName) + case *PadField: + continue + case *ExprField: + continue + default: + names = append(names, fmt.Sprintf("%s", field.SrcName())) + } + } + return strings.Join(names, ",") +} + +func (r *Request) ParamNameTypes() string { + nameTypes := make([]string, 0, len(r.Fields)) + for _, field := range r.Fields { + switch f := field.(type) { + case *ValueField: + // mofos... + if r.SrcName() != "ConfigureWindow" { + nameTypes = append(nameTypes, + fmt.Sprintf("%s %s", f.MaskName, f.MaskType.SrcName())) + } + nameTypes = append(nameTypes, + fmt.Sprintf("%s []uint32", f.ListName)) + case *PadField: + continue + case *ExprField: + continue + default: + nameTypes = append(nameTypes, + fmt.Sprintf("%s %s", field.SrcName(), field.SrcType())) + } + } + return strings.Join(nameTypes, ",") +} diff --git a/nexgb/xgbgen/go_single_field.go b/nexgb/xgbgen/go_single_field.go index bf31259..ea43d55 100644 --- a/nexgb/xgbgen/go_single_field.go +++ b/nexgb/xgbgen/go_single_field.go @@ -12,17 +12,17 @@ func (f *SingleField) Define(c *Context) { func ReadSimpleSingleField(c *Context, name string, typ Type) { switch t := typ.(type) { case *Resource: - c.Putln("%s = get32(buf[b:])", name) + c.Putln("%s = Id(Get32(buf[b:]))", name) case *TypeDef: switch t.Size().Eval() { case 1: c.Putln("%s = %s(buf[b])", name, t.SrcName()) case 2: - c.Putln("%s = %s(get16(buf[b:]))", name, t.SrcName()) + c.Putln("%s = %s(Get16(buf[b:]))", name, t.SrcName()) case 4: - c.Putln("%s = %s(get32(buf[b:]))", name, t.SrcName()) + c.Putln("%s = %s(Get32(buf[b:]))", name, t.SrcName()) case 8: - c.Putln("%s = %s(get64(buf[b:]))", name, t.SrcName()) + c.Putln("%s = %s(Get64(buf[b:]))", name, t.SrcName()) } case *Base: // If this is a bool, stop short and do something special. @@ -40,11 +40,11 @@ func ReadSimpleSingleField(c *Context, name string, typ Type) { case 1: val = fmt.Sprintf("buf[b]") case 2: - val = fmt.Sprintf("get16(buf[b:])") + val = fmt.Sprintf("Get16(buf[b:])") case 4: - val = fmt.Sprintf("get32(buf[b:])") + val = fmt.Sprintf("Get32(buf[b:])") case 8: - val = fmt.Sprintf("get64(buf[b:])") + val = fmt.Sprintf("Get64(buf[b:])") } // We need to convert base types if they aren't uintXX or byte @@ -61,20 +61,20 @@ func ReadSimpleSingleField(c *Context, name string, typ Type) { c.Putln("b += %s", typ.Size()) } -func (f *SingleField) Read(c *Context) { +func (f *SingleField) Read(c *Context, prefix string) { switch t := f.Type.(type) { case *Resource: - ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) + ReadSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t) case *TypeDef: - ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) + ReadSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t) case *Base: - ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) + ReadSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t) case *Struct: - c.Putln("v.%s = %s{}", f.SrcName(), t.SrcName()) - c.Putln("b += Read%s(buf[b:], &v.%s)", t.SrcName(), f.SrcName()) + c.Putln("%s%s = %s{}", prefix, f.SrcName(), t.SrcName()) + c.Putln("b += Read%s(buf[b:], &%s%s)", t.SrcName(), prefix, f.SrcName()) case *Union: - c.Putln("v.%s = %s{}", f.SrcName(), t.SrcName()) - c.Putln("b += Read%s(buf[b:], &v.%s)", t.SrcName(), f.SrcName()) + c.Putln("%s%s = %s{}", prefix, f.SrcName(), t.SrcName()) + c.Putln("b += Read%s(buf[b:], &%s%s)", t.SrcName(), prefix, f.SrcName()) default: log.Panicf("Cannot read field '%s' with %T type.", f.XmlName(), f.Type) } @@ -83,17 +83,17 @@ func (f *SingleField) Read(c *Context) { func WriteSimpleSingleField(c *Context, name string, typ Type) { switch t := typ.(type) { case *Resource: - c.Putln("put32(buf[b:], uint32(%s))", name) + c.Putln("Put32(buf[b:], uint32(%s))", name) case *TypeDef: switch t.Size().Eval() { case 1: c.Putln("buf[b] = byte(%s)", name) case 2: - c.Putln("put16(buf[b:], uint16(%s))", name) + c.Putln("Put16(buf[b:], uint16(%s))", name) case 4: - c.Putln("put32(buf[b:], uint32(%s))", name) + c.Putln("Put32(buf[b:], uint32(%s))", name) case 8: - c.Putln("put64(buf[b:], uint64(%s))", name) + c.Putln("Put64(buf[b:], uint64(%s))", name) } case *Base: // If this is a bool, stop short and do something special. @@ -115,21 +115,21 @@ func WriteSimpleSingleField(c *Context, name string, typ Type) { } case 2: if t.SrcName() != "uint16" { - c.Putln("put16(buf[b:], uint16(%s))", name) + c.Putln("Put16(buf[b:], uint16(%s))", name) } else { - c.Putln("put16(buf[b:], %s)", name) + c.Putln("Put16(buf[b:], %s)", name) } case 4: if t.SrcName() != "uint32" { - c.Putln("put32(buf[b:], uint32(%s))", name) + c.Putln("Put32(buf[b:], uint32(%s))", name) } else { - c.Putln("put32(buf[b:], %s)", name) + c.Putln("Put32(buf[b:], %s)", name) } case 8: if t.SrcName() != "uint64" { - c.Putln("put64(buf[b:], uint64(%s))", name) + c.Putln("Put64(buf[b:], uint64(%s))", name) } else { - c.Putln("put64(buf[b:], %s)", name) + c.Putln("Put64(buf[b:], %s)", name) } } default: @@ -140,23 +140,23 @@ func WriteSimpleSingleField(c *Context, name string, typ Type) { c.Putln("b += %s", typ.Size()) } -func (f *SingleField) Write(c *Context) { +func (f *SingleField) Write(c *Context, prefix string) { switch t := f.Type.(type) { case *Resource: - ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) + WriteSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t) case *TypeDef: - ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) + WriteSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t) case *Base: - ReadSimpleSingleField(c, fmt.Sprintf("v.%s", f.SrcName()), t) + WriteSimpleSingleField(c, fmt.Sprintf("%s%s", prefix, f.SrcName()), t) case *Union: c.Putln("{") - c.Putln("unionBytes := v.%s.Bytes()", f.SrcName()) + c.Putln("unionBytes := %s%s.Bytes()", prefix, f.SrcName()) c.Putln("copy(buf[b:], unionBytes)") c.Putln("b += pad(len(unionBytes))") c.Putln("}") case *Struct: c.Putln("{") - c.Putln("structBytes := v.%s.Bytes()", f.SrcName()) + c.Putln("structBytes := %s%s.Bytes()", prefix, f.SrcName()) c.Putln("copy(buf[b:], structBytes)") c.Putln("b += pad(len(structBytes))") c.Putln("}") diff --git a/nexgb/xgbgen/go_struct.go b/nexgb/xgbgen/go_struct.go index 600ebaf..1e43199 100644 --- a/nexgb/xgbgen/go_struct.go +++ b/nexgb/xgbgen/go_struct.go @@ -22,8 +22,11 @@ func (s *Struct) Define(c *Context) { // Write function that writes a list of this struct. s.WriteList(c) - // Write function that computes the size of a list of these structs. - s.WriteListSize(c) + // Write function that computes the size of a list of these structs, + // IF there is a list field in this struct. + if s.HasList() { + s.WriteListSize(c) + } } // Read for a struct creates a function 'ReadStructName' that takes a source @@ -37,7 +40,8 @@ func (s *Struct) Read(c *Context) { c.Putln("b := 0") c.Putln("") for _, field := range s.Fields { - field.Read(c) + field.Read(c, "v.") + c.Putln("") } c.Putln("return b") @@ -68,11 +72,12 @@ func (s *Struct) ReadList(c *Context) { func (s *Struct) Write(c *Context) { c.Putln("// Struct write %s", s.SrcName()) c.Putln("func (v %s) Bytes() []byte {", s.SrcName()) - c.Putln("buf := make([]byte, %s)", s.Size().Reduce("v.", "")) + c.Putln("buf := make([]byte, %s)", s.Size().Reduce("v.")) c.Putln("b := 0") c.Putln("") for _, field := range s.Fields { - field.Write(c) + field.Write(c, "v.") + c.Putln("") } c.Putln("return buf") c.Putln("}") @@ -87,7 +92,7 @@ func (s *Struct) WriteList(c *Context) { c.Putln("var structBytes []byte") c.Putln("for _, item := range list {") c.Putln("structBytes = item.Bytes()") - c.Putln("copy(buf[b:], len(structBytes))") + c.Putln("copy(buf[b:], structBytes)") c.Putln("b += pad(len(structBytes))") c.Putln("}") c.Putln("return b") @@ -100,7 +105,7 @@ func (s *Struct) WriteListSize(c *Context) { c.Putln("func %sListSize(list []%s) int {", s.SrcName(), s.SrcName()) c.Putln("size := 0") c.Putln("for _, item := range list {") - c.Putln("size += %s", s.Size().Reduce("item.", "")) + c.Putln("size += %s", s.Size().Reduce("item.")) c.Putln("}") c.Putln("return size") c.Putln("}") diff --git a/nexgb/xgbgen/go_union.go b/nexgb/xgbgen/go_union.go index 3b7365d..9f339af 100644 --- a/nexgb/xgbgen/go_union.go +++ b/nexgb/xgbgen/go_union.go @@ -34,9 +34,6 @@ func (u *Union) Define(c *Context) { // Write function that writes a list of this union. u.WriteList(c) - - // Write function that computes the size of a list of these unions. - u.WriteListSize(c) } func (u *Union) New(c *Context) { @@ -49,7 +46,7 @@ func (u *Union) New(c *Context) { c.Putln("var b int") c.Putln("buf := make([]byte, %s)", u.Size()) c.Putln("") - field.Write(c) + field.Write(c, "") c.Putln("") c.Putln("// Create the Union type") c.Putln("v := %s{}", u.SrcName()) @@ -58,7 +55,7 @@ func (u *Union) New(c *Context) { c.Putln("") for _, field2 := range u.Fields { c.Putln("b = 0 // always read the same bytes") - field2.Read(c) + field2.Read(c, "v.") c.Putln("") } c.Putln("return v") @@ -74,7 +71,7 @@ func (u *Union) Read(c *Context) { c.Putln("") for _, field := range u.Fields { c.Putln("b = 0 // re-read the same bytes") - field.Read(c) + field.Read(c, "v.") c.Putln("") } c.Putln("return %s", u.Size()) @@ -106,10 +103,10 @@ func (u *Union) Write(c *Context) { c.Putln("// Each field in a union must contain the same data.") c.Putln("// So simply pick the first field and write that to the wire.") c.Putln("func (v %s) Bytes() []byte {", u.SrcName()) - c.Putln("buf := make([]byte, %s)", u.Size().Reduce("v.", "")) + c.Putln("buf := make([]byte, %s)", u.Size().Reduce("v.")) c.Putln("b := 0") c.Putln("") - u.Fields[0].Write(c) + u.Fields[0].Write(c, "v.") c.Putln("return buf") c.Putln("}") c.Putln("") @@ -123,7 +120,7 @@ func (u *Union) WriteList(c *Context) { c.Putln("var unionBytes []byte") c.Putln("for _, item := range list {") c.Putln("unionBytes = item.Bytes()") - c.Putln("copy(buf[b:], len(unionBytes))") + c.Putln("copy(buf[b:], unionBytes)") c.Putln("b += pad(len(unionBytes))") c.Putln("}") c.Putln("return b") @@ -136,7 +133,7 @@ func (u *Union) WriteListSize(c *Context) { c.Putln("func %sListSize(list []%s) int {", u.SrcName(), u.SrcName()) c.Putln("size := 0") c.Putln("for _, item := range list {") - c.Putln("size += %s", u.Size().Reduce("item.", "")) + c.Putln("size += %s", u.Size().Reduce("item.")) c.Putln("}") c.Putln("return size") c.Putln("}") diff --git a/nexgb/xgbgen/representation.go b/nexgb/xgbgen/representation.go index e5d2202..ef62157 100644 --- a/nexgb/xgbgen/representation.go +++ b/nexgb/xgbgen/representation.go @@ -65,6 +65,10 @@ func (r *Request) ReplyName() string { return fmt.Sprintf("%sReply", r.SrcName()) } +func (r *Request) ReqName() string { + return fmt.Sprintf("%sRequest", r.SrcName()) +} + // Size for Request needs a context. // Namely, if this is an extension, we need to account for *four* bytes // of a header (extension opcode, request opcode, and the sequence number). @@ -80,7 +84,20 @@ func (r *Request) Size(c *Context) Size { } for _, field := range r.Fields { - size = size.Add(field.Size()) + switch field.(type) { + case *LocalField: + continue + case *SingleField: + // mofos!!! + if r.SrcName() == "ConfigureWindow" && + field.SrcName() == "ValueMask" { + + continue + } + size = size.Add(field.Size()) + default: + size = size.Add(field.Size()) + } } return size } diff --git a/nexgb/xgbgen/translation.go b/nexgb/xgbgen/translation.go index 9c7603b..fe5a52b 100644 --- a/nexgb/xgbgen/translation.go +++ b/nexgb/xgbgen/translation.go @@ -138,7 +138,7 @@ func (x *XMLEvent) Translate() *Event { Fields: make([]Field, len(x.Fields)), } for i, field := range x.Fields { - ev.Fields[i] = field.Translate() + ev.Fields[i] = field.Translate(ev) } return ev } @@ -158,7 +158,7 @@ func (x *XMLError) Translate() *Error { Fields: make([]Field, len(x.Fields)), } for i, field := range x.Fields { - err.Fields[i] = field.Translate() + err.Fields[i] = field.Translate(err) } return err } @@ -177,7 +177,7 @@ func (x *XMLStruct) Translate() *Struct { Fields: make([]Field, len(x.Fields)), } for i, field := range x.Fields { - s.Fields[i] = field.Translate() + s.Fields[i] = field.Translate(s) } return s } @@ -188,7 +188,7 @@ func (x *XMLUnion) Translate() *Union { Fields: make([]Field, len(x.Fields)), } for i, field := range x.Fields { - u.Fields[i] = field.Translate() + u.Fields[i] = field.Translate(u) } return u } @@ -202,7 +202,7 @@ func (x *XMLRequest) Translate() *Request { Reply: x.Reply.Translate(), } for i, field := range x.Fields { - r.Fields[i] = field.Translate() + r.Fields[i] = field.Translate(r) } // Address bug (or legacy code) in QueryTextExtents. @@ -230,7 +230,7 @@ func (x *XMLReply) Translate() *Reply { Fields: make([]Field, len(x.Fields)), } for i, field := range x.Fields { - r.Fields[i] = field.Translate() + r.Fields[i] = field.Translate(r) } return r } @@ -309,7 +309,7 @@ func (x *XMLExpression) Translate() Expression { panic("unreachable") } -func (x *XMLField) Translate() Field { +func (x *XMLField) Translate(parent interface{}) Field { switch x.XMLName.Local { case "pad": return &PadField{ @@ -339,6 +339,7 @@ func (x *XMLField) Translate() Field { } case "valueparam": return &ValueField{ + Parent: parent, MaskType: newTranslation(x.ValueMaskType), MaskName: x.ValueMaskName, ListName: x.ValueListName, @@ -365,7 +366,7 @@ func (x *XMLBitcase) Translate() *Bitcase { Fields: make([]Field, len(x.Fields)), } for i, field := range x.Fields { - b.Fields[i] = field.Translate() + b.Fields[i] = field.Translate(b) } return b } diff --git a/nexgb/xgbgen/type.go b/nexgb/xgbgen/type.go index d8e76a2..3498463 100644 --- a/nexgb/xgbgen/type.go +++ b/nexgb/xgbgen/type.go @@ -334,6 +334,18 @@ func (s *Struct) Initialize(p *Protocol) { } } +// HasList returns whether there is a field in this struct that is a list. +// When true, a more involved calculation is necessary to compute this struct's +// size. +func (s *Struct) HasList() bool { + for _, field := range s.Fields { + if _, ok := field.(*ListField); ok { + return true + } + } + return false +} + type Union struct { srcName string xmlName string -- cgit v1.2.3