From 3115c13e88badfd3b6b1762f2239edbf9d0b8951 Mon Sep 17 00:00:00 2001 From: "Andrew Gallant (Ocelot)" Date: Sun, 29 Apr 2012 14:09:03 -0400 Subject: [PATCH] last commit before i tear everything down --- nexgb/.gitignore | 2 +- nexgb/xgbgen/COPYING | 13 +++++ nexgb/xgbgen/bufcount.go | 15 ++++++ nexgb/xgbgen/go.go | 110 ++++++++++++++++++++++++--------------- nexgb/xgbgen/xml.go | 42 +++++++++++++++ 5 files changed, 140 insertions(+), 42 deletions(-) create mode 100644 nexgb/xgbgen/COPYING create mode 100644 nexgb/xgbgen/bufcount.go diff --git a/nexgb/.gitignore b/nexgb/.gitignore index 1c0248d..179f830 100644 --- a/nexgb/.gitignore +++ b/nexgb/.gitignore @@ -1,2 +1,2 @@ -xgbgen +xgbgen/xgbgen .*.swp 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 + + 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) - 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(")") - } - c.Putln("") - - consumed = size + nextByte = field.MorphReadField(c, kind, nextByte, prefix) case "list": - c.Putln("") + typ := field.Type.Morph(c) + + // 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!") + } } - return byt + consumed + return nextByte +} + +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 + } + + 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 {