aboutsummaryrefslogtreecommitdiff
path: root/nexgb/xgbgen
diff options
context:
space:
mode:
Diffstat (limited to 'nexgb/xgbgen')
-rw-r--r--nexgb/xgbgen/context.go21
-rw-r--r--nexgb/xgbgen/expression.go73
-rw-r--r--nexgb/xgbgen/field.go75
-rw-r--r--nexgb/xgbgen/go.go53
-rw-r--r--nexgb/xgbgen/go_error.go88
-rw-r--r--nexgb/xgbgen/go_event.go15
-rw-r--r--nexgb/xgbgen/go_list.go97
-rw-r--r--nexgb/xgbgen/go_reply.go19
-rw-r--r--nexgb/xgbgen/go_request_reply.go140
-rw-r--r--nexgb/xgbgen/go_single_field.go62
-rw-r--r--nexgb/xgbgen/go_struct.go19
-rw-r--r--nexgb/xgbgen/go_union.go17
-rw-r--r--nexgb/xgbgen/representation.go19
-rw-r--r--nexgb/xgbgen/translation.go17
-rw-r--r--nexgb/xgbgen/type.go12
15 files changed, 545 insertions, 182 deletions
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