diff options
Diffstat (limited to 'nexgb')
| -rw-r--r-- | nexgb/.gitignore | 2 | ||||
| -rw-r--r-- | nexgb/xgbgen/COPYING | 13 | ||||
| -rw-r--r-- | nexgb/xgbgen/bufcount.go | 15 | ||||
| -rw-r--r-- | nexgb/xgbgen/go.go | 102 | ||||
| -rw-r--r-- | nexgb/xgbgen/xml.go | 42 | 
5 files changed, 136 insertions, 38 deletions
| 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 <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 { | 
