From c222d406b09de529388fcd248476e9ae258895b8 Mon Sep 17 00:00:00 2001
From: "Andrew Gallant (Ocelot)" <Andrew.Gallant@tufts.edu>
Date: Sat, 5 May 2012 02:55:38 -0400
Subject: converting to new reply/cookie scheme

---
 nexgb/xgbgen/expression.go       | 27 +++++++++++++
 nexgb/xgbgen/go_event.go         | 16 ++++++++
 nexgb/xgbgen/go_request_reply.go | 84 +++++++++++++++++++++++++++-------------
 nexgb/xgbgen/representation.go   | 23 ++++++++++-
 4 files changed, 122 insertions(+), 28 deletions(-)

diff --git a/nexgb/xgbgen/expression.go b/nexgb/xgbgen/expression.go
index 12bcb19..6a8aa52 100644
--- a/nexgb/xgbgen/expression.go
+++ b/nexgb/xgbgen/expression.go
@@ -158,6 +158,33 @@ func (e *UnaryOp) Initialize(p *Protocol) {
 	e.Expr.Initialize(p)
 }
 
+type Padding struct {
+	Expr Expression
+}
+
+func (e *Padding) Concrete() bool {
+	return e.Expr.Concrete()
+}
+
+func (e *Padding) Eval() uint {
+	return uint(pad(int(e.Expr.Eval())))
+}
+
+func (e *Padding) Reduce(prefix string) string {
+	if e.Concrete() {
+		return fmt.Sprintf("%d", e.Eval())
+	}
+	return fmt.Sprintf("pad(%s)", e.Expr.Reduce(prefix))
+}
+
+func (e *Padding) String() string {
+	return e.Reduce("")
+}
+
+func (e *Padding) Initialize(p *Protocol) {
+	e.Expr.Initialize(p)
+}
+
 type PopCount struct {
 	Expr Expression
 }
diff --git a/nexgb/xgbgen/go_event.go b/nexgb/xgbgen/go_event.go
index 71252a7..41f9320 100644
--- a/nexgb/xgbgen/go_event.go
+++ b/nexgb/xgbgen/go_event.go
@@ -28,6 +28,14 @@ func (e *Event) Define(c *Context) {
 	// Makes sure that this event type is an Event interface.
 	c.Putln("func (v %s) ImplementsEvent() { }", e.EvType())
 	c.Putln("")
+	c.Putln("func (v %s) SequenceId() uint16 {", e.EvType())
+	if e.NoSequence {
+		c.Putln("return uint16(0)")
+	} else {
+		c.Putln("return v.Sequence")
+	}
+	c.Putln("}")
+	c.Putln("")
 
 	// Let's the XGB event loop read this event.
 	c.Putln("func init() {")
@@ -99,6 +107,14 @@ func (e *EventCopy) Define(c *Context) {
 	// Makes sure that this event type is an Event interface.
 	c.Putln("func (v %s) ImplementsEvent() { }", e.EvType())
 	c.Putln("")
+	c.Putln("func (v %s) SequenceId() uint16 {", e.EvType())
+	if e.Old.(*Event).NoSequence {
+		c.Putln("return uint16(0)")
+	} else {
+		c.Putln("return v.Sequence")
+	}
+	c.Putln("}")
+	c.Putln("")
 
 	// Let's the XGB event loop read this event.
 	c.Putln("func init() {")
diff --git a/nexgb/xgbgen/go_request_reply.go b/nexgb/xgbgen/go_request_reply.go
index e6180a1..00c48f9 100644
--- a/nexgb/xgbgen/go_request_reply.go
+++ b/nexgb/xgbgen/go_request_reply.go
@@ -8,30 +8,51 @@ import (
 func (r *Request) Define(c *Context) {
 	c.Putln("// Request %s", r.SrcName())
 	c.Putln("// size: %s", r.Size(c))
+	c.Putln("type %s cookie", r.CookieName())
 	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("func (c *Conn) %s(%s) %s {",
+			r.SrcName(), r.ParamNameTypes(), r.CookieName())
+		c.Putln("cookie := c.newCookie(true, true)")
+		c.Putln("c.newRequest(%s(%s), cookie)", r.ReqName(), r.ParamNames())
+		c.Putln("return %s(cookie)", r.CookieName())
+		c.Putln("}")
+		c.Putln("")
+
+		c.Putln("func (c *Conn) %sUnchecked(%s) %s {",
+			r.SrcName(), r.ParamNameTypes(), r.CookieName())
+		c.Putln("cookie := c.newCookie(false, true)")
+		c.Putln("c.newRequest(%s(%s), cookie)", r.ReqName(), r.ParamNames())
+		c.Putln("return %s(cookie)", r.CookieName())
 		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("func (c *Conn) %s(%s) %s {",
+			r.SrcName(), r.ParamNameTypes(), r.CookieName())
+		c.Putln("cookie := c.newCookie(false, false)")
+		c.Putln("c.newRequest(%s(%s), cookie)", r.ReqName(), r.ParamNames())
+		c.Putln("return %s(cookie)", r.CookieName())
+		c.Putln("}")
+		c.Putln("")
+
+		c.Putln("func (c *Conn) %sChecked(%s) %s {",
+			r.SrcName(), r.ParamNameTypes(), r.CookieName())
+		c.Putln("cookie := c.newCookie(true, false)")
+		c.Putln("c.newRequest(%s(%s), cookie)", r.ReqName(), r.ParamNames())
+		c.Putln("return %s(cookie)", r.CookieName())
 		c.Putln("}")
 		c.Putln("")
 	}
+
+	r.WriteRequest(c)
 }
 
 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("type %s struct {", r.ReplyTypeName())
 	c.Putln("Sequence uint16")
 	c.Putln("Length uint32")
 	for _, field := range r.Reply.Fields {
@@ -40,15 +61,21 @@ func (r *Request) ReadReply(c *Context) {
 	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("// Waits and reads reply data from request %s", r.SrcName())
+	c.Putln("func (cook %s) Reply() (*%s, error) {",
+		r.CookieName(), r.ReplyTypeName())
+		c.Putln("buf, err := cookie(cook).reply()")
+		c.Putln("if err != nil {")
+		c.Putln("return nil, err")
+		c.Putln("}")
+		c.Putln("return %s(buf), nil", r.ReplyName())
 	c.Putln("}")
 	c.Putln("")
-	c.Putln("v := new(%s)", r.ReplyName())
+
+	c.Putln("// Read reply into structure from buffer for %s", r.SrcName())
+	c.Putln("func %s(buf []byte) *%s {",
+		r.ReplyName(), r.ReplyTypeName())
+	c.Putln("v := new(%s)", r.ReplyTypeName())
 	c.Putln("b := 1 // skip reply determinant")
 	c.Putln("")
 	for i, field := range r.Reply.Fields {
@@ -63,21 +90,14 @@ func (r *Request) ReadReply(c *Context) {
 		field.Read(c, "v.")
 		c.Putln("")
 	}
-	c.Putln("return v, nil")
+	c.Putln("return v")
 	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("func %s(%s) []byte {", r.ReqName(), r.ParamNameTypes())
 	c.Putln("size := %s", r.Size(c))
 	c.Putln("b := 0")
 	c.Putln("buf := make([]byte, size)")
@@ -85,6 +105,12 @@ func (r *Request) WriteRequestFields(c *Context) {
 	c.Putln("buf[b] = %d // request opcode", r.Opcode)
 	c.Putln("b += 1")
 	c.Putln("")
+	if strings.ToLower(c.protocol.Name) != "xproto" {
+		c.Putln("buf[b] = c.extensions[\"%s\"]",
+			strings.ToUpper(c.protocol.ExtXName))
+		c.Putln("b += 1")
+		c.Putln("")
+	}
 	for i, field := range r.Fields {
 		if i == 1 {
 			c.Putln("Put16(buf[b:], uint16(size / 4)) "+
@@ -95,6 +121,9 @@ func (r *Request) WriteRequestFields(c *Context) {
 		field.Write(c, "")
 		c.Putln("")
 	}
+	c.Putln("return buf")
+	c.Putln("}")
+	c.Putln("")
 }
 
 func (r *Request) ParamNames() string {
@@ -102,7 +131,10 @@ func (r *Request) ParamNames() string {
 	for _, field := range r.Fields {
 		switch f := field.(type) {
 		case *ValueField:
-			names = append(names, f.MaskName)
+			// mofos...
+			if r.SrcName() != "ConfigureWindow" {
+				names = append(names, f.MaskName)
+			}
 			names = append(names, f.ListName)
 		case *PadField:
 			continue
diff --git a/nexgb/xgbgen/representation.go b/nexgb/xgbgen/representation.go
index ef62157..be7accd 100644
--- a/nexgb/xgbgen/representation.go
+++ b/nexgb/xgbgen/representation.go
@@ -3,6 +3,7 @@ package main
 import (
 	"fmt"
 	"log"
+	"unicode"
 )
 
 type Protocol struct {
@@ -58,6 +59,16 @@ func (r *Request) XmlName() string {
 }
 
 func (r *Request) ReplyName() string {
+	if r.Reply == nil {
+		log.Panicf("Cannot call 'ReplyName' on request %s, which has no reply.",
+			r.SrcName())
+	}
+	name := r.SrcName()
+	lower := string(unicode.ToLower(rune(name[0]))) + name[1:]
+	return fmt.Sprintf("%sReply", lower)
+}
+
+func (r *Request) ReplyTypeName() string {
 	if r.Reply == nil {
 		log.Panicf("Cannot call 'ReplyName' on request %s, which has no reply.",
 			r.SrcName())
@@ -66,7 +77,13 @@ func (r *Request) ReplyName() string {
 }
 
 func (r *Request) ReqName() string {
-	return fmt.Sprintf("%sRequest", r.SrcName())
+	name := r.SrcName()
+	lower := string(unicode.ToLower(rune(name[0]))) + name[1:]
+	return fmt.Sprintf("%sRequest", lower)
+}
+
+func (r *Request) CookieName() string {
+	return fmt.Sprintf("%sCookie", r.SrcName())
 }
 
 // Size for Request needs a context.
@@ -99,7 +116,9 @@ func (r *Request) Size(c *Context) Size {
 			size = size.Add(field.Size())
 		}
 	}
-	return size
+	return newExpressionSize(&Padding{
+		Expr: size.Expression,
+	})
 }
 
 type Reply struct {
-- 
cgit v1.2.3-70-g09d2