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("") + + // 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) Read(c *Context, prefix string) { +func (e *Error) Read(c *Context) { c.Putln("// Error read %s", e.SrcName()) -} - -func (e *Error) Write(c *Context, prefix string) { - c.Putln("// Error write %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"` }