aboutsummaryrefslogtreecommitdiff
path: root/nexgb/xgbgen/xml.go
diff options
context:
space:
mode:
authorAndrew Gallant (Ocelot) <Andrew.Gallant@tufts.edu>2012-04-28 23:25:57 -0400
committerAndrew Gallant (Ocelot) <Andrew.Gallant@tufts.edu>2012-04-28 23:25:57 -0400
commit52a21b415ad95b2c4649254447388cb329cee1a4 (patch)
tree0897f4033cc6251c7feb85fe9765159a3d0608eb /nexgb/xgbgen/xml.go
downloadhaven-52a21b415ad95b2c4649254447388cb329cee1a4.tar.gz
haven-52a21b415ad95b2c4649254447388cb329cee1a4.tar.xz
haven-52a21b415ad95b2c4649254447388cb329cee1a4.zip
initial commit. not currently in a working state.
Diffstat (limited to 'nexgb/xgbgen/xml.go')
-rw-r--r--nexgb/xgbgen/xml.go298
1 files changed, 298 insertions, 0 deletions
diff --git a/nexgb/xgbgen/xml.go b/nexgb/xgbgen/xml.go
new file mode 100644
index 0000000..0f632b4
--- /dev/null
+++ b/nexgb/xgbgen/xml.go
@@ -0,0 +1,298 @@
+package main
+
+import (
+ "encoding/xml"
+ "io/ioutil"
+ "log"
+ "time"
+)
+
+type XML struct {
+ // Root 'xcb' element properties.
+ XMLName xml.Name `xml:"xcb"`
+ Header string `xml:"header,attr"`
+ ExtensionXName string `xml:"extension-xname,attr"`
+ ExtensionName string `xml:"extension-name,attr"`
+ MajorVersion string `xml:"major-version,attr"`
+ MinorVersion string `xml:"minor-version,attr"`
+
+ // 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"`
+
+ // 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"`
+}
+
+// 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("")
+
+ 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.Events.Morph(c)
+ c.Putln("")
+
+ x.Errors.Morph(c)
+ c.Putln("")
+
+ x.EventCopies.Morph(c)
+ c.Putln("")
+
+ x.ErrorCopies.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
+
+type Imports []*Import
+
+func (imports Imports) Eval() {
+ for _, imp := range imports {
+ xmlBytes, err := ioutil.ReadFile(*protoPath + "/" + imp.Name + ".xml")
+ if err != nil {
+ log.Fatalf("Could not read X protocol description for import " +
+ "'%s' because: %s", imp.Name, err)
+ }
+
+ imp.xml = &XML{}
+ err = xml.Unmarshal(xmlBytes, imp.xml)
+ if err != nil {
+ log.Fatal("Could not parse X protocol description for import " +
+ "'%s' because: %s", imp.Name, err)
+ }
+ }
+}
+
+type Import struct {
+ Name string `xml:",chardata"`
+ xml *XML `xml:"-"`
+}
+
+type Enums []Enum
+
+// 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 Enum struct {
+ Name Type `xml:"name,attr"`
+ Items []*EnumItem `xml:"item"`
+}
+
+type EnumItem struct {
+ Name Name `xml:"name,attr"`
+ Expr *Expression `xml:",any"`
+}
+
+type Xids []*Xid
+
+type Xid struct {
+ XMLName xml.Name
+ Name Type `xml:"name,attr"`
+}
+
+type TypeDefs []*TypeDef
+
+type TypeDef struct {
+ Old Type `xml:"oldname,attr"`
+ New Type `xml:"newname,attr"`
+}
+
+type EventCopies []*EventCopy
+
+type EventCopy struct {
+ Name Type `xml:"name,attr"`
+ Number string `xml:"number,attr"`
+ Ref Type `xml:"ref,attr"`
+}
+
+type ErrorCopies []*ErrorCopy
+
+type ErrorCopy struct {
+ Name Type `xml:"name,attr"`
+ Number string `xml:"number,attr"`
+ Ref Type `xml:"ref,attr"`
+}
+
+type Structs []*Struct
+
+type Struct struct {
+ Name Type `xml:"name,attr"`
+ Fields []*Field `xml:",any"`
+}
+
+type Unions []*Union
+
+type Union struct {
+ Name Type `xml:"name,attr"`
+ Fields []*Field `xml:",any"`
+}
+
+type Requests []*Request
+
+type Request struct {
+ Name Type `xml:"name,attr"`
+ Opcode int `xml:"opcode,attr"`
+ Combine bool `xml:"combine-adjacent,attr"`
+ Fields []*Field `xml:",any"`
+ Reply *Reply `xml:"reply"`
+}
+
+type Reply struct {
+ Fields []*Field `xml:",any"`
+}
+
+type Events []*Event
+
+type Event struct {
+ Name Type `xml:"name,attr"`
+ Number int `xml:"number,attr"`
+ NoSequence bool `xml:"no-sequence-number,true"`
+ Fields []*Field `xml:",any"`
+}
+
+type Errors []*Error
+
+type Error struct {
+ Name Type `xml:"name,attr"`
+ Number int `xml:"number,attr"`
+ Fields []*Field `xml:",any"`
+}
+