From 39507f86ab0468292c24081a80f41c1799d6b477 Mon Sep 17 00:00:00 2001
From: "Andrew Gallant (Ocelot)" <Andrew.Gallant@tufts.edu>
Date: Wed, 2 May 2012 01:46:30 -0400
Subject: finally starting on the crescendo: requests and replies.

---
 nexgb/xgbgen/context.go        |  3 ++
 nexgb/xgbgen/field.go          |  4 ++-
 nexgb/xgbgen/go.go             |  9 ------
 nexgb/xgbgen/go_error.go       | 65 ++++++++++++++++++++++++++++++------------
 nexgb/xgbgen/go_event.go       | 21 ++++++++------
 nexgb/xgbgen/go_list.go        |  4 +--
 nexgb/xgbgen/go_reply.go       | 19 ++++++++++++
 nexgb/xgbgen/representation.go | 53 ++++++++++++++++++++++++++++++++++
 nexgb/xgbgen/translation.go    | 12 ++++----
 nexgb/xgbgen/type.go           |  9 ++++--
 nexgb/xgbgen/xml.go            |  2 +-
 11 files changed, 153 insertions(+), 48 deletions(-)
 create mode 100644 nexgb/xgbgen/go_reply.go

diff --git a/nexgb/xgbgen/context.go b/nexgb/xgbgen/context.go
index 67801c7..33641b3 100644
--- a/nexgb/xgbgen/context.go
+++ b/nexgb/xgbgen/context.go
@@ -51,4 +51,7 @@ func (c *Context) Morph(xmlBytes []byte) {
 	for _, typ := range c.protocol.Types {
 		typ.Define(c)
 	}
+	for _, req := range c.protocol.Requests {
+		req.Define(c)
+	}
 }
diff --git a/nexgb/xgbgen/field.go b/nexgb/xgbgen/field.go
index 6d39af2..8d8412c 100644
--- a/nexgb/xgbgen/field.go
+++ b/nexgb/xgbgen/field.go
@@ -102,8 +102,10 @@ func (f *ListField) Size() Size {
 		return newExpressionSize(simpleLen)
 	case *Resource:
 		return newExpressionSize(simpleLen)
+	case *TypeDef:
+		return newExpressionSize(simpleLen)
 	default:
-		log.Fatalf("Cannot compute list size with type '%T'.", f.Type)
+		log.Panicf("Cannot compute list size with type '%T'.", f.Type)
 	}
 	panic("unreachable")
 }
diff --git a/nexgb/xgbgen/go.go b/nexgb/xgbgen/go.go
index 11e413b..b7b153e 100644
--- a/nexgb/xgbgen/go.go
+++ b/nexgb/xgbgen/go.go
@@ -105,57 +105,48 @@ func (f *PadField) Write(c *Context) {
 // Local fields
 func (f *LocalField) Define(c *Context) {
 	c.Putln("// local field: %s %s", f.SrcName(), f.Type.SrcName())
-	panic("todo")
 }
 
 func (f *LocalField) Read(c *Context) {
 	c.Putln("// reading local field: %s (%s) :: %s",
 		f.SrcName(), f.Size(), f.Type.SrcName())
-	panic("todo")
 }
 
 func (f *LocalField) Write(c *Context) {
 	c.Putln("// writing local field: %s (%s) :: %s",
 		f.SrcName(), f.Size(), f.Type.SrcName())
-	panic("todo")
 }
 
 // Expr fields
 func (f *ExprField) Define(c *Context) {
 	c.Putln("// expression field: %s %s (%s)",
 		f.SrcName(), f.Type.SrcName(), f.Expr)
-	panic("todo")
 }
 
 func (f *ExprField) Read(c *Context) {
 	c.Putln("// reading expression field: %s (%s) (%s) :: %s",
 		f.SrcName(), f.Size(), f.Expr, f.Type.SrcName())
-	panic("todo")
 }
 
 func (f *ExprField) Write(c *Context) {
 	c.Putln("// writing expression field: %s (%s) (%s) :: %s",
 		f.SrcName(), f.Size(), f.Expr, f.Type.SrcName())
-	panic("todo")
 }
 
 // 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) {
 	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)
-	panic("todo")
 }
 
 // Switch field
diff --git a/nexgb/xgbgen/go_error.go b/nexgb/xgbgen/go_error.go
index 493a8b9..17c0db5 100644
--- a/nexgb/xgbgen/go_error.go
+++ b/nexgb/xgbgen/go_error.go
@@ -3,15 +3,53 @@ package main
 // Error types
 func (e *Error) Define(c *Context) {
 	c.Putln("// Error definition %s (%d)", e.SrcName(), e.Number)
+	c.Putln("// Size: %s", e.Size())
+	c.Putln("")
+	c.Putln("const %s = %d", e.ErrConst(), e.Number)
+	c.Putln("")
+	c.Putln("type %s struct {", e.ErrType())
+	c.Putln("Sequence uint16")
+	c.Putln("NiceName string")
+	for _, field := range e.Fields {
+		field.Define(c)
+	}
+	c.Putln("}")
 	c.Putln("")
-}
 
-func (e *Error) Read(c *Context, prefix string) {
-	c.Putln("// Error read %s", e.SrcName())
+	// Read defines a function that transforms a byte slice into this
+	// 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("")
+
+	// Let's the XGB event loop read this error.
+	c.Putln("func init() {")
+	c.Putln("newErrorFuncs[%d] = New%s", e.Number, e.ErrType())
+	c.Putln("}")
+	c.Putln("")
 }
 
-func (e *Error) Write(c *Context, prefix string) {
-	c.Putln("// Error write %s", e.SrcName())
+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("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("b += 2")
+	c.Putln("")
+	for _, field := range e.Fields {
+		field.Read(c)
+		c.Putln("")
+	}
+	c.Putln("return v")
+	c.Putln("}")
+	c.Putln("")
 }
 
 // ErrorCopy types
@@ -27,31 +65,20 @@ func (e *ErrorCopy) Define(c *Context) {
 	// error struct.
 	e.Read(c)
 
-	// Write defines a function that transoforms this error struct into
-	// a byte slice.
-	e.Write(c)
-
 	// Makes sure that this error type is an Error interface.
 	c.Putln("func (err %s) ImplementsError() { }", e.ErrType())
 	c.Putln("")
 
 	// Let's the XGB know how to read this error.
 	c.Putln("func init() {")
-	c.Putln("newErrorFuncs[%d] = New%s", e.Number, e.SrcName())
+	c.Putln("newErrorFuncs[%d] = New%s", e.Number, e.ErrType())
 	c.Putln("}")
 	c.Putln("")
 }
 
 func (e *ErrorCopy) Read(c *Context) {
-	c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.ErrType())
-	c.Putln("return (%s)(New%s(buf))", e.ErrType(), e.Old.SrcName())
-	c.Putln("}")
-	c.Putln("")
-}
-
-func (e *ErrorCopy) Write(c *Context) {
-	c.Putln("func (err %s) Bytes() []byte {", e.ErrType())
-	c.Putln("return (%s)(err).Bytes()", e.Old.(*Error).ErrType())
+	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("}")
 	c.Putln("")
 }
diff --git a/nexgb/xgbgen/go_event.go b/nexgb/xgbgen/go_event.go
index e6d40b0..fe2a77e 100644
--- a/nexgb/xgbgen/go_event.go
+++ b/nexgb/xgbgen/go_event.go
@@ -4,8 +4,13 @@ package main
 func (e *Event) Define(c *Context) {
 	c.Putln("// Event definition %s (%d)", e.SrcName(), e.Number)
 	c.Putln("// Size: %s", e.Size())
+	c.Putln("")
+	c.Putln("const %s = %d", e.SrcName(), e.Number)
+	c.Putln("")
 	c.Putln("type %s struct {", e.EvType())
-	c.Putln("Sequence uint16")
+	if !e.NoSequence {
+		c.Putln("Sequence uint16")
+	}
 	for _, field := range e.Fields {
 		field.Define(c)
 	}
@@ -16,7 +21,7 @@ func (e *Event) Define(c *Context) {
 	// event struct.
 	e.Read(c)
 
-	// Write defines a function that transoforms this event struct into
+	// Write defines a function that transforms this event struct into
 	// a byte slice.
 	e.Write(c)
 
@@ -26,14 +31,14 @@ func (e *Event) Define(c *Context) {
 
 	// Let's the XGB event loop read this event.
 	c.Putln("func init() {")
-	c.Putln("newEventFuncs[%d] = New%s", e.Number, e.SrcName())
+	c.Putln("newEventFuncs[%d] = New%s", e.Number, e.EvType())
 	c.Putln("}")
 	c.Putln("")
 }
 
 func (e *Event) Read(c *Context) {
 	c.Putln("// Event read %s", e.SrcName())
-	c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.EvType())
+	c.Putln("func New%s(buf []byte) %s {", e.EvType(), e.EvType())
 	c.Putln("v := %s{}", e.EvType())
 	c.Putln("b := 1 // don't read event number")
 	c.Putln("")
@@ -97,21 +102,21 @@ func (e *EventCopy) Define(c *Context) {
 
 	// Let's the XGB event loop read this event.
 	c.Putln("func init() {")
-	c.Putln("newEventFuncs[%d] = New%s", e.Number, e.SrcName())
+	c.Putln("newEventFuncs[%d] = New%s", e.Number, e.EvType())
 	c.Putln("}")
 	c.Putln("")
 }
 
 func (e *EventCopy) Read(c *Context) {
-	c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.EvType())
-	c.Putln("return (%s)(New%s(buf))", e.EvType(), e.Old.SrcName())
+	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("}")
 	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(ev).Bytes()", e.Old.(*Event).EvType())
 	c.Putln("}")
 	c.Putln("")
 }
diff --git a/nexgb/xgbgen/go_list.go b/nexgb/xgbgen/go_list.go
index a95ba71..67ecd34 100644
--- a/nexgb/xgbgen/go_list.go
+++ b/nexgb/xgbgen/go_list.go
@@ -41,7 +41,7 @@ func (f *ListField) Read(c *Context) {
 			f.SrcName(), t.SrcName(), f.LengthExpr.Reduce("v.", ""))
 		c.Putln("b += Read%sList(buf[b:], v.%s)", t.SrcName(), f.SrcName())
 	default:
-		log.Fatalf("Cannot read list field '%s' with %T type.",
+		log.Panicf("Cannot read list field '%s' with %T type.",
 			f.XmlName(), f.Type)
 	}
 }
@@ -70,7 +70,7 @@ func (f *ListField) Write(c *Context) {
 	case *Struct:
 		c.Putln("b += %sListBytes(buf[b:], v.%s)", t.SrcName(), f.SrcName())
 	default:
-		log.Fatalf("Cannot read list field '%s' with %T type.",
+		log.Panicf("Cannot read list field '%s' with %T type.",
 			f.XmlName(), f.Type)
 	}
 }
diff --git a/nexgb/xgbgen/go_reply.go b/nexgb/xgbgen/go_reply.go
new file mode 100644
index 0000000..e561d9c
--- /dev/null
+++ b/nexgb/xgbgen/go_reply.go
@@ -0,0 +1,19 @@
+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/representation.go b/nexgb/xgbgen/representation.go
index 2d33a45..e5d2202 100644
--- a/nexgb/xgbgen/representation.go
+++ b/nexgb/xgbgen/representation.go
@@ -1,5 +1,10 @@
 package main
 
+import (
+	"fmt"
+	"log"
+)
+
 type Protocol struct {
 	Name         string
 	ExtXName     string
@@ -44,10 +49,58 @@ func (r *Request) Initialize(p *Protocol) {
 	}
 }
 
+func (r *Request) SrcName() string {
+	return r.srcName
+}
+
+func (r *Request) XmlName() string {
+	return r.xmlName
+}
+
+func (r *Request) ReplyName() string {
+	if r.Reply == nil {
+		log.Panicf("Cannot call 'ReplyName' on request %s, which has no reply.",
+			r.SrcName())
+	}
+	return fmt.Sprintf("%sReply", 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).
+// If it's a core protocol request, then we only account for *three*
+// bytes of the header (remove the extension opcode).
+func (r *Request) Size(c *Context) Size {
+	size := newFixedSize(0)
+
+	if c.protocol.Name == "xproto" {
+		size = size.Add(newFixedSize(3))
+	} else {
+		size = size.Add(newFixedSize(4))
+	}
+
+	for _, field := range r.Fields {
+		size = size.Add(field.Size())
+	}
+	return size
+}
+
 type Reply struct {
 	Fields []Field
 }
 
+func (r *Reply) Size() Size {
+	size := newFixedSize(0)
+
+	// Account for reply discriminant, sequence number and reply length
+	size = size.Add(newFixedSize(7))
+
+	for _, field := range r.Fields {
+		size = size.Add(field.Size())
+	}
+	return size
+}
+
 func (r *Reply) Initialize(p *Protocol) {
 	for _, field := range r.Fields {
 		field.Initialize(p)
diff --git a/nexgb/xgbgen/translation.go b/nexgb/xgbgen/translation.go
index 36daa8b..9c7603b 100644
--- a/nexgb/xgbgen/translation.go
+++ b/nexgb/xgbgen/translation.go
@@ -210,11 +210,13 @@ func (x *XMLRequest) Translate() *Request {
 	// computation of the 'odd_length' field. However, 'string_len' is not
 	// defined. Therefore, let's forcefully add it as a 'local field'.
 	// (i.e., a parameter in the caller but does not get send over the wire.)
-	stringLenLocal := &LocalField{&SingleField{
-		xmlName: "string_len",
-		Type:    newTranslation("CARD16"),
-	}}
-	r.Fields = append(r.Fields, stringLenLocal)
+	if x.Name == "QueryTextExtents" {
+		stringLenLocal := &LocalField{&SingleField{
+			xmlName: "string_len",
+			Type:    newTranslation("CARD16"),
+		}}
+		r.Fields = append(r.Fields, stringLenLocal)
+	}
 
 	return r
 }
diff --git a/nexgb/xgbgen/type.go b/nexgb/xgbgen/type.go
index 1e06bda..d8e76a2 100644
--- a/nexgb/xgbgen/type.go
+++ b/nexgb/xgbgen/type.go
@@ -221,7 +221,7 @@ func (e *EventCopy) XmlName() string {
 }
 
 func (e *EventCopy) Size() Size {
-	panic("Cannot take size of EventCopy type.")
+	return newExpressionSize(&Value{v: 32})
 }
 
 func (e *EventCopy) Initialize(p *Protocol) {
@@ -252,11 +252,14 @@ func (e *Error) XmlName() string {
 }
 
 func (e *Error) Size() Size {
-	panic("Cannot take size of Error type.")
+	return newExpressionSize(&Value{v: 32})
 }
 
 func (e *Error) Initialize(p *Protocol) {
 	e.srcName = TypeSrcName(p, e)
+	for _, field := range e.Fields {
+		field.Initialize(p)
+	}
 }
 
 func (e *Error) ErrConst() string {
@@ -283,7 +286,7 @@ func (e *ErrorCopy) XmlName() string {
 }
 
 func (e *ErrorCopy) Size() Size {
-	panic("Cannot take size of ErrorCopy type.")
+	return newExpressionSize(&Value{v: 32})
 }
 
 func (e *ErrorCopy) Initialize(p *Protocol) {
diff --git a/nexgb/xgbgen/xml.go b/nexgb/xgbgen/xml.go
index f219c2d..1b2f89a 100644
--- a/nexgb/xgbgen/xml.go
+++ b/nexgb/xgbgen/xml.go
@@ -135,7 +135,7 @@ type XMLEvents []*XMLEvent
 type XMLEvent struct {
 	Name       string    `xml:"name,attr"`
 	Number     int       `xml:"number,attr"`
-	NoSequence bool      `xml:"no-sequence-number,true"`
+	NoSequence bool      `xml:"no-sequence-number,attr"`
 	Fields     XMLFields `xml:",any"`
 }
 
-- 
cgit v1.2.3-70-g09d2