complete and total overhaul like i promised. things are much easier to reason about. still not working yet though.
This commit is contained in:
@@ -4,7 +4,6 @@ import (
|
||||
"encoding/xml"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
type XML struct {
|
||||
@@ -18,231 +17,25 @@ type XML struct {
|
||||
|
||||
// Types for all top-level elements.
|
||||
// First are the simple ones.
|
||||
Imports Imports `xml:"import"`
|
||||
Enums Enums `xml:"enum"`
|
||||
Xids Xids `xml:"xidtype"`
|
||||
XidUnions Xids `xml:"xidunion"`
|
||||
TypeDefs TypeDefs `xml:"typedef"`
|
||||
EventCopies EventCopies `xml:"eventcopy"`
|
||||
ErrorCopies ErrorCopies `xml:"errorcopy"`
|
||||
Imports XMLImports `xml:"import"`
|
||||
Enums XMLEnums `xml:"enum"`
|
||||
Xids XMLXids `xml:"xidtype"`
|
||||
XidUnions XMLXids `xml:"xidunion"`
|
||||
TypeDefs XMLTypeDefs `xml:"typedef"`
|
||||
EventCopies XMLEventCopies `xml:"eventcopy"`
|
||||
ErrorCopies XMLErrorCopies `xml:"errorcopy"`
|
||||
|
||||
// Here are the complex ones, i.e., anything with "structure contents"
|
||||
Structs Structs `xml:"struct"`
|
||||
Unions Unions `xml:"union"`
|
||||
Requests Requests `xml:"request"`
|
||||
Events Events `xml:"event"`
|
||||
Errors Errors `xml:"error"`
|
||||
Structs XMLStructs `xml:"struct"`
|
||||
Unions XMLUnions `xml:"union"`
|
||||
Requests XMLRequests `xml:"request"`
|
||||
Events XMLEvents `xml:"event"`
|
||||
Errors XMLErrors `xml:"error"`
|
||||
}
|
||||
|
||||
// Morph cascades down all of the XML and calls each type's corresponding
|
||||
// Morph function with itself as an argument (the context).
|
||||
func (x *XML) Morph(c *Context) {
|
||||
// Start the header...
|
||||
c.Putln("package xgb")
|
||||
c.Putln("/*")
|
||||
c.Putln("\tX protocol API for '%s.xml'.", c.xml.Header)
|
||||
c.Putln("\tThis file is automatically generated. Edit at your own peril!")
|
||||
c.Putln("\tGenerated on %s",
|
||||
time.Now().Format("Jan 2, 2006 at 3:04:05pm MST"))
|
||||
c.Putln("*/")
|
||||
c.Putln("")
|
||||
type XMLImports []*XMLImport
|
||||
|
||||
x.Imports.Morph(c)
|
||||
c.Putln("")
|
||||
|
||||
x.Enums.Morph(c)
|
||||
c.Putln("")
|
||||
|
||||
x.Xids.Morph(c)
|
||||
c.Putln("")
|
||||
|
||||
x.XidUnions.Morph(c)
|
||||
c.Putln("")
|
||||
|
||||
x.TypeDefs.Morph(c)
|
||||
c.Putln("")
|
||||
|
||||
x.Structs.Morph(c)
|
||||
c.Putln("")
|
||||
|
||||
x.Unions.Morph(c)
|
||||
c.Putln("")
|
||||
|
||||
x.Requests.Morph(c)
|
||||
c.Putln("")
|
||||
|
||||
x.Errors.Morph(c)
|
||||
c.Putln("")
|
||||
|
||||
x.ErrorCopies.Morph(c)
|
||||
c.Putln("")
|
||||
|
||||
x.Events.Morph(c)
|
||||
c.Putln("")
|
||||
|
||||
x.EventCopies.Morph(c)
|
||||
c.Putln("")
|
||||
}
|
||||
|
||||
// IsResource returns true if the 'needle' type is a resource type.
|
||||
// i.e., an "xid"
|
||||
func (x *XML) IsResource(needle Type) bool {
|
||||
for _, xid := range x.Xids {
|
||||
if needle == xid.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, xidunion := range x.XidUnions {
|
||||
if needle == xidunion.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, imp := range x.Imports {
|
||||
if imp.xml.IsResource(needle) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// HasType returns true if the 'needle' type can be found in the protocol
|
||||
// description represented by 'x'.
|
||||
func (x *XML) HasType(needle Type) bool {
|
||||
for _, enum := range x.Enums {
|
||||
if needle == enum.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, xid := range x.Xids {
|
||||
if needle == xid.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, xidunion := range x.XidUnions {
|
||||
if needle == xidunion.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, typedef := range x.TypeDefs {
|
||||
if needle == typedef.New {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, evcopy := range x.EventCopies {
|
||||
if needle == evcopy.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, errcopy := range x.ErrorCopies {
|
||||
if needle == errcopy.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, strct := range x.Structs {
|
||||
if needle == strct.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, union := range x.Unions {
|
||||
if needle == union.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, ev := range x.Events {
|
||||
if needle == ev.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
for _, err := range x.Errors {
|
||||
if needle == err.Name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
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 {
|
||||
// If this is a base type, we're done.
|
||||
if size, ok := BaseTypeSizes[string(typ)]; ok {
|
||||
return size
|
||||
}
|
||||
|
||||
// If it's a resource, we're also done.
|
||||
if c.xml.IsResource(typ) {
|
||||
return BaseTypeSizes["Id"]
|
||||
}
|
||||
|
||||
// It's not, so that implies there is *some* typedef declaring it
|
||||
// in terms of another type. Just follow that chain until we get to
|
||||
// a base type. We also need to check imported stuff.
|
||||
for _, typedef := range c.xml.TypeDefs {
|
||||
if typ == typedef.New {
|
||||
return typedef.Old.Size(c)
|
||||
}
|
||||
}
|
||||
for _, imp := range c.xml.Imports {
|
||||
for _, typedef := range imp.xml.TypeDefs {
|
||||
if typ == typedef.New {
|
||||
return typedef.Old.Size(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Panicf("Could not find base size of type '%s'.", typ)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
type Imports []*Import
|
||||
|
||||
func (imports Imports) Eval() {
|
||||
func (imports XMLImports) Eval() {
|
||||
for _, imp := range imports {
|
||||
xmlBytes, err := ioutil.ReadFile(*protoPath + "/" + imp.Name + ".xml")
|
||||
if err != nil {
|
||||
@@ -256,117 +49,101 @@ func (imports Imports) Eval() {
|
||||
log.Fatal("Could not parse X protocol description for import " +
|
||||
"'%s' because: %s", imp.Name, err)
|
||||
}
|
||||
|
||||
// recursive imports...
|
||||
imp.xml.Imports.Eval()
|
||||
}
|
||||
}
|
||||
|
||||
type Import struct {
|
||||
type XMLImport struct {
|
||||
Name string `xml:",chardata"`
|
||||
xml *XML `xml:"-"`
|
||||
}
|
||||
|
||||
type Enums []Enum
|
||||
type XMLEnums []XMLEnum
|
||||
|
||||
// Eval on the list of all enum types goes through and forces every enum
|
||||
// item to have a valid expression.
|
||||
// This is necessary because when an item is empty, it is defined to have
|
||||
// the value of "one more than that of the previous item, or 0 for the first
|
||||
// item".
|
||||
func (enums Enums) Eval() {
|
||||
for _, enum := range enums {
|
||||
nextValue := uint(0)
|
||||
for _, item := range enum.Items {
|
||||
if item.Expr == nil {
|
||||
item.Expr = newValueExpression(nextValue)
|
||||
nextValue++
|
||||
} else {
|
||||
nextValue = item.Expr.Eval() + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
type XMLEnum struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Items []*XMLEnumItem `xml:"item"`
|
||||
}
|
||||
|
||||
type Enum struct {
|
||||
Name Type `xml:"name,attr"`
|
||||
Items []*EnumItem `xml:"item"`
|
||||
type XMLEnumItem struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Expr *XMLExpression `xml:",any"`
|
||||
}
|
||||
|
||||
type EnumItem struct {
|
||||
Name Name `xml:"name,attr"`
|
||||
Expr *Expression `xml:",any"`
|
||||
}
|
||||
type XMLXids []*XMLXid
|
||||
|
||||
type Xids []*Xid
|
||||
|
||||
type Xid struct {
|
||||
type XMLXid struct {
|
||||
XMLName xml.Name
|
||||
Name Type `xml:"name,attr"`
|
||||
Name string `xml:"name,attr"`
|
||||
}
|
||||
|
||||
type TypeDefs []*TypeDef
|
||||
type XMLTypeDefs []*XMLTypeDef
|
||||
|
||||
type TypeDef struct {
|
||||
Old Type `xml:"oldname,attr"`
|
||||
New Type `xml:"newname,attr"`
|
||||
type XMLTypeDef struct {
|
||||
Old string `xml:"oldname,attr"`
|
||||
New string `xml:"newname,attr"`
|
||||
}
|
||||
|
||||
type EventCopies []*EventCopy
|
||||
type XMLEventCopies []*XMLEventCopy
|
||||
|
||||
type EventCopy struct {
|
||||
Name Type `xml:"name,attr"`
|
||||
type XMLEventCopy struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Number int `xml:"number,attr"`
|
||||
Ref Type `xml:"ref,attr"`
|
||||
Ref string `xml:"ref,attr"`
|
||||
}
|
||||
|
||||
type ErrorCopies []*ErrorCopy
|
||||
type XMLErrorCopies []*XMLErrorCopy
|
||||
|
||||
type ErrorCopy struct {
|
||||
Name Type `xml:"name,attr"`
|
||||
type XMLErrorCopy struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Number int `xml:"number,attr"`
|
||||
Ref Type `xml:"ref,attr"`
|
||||
Ref string `xml:"ref,attr"`
|
||||
}
|
||||
|
||||
type Structs []*Struct
|
||||
type XMLStructs []*XMLStruct
|
||||
|
||||
type Struct struct {
|
||||
Name Type `xml:"name,attr"`
|
||||
Fields Fields `xml:",any"`
|
||||
type XMLStruct struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Fields XMLFields `xml:",any"`
|
||||
}
|
||||
|
||||
type Unions []*Union
|
||||
type XMLUnions []*XMLUnion
|
||||
|
||||
type Union struct {
|
||||
Name Type `xml:"name,attr"`
|
||||
Fields Fields `xml:",any"`
|
||||
type XMLUnion struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Fields XMLFields `xml:",any"`
|
||||
}
|
||||
|
||||
type Requests []*Request
|
||||
type XMLRequests []*XMLRequest
|
||||
|
||||
type Request struct {
|
||||
Name Type `xml:"name,attr"`
|
||||
type XMLRequest struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Opcode int `xml:"opcode,attr"`
|
||||
Combine bool `xml:"combine-adjacent,attr"`
|
||||
Fields Fields `xml:",any"`
|
||||
Reply *Reply `xml:"reply"`
|
||||
Fields XMLFields `xml:",any"`
|
||||
Reply *XMLReply `xml:"reply"`
|
||||
}
|
||||
|
||||
type Reply struct {
|
||||
Fields Fields `xml:",any"`
|
||||
type XMLReply struct {
|
||||
Fields XMLFields `xml:",any"`
|
||||
}
|
||||
|
||||
type Events []*Event
|
||||
type XMLEvents []*XMLEvent
|
||||
|
||||
type Event struct {
|
||||
Name Type `xml:"name,attr"`
|
||||
type XMLEvent struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Number int `xml:"number,attr"`
|
||||
NoSequence bool `xml:"no-sequence-number,true"`
|
||||
Fields Fields `xml:",any"`
|
||||
Fields XMLFields `xml:",any"`
|
||||
}
|
||||
|
||||
type Errors []*Error
|
||||
type XMLErrors []*XMLError
|
||||
|
||||
type Error struct {
|
||||
Name Type `xml:"name,attr"`
|
||||
type XMLError struct {
|
||||
Name string `xml:"name,attr"`
|
||||
Number int `xml:"number,attr"`
|
||||
Fields Fields `xml:",any"`
|
||||
Fields XMLFields `xml:",any"`
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user