aboutsummaryrefslogtreecommitdiff
path: root/nexgb/xgbgen
diff options
context:
space:
mode:
Diffstat (limited to 'nexgb/xgbgen')
-rw-r--r--nexgb/xgbgen/COPYING13
-rw-r--r--nexgb/xgbgen/bufcount.go15
-rw-r--r--nexgb/xgbgen/go.go102
-rw-r--r--nexgb/xgbgen/xml.go42
4 files changed, 135 insertions, 37 deletions
diff --git a/nexgb/xgbgen/COPYING b/nexgb/xgbgen/COPYING
new file mode 100644
index 0000000..5c93f45
--- /dev/null
+++ b/nexgb/xgbgen/COPYING
@@ -0,0 +1,13 @@
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ Version 2, December 2004
+
+ Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
+
+ Everyone is permitted to copy and distribute verbatim or modified
+ copies of this license document, and changing it is allowed as long
+ as the name is changed.
+
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
diff --git a/nexgb/xgbgen/bufcount.go b/nexgb/xgbgen/bufcount.go
new file mode 100644
index 0000000..c3a5645
--- /dev/null
+++ b/nexgb/xgbgen/bufcount.go
@@ -0,0 +1,15 @@
+package main
+
+/*
+ A buffer count is a mechanism by which to keep track of which byte one
+ is reading or writing to/from the wire.
+
+ It's an abstraction over the fact that while such a counter is usually
+ fixed, it can be made variable based on values at run-time.
+*/
+
+type BufCount struct {
+ Fixed int
+ Exprs []*Expression
+}
+
diff --git a/nexgb/xgbgen/go.go b/nexgb/xgbgen/go.go
index bfc54dd..b939b3a 100644
--- a/nexgb/xgbgen/go.go
+++ b/nexgb/xgbgen/go.go
@@ -23,6 +23,7 @@ package main
*/
import (
+ "fmt"
"log"
"strings"
)
@@ -214,16 +215,12 @@ func (bitcase *Bitcase) MorphDefine(c *Context) {
bitcase.Fields.MorphDefine(c)
}
-func (fields Fields) MorphRead(c *Context, kind int, evNoSeq bool) {
- var nextByte uint
-
- switch kind {
- case FieldsEvent:
- nextByte = 1
- }
+func (fields Fields) MorphRead(c *Context, kind int, evNoSeq bool,
+ prefix string, byt uint) uint {
+ nextByte := byt
for _, field := range fields {
- nextByte = field.MorphRead(c, kind, nextByte)
+ nextByte = field.MorphRead(c, kind, nextByte, prefix)
switch kind {
case FieldsEvent:
// Skip the sequence id
@@ -232,45 +229,76 @@ func (fields Fields) MorphRead(c *Context, kind int, evNoSeq bool) {
}
}
}
+ return nextByte
}
-func (field *Field) MorphRead(c *Context, kind int, byt uint) uint {
- consumed := uint(0)
+func (field *Field) MorphRead(c *Context, kind int, byt uint,
+ prefix string) uint {
+
+ nextByte := byt
switch field.XMLName.Local {
case "pad":
- consumed = uint(field.Bytes)
+ nextByte += uint(field.Bytes)
case "field":
- if field.Type == "ClientMessageData" {
- break
- }
- size := field.Type.Size(c)
+ nextByte = field.MorphReadField(c, kind, nextByte, prefix)
+ case "list":
typ := field.Type.Morph(c)
- name := field.Name.Morph(c)
- _, isBase := BaseTypeMap[string(field.Type)]
- c.Put("v.%s = ", name)
- if !isBase {
- c.Put("%s(", typ)
- }
- switch size {
- case 1: c.Put("buf[%d]", byt)
- case 2: c.Put("get16(buf[%d:])", byt)
- case 4: c.Put("get32(buf[%d:])", byt)
- case 8: c.Put("get64(buf[%d:])", byt)
- default:
- log.Fatalf("Unsupported field size '%d' for field '%s'.",
- size, field)
- }
- if !isBase {
- c.Put(")")
+ // Create a temporary Field so we can use MorphReadField.
+ // temp := &Field{
+ // XMLName: xml.Name{Local: "field"},
+ // Name: field.Name,
+ // Type: field.Type,
+ // }
+
+ // Special case: if the list is just raw bytes, use copy!
+ if typ == "byte" {
+ c.Putln("copy(%s%s, buf[%d:])", prefix, field.Name.Morph(c),
+ byt)
+ nextByte = byt + 20
+ } else {
+ c.Putln("//list!")
}
- c.Putln("")
+ }
+ return nextByte
+}
- consumed = size
- case "list":
+func (field *Field) MorphReadField(c *Context, kind int, byt uint,
+ prefix string) uint {
+
+ if union := field.Type.Union(c); union != nil {
c.Putln("")
+ c.Putln("%s%s = %s{}", prefix, field.Name.Morph(c), field.Type.Morph(c))
+ union.Fields.MorphRead(c, kind, false,
+ fmt.Sprintf("%s%s.", prefix, field.Name.Morph(c)), byt)
+ c.Putln("")
+ return byt
}
- return byt + consumed
+
+ size := field.Type.Size(c)
+ typ := field.Type.Morph(c)
+ name := field.Name.Morph(c)
+ _, isBase := BaseTypeMap[string(field.Type)]
+
+ c.Put("%s%s = ", prefix, name)
+ if !isBase {
+ c.Put("%s(", typ)
+ }
+ switch size {
+ case 1: c.Put("buf[%d]", byt)
+ case 2: c.Put("get16(buf[%d:])", byt)
+ case 4: c.Put("get32(buf[%d:])", byt)
+ case 8: c.Put("get64(buf[%d:])", byt)
+ default:
+ log.Fatalf("Unsupported field size '%d' for field '%s'.",
+ size, field)
+ }
+ if !isBase {
+ c.Put(")")
+ }
+ c.Putln("")
+
+ return byt + size
}
func (fields Fields) MorphWrite(c *Context, kind int) {
@@ -377,7 +405,7 @@ func (ev *Event) Morph(c *Context) {
c.Putln("")
c.Putln("func New%s(buf []byte) %sEvent {", name, name)
c.Putln("var v %sEvent", name)
- ev.Fields.MorphRead(c, FieldsEvent, ev.NoSequence)
+ ev.Fields.MorphRead(c, FieldsEvent, ev.NoSequence, "v.", 1)
c.Putln("return v")
c.Putln("}")
c.Putln("")
diff --git a/nexgb/xgbgen/xml.go b/nexgb/xgbgen/xml.go
index 12932b2..e4202d0 100644
--- a/nexgb/xgbgen/xml.go
+++ b/nexgb/xgbgen/xml.go
@@ -166,6 +166,48 @@ type Name string
type Type string
+// Union returns the 'Union' struct corresponding to this type, if
+// one exists.
+func (typ Type) Union(c *Context) *Union {
+ // If this is a typedef, use that instead.
+ if oldTyp, ok := typ.TypeDef(c); ok {
+ return oldTyp.Union(c)
+ }
+
+ // Otherwise, just look for a union type with 'typ' name.
+ for _, union := range c.xml.Unions {
+ if typ == union.Name {
+ return union
+ }
+ }
+ for _, imp := range c.xml.Imports {
+ for _, union := range imp.xml.Unions {
+ if typ == union.Name {
+ return union
+ }
+ }
+ }
+ return nil
+}
+
+// TypeDef returns the 'old' type corresponding to this type, if it's found
+// in a type def. If not found, the second return value is false.
+func (typ Type) TypeDef(c *Context) (Type, bool) {
+ for _, typedef := range c.xml.TypeDefs {
+ if typ == typedef.New {
+ return typedef.Old, true
+ }
+ }
+ for _, imp := range c.xml.Imports {
+ for _, typedef := range imp.xml.TypeDefs {
+ if typ == typedef.New {
+ return typedef.Old, true
+ }
+ }
+ }
+ return "", false
+}
+
// Size is a nifty function that takes any type and digs until it finds
// its underlying base type. At which point, the size can be determined.
func (typ Type) Size(c *Context) uint {