diff options
Diffstat (limited to 'nexgb/xgbgen')
| -rw-r--r-- | nexgb/xgbgen/context.go | 21 | ||||
| -rw-r--r-- | nexgb/xgbgen/expression.go | 73 | ||||
| -rw-r--r-- | nexgb/xgbgen/field.go | 75 | ||||
| -rw-r--r-- | nexgb/xgbgen/go.go | 53 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_error.go | 88 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_event.go | 15 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_list.go | 97 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_reply.go | 19 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_request_reply.go | 140 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_single_field.go | 62 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_struct.go | 19 | ||||
| -rw-r--r-- | nexgb/xgbgen/go_union.go | 17 | ||||
| -rw-r--r-- | nexgb/xgbgen/representation.go | 19 | ||||
| -rw-r--r-- | nexgb/xgbgen/translation.go | 17 | ||||
| -rw-r--r-- | nexgb/xgbgen/type.go | 12 | 
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  | 
