initial commit. not currently in a working state.
This commit is contained in:
298
nexgb/xgbgen/xml.go
Normal file
298
nexgb/xgbgen/xml.go
Normal file
@@ -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"`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user