finally starting on the crescendo: requests and replies.

This commit is contained in:
Andrew Gallant (Ocelot) 2012-05-02 01:46:30 -04:00
parent f48b6fafc6
commit 39507f86ab
11 changed files with 153 additions and 48 deletions

View File

@ -51,4 +51,7 @@ func (c *Context) Morph(xmlBytes []byte) {
for _, typ := range c.protocol.Types { for _, typ := range c.protocol.Types {
typ.Define(c) typ.Define(c)
} }
for _, req := range c.protocol.Requests {
req.Define(c)
}
} }

View File

@ -102,8 +102,10 @@ func (f *ListField) Size() Size {
return newExpressionSize(simpleLen) return newExpressionSize(simpleLen)
case *Resource: case *Resource:
return newExpressionSize(simpleLen) return newExpressionSize(simpleLen)
case *TypeDef:
return newExpressionSize(simpleLen)
default: 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") panic("unreachable")
} }

View File

@ -105,57 +105,48 @@ func (f *PadField) Write(c *Context) {
// Local fields // Local fields
func (f *LocalField) Define(c *Context) { func (f *LocalField) Define(c *Context) {
c.Putln("// local field: %s %s", f.SrcName(), f.Type.SrcName()) c.Putln("// local field: %s %s", f.SrcName(), f.Type.SrcName())
panic("todo")
} }
func (f *LocalField) Read(c *Context) { func (f *LocalField) Read(c *Context) {
c.Putln("// reading local field: %s (%s) :: %s", c.Putln("// reading local field: %s (%s) :: %s",
f.SrcName(), f.Size(), f.Type.SrcName()) f.SrcName(), f.Size(), f.Type.SrcName())
panic("todo")
} }
func (f *LocalField) Write(c *Context) { func (f *LocalField) Write(c *Context) {
c.Putln("// writing local field: %s (%s) :: %s", c.Putln("// writing local field: %s (%s) :: %s",
f.SrcName(), f.Size(), f.Type.SrcName()) f.SrcName(), f.Size(), f.Type.SrcName())
panic("todo")
} }
// Expr fields // Expr fields
func (f *ExprField) Define(c *Context) { func (f *ExprField) Define(c *Context) {
c.Putln("// expression field: %s %s (%s)", c.Putln("// expression field: %s %s (%s)",
f.SrcName(), f.Type.SrcName(), f.Expr) f.SrcName(), f.Type.SrcName(), f.Expr)
panic("todo")
} }
func (f *ExprField) Read(c *Context) { func (f *ExprField) Read(c *Context) {
c.Putln("// reading expression field: %s (%s) (%s) :: %s", c.Putln("// reading expression field: %s (%s) (%s) :: %s",
f.SrcName(), f.Size(), f.Expr, f.Type.SrcName()) f.SrcName(), f.Size(), f.Expr, f.Type.SrcName())
panic("todo")
} }
func (f *ExprField) Write(c *Context) { func (f *ExprField) Write(c *Context) {
c.Putln("// writing expression field: %s (%s) (%s) :: %s", c.Putln("// writing expression field: %s (%s) (%s) :: %s",
f.SrcName(), f.Size(), f.Expr, f.Type.SrcName()) f.SrcName(), f.Size(), f.Expr, f.Type.SrcName())
panic("todo")
} }
// Value field // Value field
func (f *ValueField) Define(c *Context) { func (f *ValueField) Define(c *Context) {
c.Putln("// valueparam field: type: %s, mask name: %s, list name: %s", c.Putln("// valueparam field: type: %s, mask name: %s, list name: %s",
f.MaskType.SrcName(), f.MaskName, f.ListName) f.MaskType.SrcName(), f.MaskName, f.ListName)
panic("todo")
} }
func (f *ValueField) Read(c *Context) { func (f *ValueField) Read(c *Context) {
c.Putln("// reading valueparam: type: %s, mask name: %s, list name: %s", c.Putln("// reading valueparam: type: %s, mask name: %s, list name: %s",
f.MaskType.SrcName(), f.MaskName, f.ListName) f.MaskType.SrcName(), f.MaskName, f.ListName)
panic("todo")
} }
func (f *ValueField) Write(c *Context) { func (f *ValueField) Write(c *Context) {
c.Putln("// writing valueparam: type: %s, mask name: %s, list name: %s", c.Putln("// writing valueparam: type: %s, mask name: %s, list name: %s",
f.MaskType.SrcName(), f.MaskName, f.ListName) f.MaskType.SrcName(), f.MaskName, f.ListName)
panic("todo")
} }
// Switch field // Switch field

View File

@ -3,15 +3,53 @@ package main
// Error types // Error types
func (e *Error) Define(c *Context) { func (e *Error) Define(c *Context) {
c.Putln("// Error definition %s (%d)", e.SrcName(), e.Number) 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("")
// 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("") c.Putln("")
} }
func (e *Error) Read(c *Context, prefix string) { func (e *Error) Read(c *Context) {
c.Putln("// Error read %s", e.SrcName()) 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")
func (e *Error) Write(c *Context, prefix string) { c.Putln("}")
c.Putln("// Error write %s", e.SrcName()) c.Putln("")
} }
// ErrorCopy types // ErrorCopy types
@ -27,31 +65,20 @@ func (e *ErrorCopy) Define(c *Context) {
// error struct. // error struct.
e.Read(c) 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. // Makes sure that this error type is an Error interface.
c.Putln("func (err %s) ImplementsError() { }", e.ErrType()) c.Putln("func (err %s) ImplementsError() { }", e.ErrType())
c.Putln("") c.Putln("")
// Let's the XGB know how to read this error. // Let's the XGB know how to read this error.
c.Putln("func init() {") 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("}")
c.Putln("") c.Putln("")
} }
func (e *ErrorCopy) Read(c *Context) { func (e *ErrorCopy) Read(c *Context) {
c.Putln("func New%s(buf []byte) %s {", e.SrcName(), e.ErrType()) c.Putln("func New%s(buf []byte) %s {", e.ErrType(), e.ErrType())
c.Putln("return (%s)(New%s(buf))", e.ErrType(), e.Old.SrcName()) c.Putln("return %s(New%s(buf))", e.ErrType(), e.Old.(*Error).ErrType())
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("}") c.Putln("}")
c.Putln("") c.Putln("")
} }

View File

@ -4,8 +4,13 @@ package main
func (e *Event) Define(c *Context) { func (e *Event) Define(c *Context) {
c.Putln("// Event definition %s (%d)", e.SrcName(), e.Number) c.Putln("// Event definition %s (%d)", e.SrcName(), e.Number)
c.Putln("// Size: %s", e.Size()) 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("type %s struct {", e.EvType())
if !e.NoSequence {
c.Putln("Sequence uint16") c.Putln("Sequence uint16")
}
for _, field := range e.Fields { for _, field := range e.Fields {
field.Define(c) field.Define(c)
} }
@ -16,7 +21,7 @@ func (e *Event) Define(c *Context) {
// event struct. // event struct.
e.Read(c) 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. // a byte slice.
e.Write(c) e.Write(c)
@ -26,14 +31,14 @@ func (e *Event) Define(c *Context) {
// Let's the XGB event loop read this event. // Let's the XGB event loop read this event.
c.Putln("func init() {") 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("}")
c.Putln("") c.Putln("")
} }
func (e *Event) Read(c *Context) { func (e *Event) Read(c *Context) {
c.Putln("// Event read %s", e.SrcName()) 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("v := %s{}", e.EvType())
c.Putln("b := 1 // don't read event number") c.Putln("b := 1 // don't read event number")
c.Putln("") c.Putln("")
@ -97,21 +102,21 @@ func (e *EventCopy) Define(c *Context) {
// Let's the XGB event loop read this event. // Let's the XGB event loop read this event.
c.Putln("func init() {") 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("}")
c.Putln("") c.Putln("")
} }
func (e *EventCopy) Read(c *Context) { func (e *EventCopy) Read(c *Context) {
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("return (%s)(New%s(buf))", e.EvType(), e.Old.SrcName()) c.Putln("return %s(New%s(buf))", e.EvType(), e.Old.(*Event).EvType())
c.Putln("}") c.Putln("}")
c.Putln("") c.Putln("")
} }
func (e *EventCopy) Write(c *Context) { func (e *EventCopy) Write(c *Context) {
c.Putln("func (v %s) Bytes() []byte {", e.EvType()) 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("}")
c.Putln("") c.Putln("")
} }

View File

@ -41,7 +41,7 @@ func (f *ListField) Read(c *Context) {
f.SrcName(), t.SrcName(), f.LengthExpr.Reduce("v.", "")) f.SrcName(), t.SrcName(), f.LengthExpr.Reduce("v.", ""))
c.Putln("b += Read%sList(buf[b:], v.%s)", t.SrcName(), f.SrcName()) c.Putln("b += Read%sList(buf[b:], v.%s)", t.SrcName(), f.SrcName())
default: 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) f.XmlName(), f.Type)
} }
} }
@ -70,7 +70,7 @@ func (f *ListField) Write(c *Context) {
case *Struct: case *Struct:
c.Putln("b += %sListBytes(buf[b:], v.%s)", t.SrcName(), f.SrcName()) c.Putln("b += %sListBytes(buf[b:], v.%s)", t.SrcName(), f.SrcName())
default: 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) f.XmlName(), f.Type)
} }
} }

19
nexgb/xgbgen/go_reply.go Normal file
View File

@ -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("")
}
}

View File

@ -1,5 +1,10 @@
package main package main
import (
"fmt"
"log"
)
type Protocol struct { type Protocol struct {
Name string Name string
ExtXName 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 { type Reply struct {
Fields []Field 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) { func (r *Reply) Initialize(p *Protocol) {
for _, field := range r.Fields { for _, field := range r.Fields {
field.Initialize(p) field.Initialize(p)

View File

@ -210,11 +210,13 @@ func (x *XMLRequest) Translate() *Request {
// computation of the 'odd_length' field. However, 'string_len' is not // computation of the 'odd_length' field. However, 'string_len' is not
// defined. Therefore, let's forcefully add it as a 'local field'. // 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.) // (i.e., a parameter in the caller but does not get send over the wire.)
if x.Name == "QueryTextExtents" {
stringLenLocal := &LocalField{&SingleField{ stringLenLocal := &LocalField{&SingleField{
xmlName: "string_len", xmlName: "string_len",
Type: newTranslation("CARD16"), Type: newTranslation("CARD16"),
}} }}
r.Fields = append(r.Fields, stringLenLocal) r.Fields = append(r.Fields, stringLenLocal)
}
return r return r
} }

View File

@ -221,7 +221,7 @@ func (e *EventCopy) XmlName() string {
} }
func (e *EventCopy) Size() Size { func (e *EventCopy) Size() Size {
panic("Cannot take size of EventCopy type.") return newExpressionSize(&Value{v: 32})
} }
func (e *EventCopy) Initialize(p *Protocol) { func (e *EventCopy) Initialize(p *Protocol) {
@ -252,11 +252,14 @@ func (e *Error) XmlName() string {
} }
func (e *Error) Size() Size { func (e *Error) Size() Size {
panic("Cannot take size of Error type.") return newExpressionSize(&Value{v: 32})
} }
func (e *Error) Initialize(p *Protocol) { func (e *Error) Initialize(p *Protocol) {
e.srcName = TypeSrcName(p, e) e.srcName = TypeSrcName(p, e)
for _, field := range e.Fields {
field.Initialize(p)
}
} }
func (e *Error) ErrConst() string { func (e *Error) ErrConst() string {
@ -283,7 +286,7 @@ func (e *ErrorCopy) XmlName() string {
} }
func (e *ErrorCopy) Size() Size { func (e *ErrorCopy) Size() Size {
panic("Cannot take size of ErrorCopy type.") return newExpressionSize(&Value{v: 32})
} }
func (e *ErrorCopy) Initialize(p *Protocol) { func (e *ErrorCopy) Initialize(p *Protocol) {

View File

@ -135,7 +135,7 @@ type XMLEvents []*XMLEvent
type XMLEvent struct { type XMLEvent struct {
Name string `xml:"name,attr"` Name string `xml:"name,attr"`
Number int `xml:"number,attr"` Number int `xml:"number,attr"`
NoSequence bool `xml:"no-sequence-number,true"` NoSequence bool `xml:"no-sequence-number,attr"`
Fields XMLFields `xml:",any"` Fields XMLFields `xml:",any"`
} }