aboutsummaryrefslogtreecommitdiff
path: root/nexgb/xgbgen/type.go
diff options
context:
space:
mode:
authorPřemysl Janouch <p@janouch.name>2018-09-08 16:54:17 +0200
committerPřemysl Janouch <p@janouch.name>2018-09-08 16:54:17 +0200
commit3173202cc1e08762c6e156a8fffd23269a5ddb2b (patch)
tree95c4a06f8384d41b15e9c22afac0a387de79dc51 /nexgb/xgbgen/type.go
parent632b3ae494d45755525644fe5d04475c95aae364 (diff)
parent3906399e7c2a40fbaf355de572cf50a314083f64 (diff)
downloadhaven-3173202cc1e08762c6e156a8fffd23269a5ddb2b.tar.gz
haven-3173202cc1e08762c6e156a8fffd23269a5ddb2b.tar.xz
haven-3173202cc1e08762c6e156a8fffd23269a5ddb2b.zip
Merge aarzilli/xgb, branch xcb1.12 as nexgb
History has been linearized and rewritten to stay under the new subdirectory. I want to make changes incompatible to BurntSushi/xgb. The history begs for being thrown away entirely because of its quality and because it doesn't cover the Google period but it is still useful for copyright tracking.
Diffstat (limited to 'nexgb/xgbgen/type.go')
-rw-r--r--nexgb/xgbgen/type.go390
1 files changed, 390 insertions, 0 deletions
diff --git a/nexgb/xgbgen/type.go b/nexgb/xgbgen/type.go
new file mode 100644
index 0000000..59f1a2d
--- /dev/null
+++ b/nexgb/xgbgen/type.go
@@ -0,0 +1,390 @@
+package main
+
+import (
+ "fmt"
+ "strings"
+)
+
+type Type interface {
+ Initialize(p *Protocol)
+ SrcName() string
+ XmlName() string
+ Size() Size
+
+ Define(c *Context)
+}
+
+type Types []Type
+
+func (ts Types) Len() int { return len(ts) }
+func (ts Types) Swap(i, j int) { ts[i], ts[j] = ts[j], ts[i] }
+func (ts Types) Less(i, j int) bool {
+ x1, x2 := ts[i].XmlName(), ts[j].XmlName()
+ s1, s2 := ts[i].SrcName(), ts[j].SrcName()
+ return (s1 == s2 && x1 < x2) || s1 < s2
+}
+
+// Translation is used *only* when transitioning from XML types to
+// our better representation. They are placeholders for the real types (below)
+// that will replace them.
+type Translation struct {
+ xmlName string
+}
+
+func newTranslation(name string) *Translation {
+ return &Translation{xmlName: name}
+}
+
+// RealType takes 'XmlName' and finds its real concrete type in our Protocol.
+// It is an error if we can't find such a type.
+func (t *Translation) RealType(p *Protocol) Type {
+ // Check to see if there is a namespace. If so, strip it and use it to
+ // make sure we only look for a type in that protocol.
+ namespace, typeName := "", t.XmlName()
+ if ni := strings.Index(t.XmlName(), ":"); ni > -1 {
+ namespace, typeName = strings.ToLower(typeName[:ni]), typeName[ni+1:]
+ }
+
+ if len(namespace) == 0 || namespace == strings.ToLower(p.Name) {
+ for _, typ := range p.Types {
+ if typeName == typ.XmlName() {
+ return typ
+ }
+ }
+ }
+ for _, imp := range p.Imports {
+ if len(namespace) == 0 || namespace == strings.ToLower(imp.Name) {
+ for _, typ := range imp.Types {
+ if typeName == typ.XmlName() {
+ return typ
+ }
+ }
+ }
+ }
+ panic("Could not find real type for translation type: " + t.XmlName())
+}
+
+func (t *Translation) SrcName() string {
+ panic("it is illegal to call SrcName on a translation type")
+}
+
+func (t *Translation) XmlName() string {
+ return t.xmlName
+}
+
+func (t *Translation) Size() Size {
+ panic("it is illegal to call Size on a translation type")
+}
+
+func (t *Translation) Define(c *Context) {
+ panic("it is illegal to call Define on a translation type")
+}
+
+func (t *Translation) Initialize(p *Protocol) {
+ panic("it is illegal to call Initialize on a translation type")
+}
+
+type Base struct {
+ srcName string
+ xmlName string
+ size Size
+}
+
+func (b *Base) SrcName() string {
+ return b.srcName
+}
+
+func (b *Base) XmlName() string {
+ return b.xmlName
+}
+
+func (b *Base) Size() Size {
+ return b.size
+}
+
+func (b *Base) Initialize(p *Protocol) {
+ b.srcName = TypeSrcName(p, b)
+}
+
+type Enum struct {
+ srcName string
+ xmlName string
+ Items []*EnumItem
+}
+
+type EnumItem struct {
+ srcName string
+ xmlName string
+ Expr Expression
+}
+
+func (enum *Enum) SrcName() string {
+ return enum.srcName
+}
+
+func (enum *Enum) XmlName() string {
+ return enum.xmlName
+}
+
+func (enum *Enum) Size() Size {
+ panic("Cannot take size of enum")
+}
+
+func (enum *Enum) Initialize(p *Protocol) {
+ enum.srcName = TypeSrcName(p, enum)
+ for _, item := range enum.Items {
+ item.srcName = SrcName(p, item.xmlName)
+ if item.Expr != nil {
+ item.Expr.Initialize(p)
+ }
+ }
+}
+
+type Resource struct {
+ srcName string
+ xmlName string
+}
+
+func (r *Resource) SrcName() string {
+ return r.srcName
+}
+
+func (r *Resource) XmlName() string {
+ return r.xmlName
+}
+
+func (r *Resource) Size() Size {
+ return newFixedSize(BaseTypeSizes["Id"], true)
+}
+
+func (r *Resource) Initialize(p *Protocol) {
+ r.srcName = TypeSrcName(p, r)
+}
+
+type TypeDef struct {
+ srcName string
+ xmlName string
+ Old Type
+}
+
+func (t *TypeDef) SrcName() string {
+ return t.srcName
+}
+
+func (t *TypeDef) XmlName() string {
+ return t.xmlName
+}
+
+func (t *TypeDef) Size() Size {
+ return t.Old.Size()
+}
+
+func (t *TypeDef) Initialize(p *Protocol) {
+ t.Old = t.Old.(*Translation).RealType(p)
+ t.srcName = TypeSrcName(p, t)
+}
+
+type Event struct {
+ srcName string
+ xmlName string
+ Number int
+ NoSequence bool
+ Fields []Field
+}
+
+func (e *Event) SrcName() string {
+ return e.srcName
+}
+
+func (e *Event) XmlName() string {
+ return e.xmlName
+}
+
+func (e *Event) Size() Size {
+ return newExpressionSize(&Value{v: 32}, true)
+}
+
+func (e *Event) Initialize(p *Protocol) {
+ e.srcName = TypeSrcName(p, e)
+ for _, field := range e.Fields {
+ field.Initialize(p)
+ }
+}
+
+func (e *Event) EvType() string {
+ return fmt.Sprintf("%sEvent", e.srcName)
+}
+
+type EventCopy struct {
+ srcName string
+ xmlName string
+ Old Type
+ Number int
+}
+
+func (e *EventCopy) SrcName() string {
+ return e.srcName
+}
+
+func (e *EventCopy) XmlName() string {
+ return e.xmlName
+}
+
+func (e *EventCopy) Size() Size {
+ return newExpressionSize(&Value{v: 32}, true)
+}
+
+func (e *EventCopy) Initialize(p *Protocol) {
+ e.srcName = TypeSrcName(p, e)
+ e.Old = e.Old.(*Translation).RealType(p)
+ if _, ok := e.Old.(*Event); !ok {
+ panic("an EventCopy's old type *must* be *Event")
+ }
+}
+
+func (e *EventCopy) EvType() string {
+ return fmt.Sprintf("%sEvent", e.srcName)
+}
+
+type Error struct {
+ srcName string
+ xmlName string
+ Number int
+ Fields []Field
+}
+
+func (e *Error) SrcName() string {
+ return e.srcName
+}
+
+func (e *Error) XmlName() string {
+ return e.xmlName
+}
+
+func (e *Error) Size() Size {
+ return newExpressionSize(&Value{v: 32}, true)
+}
+
+func (e *Error) Initialize(p *Protocol) {
+ e.srcName = TypeSrcName(p, e)
+ for _, field := range e.Fields {
+ field.Initialize(p)
+ }
+}
+
+func (e *Error) ErrConst() string {
+ return fmt.Sprintf("Bad%s", e.srcName)
+}
+
+func (e *Error) ErrType() string {
+ return fmt.Sprintf("%sError", e.srcName)
+}
+
+type ErrorCopy struct {
+ srcName string
+ xmlName string
+ Old Type
+ Number int
+}
+
+func (e *ErrorCopy) SrcName() string {
+ return e.srcName
+}
+
+func (e *ErrorCopy) XmlName() string {
+ return e.xmlName
+}
+
+func (e *ErrorCopy) Size() Size {
+ return newExpressionSize(&Value{v: 32}, true)
+}
+
+func (e *ErrorCopy) Initialize(p *Protocol) {
+ e.srcName = TypeSrcName(p, e)
+ e.Old = e.Old.(*Translation).RealType(p)
+ if _, ok := e.Old.(*Error); !ok {
+ panic("an ErrorCopy's old type *must* be *Event")
+ }
+}
+
+func (e *ErrorCopy) ErrConst() string {
+ return fmt.Sprintf("Bad%s", e.srcName)
+}
+
+func (e *ErrorCopy) ErrType() string {
+ return fmt.Sprintf("%sError", e.srcName)
+}
+
+type Struct struct {
+ srcName string
+ xmlName string
+ Fields []Field
+}
+
+func (s *Struct) SrcName() string {
+ return s.srcName
+}
+
+func (s *Struct) XmlName() string {
+ return s.xmlName
+}
+
+func (s *Struct) Size() Size {
+ size := newFixedSize(0, true)
+ for _, field := range s.Fields {
+ size = size.Add(field.Size())
+ }
+ return size
+}
+
+func (s *Struct) Initialize(p *Protocol) {
+ s.srcName = TypeSrcName(p, s)
+ for _, field := range s.Fields {
+ field.Initialize(p)
+ }
+}
+
+// HasList returns whether there is a field in this struct that is a list.
+// When true, a more involved calculation is necessary to compute this struct's
+// size.
+func (s *Struct) HasList() bool {
+ for _, field := range s.Fields {
+ if _, ok := field.(*ListField); ok {
+ return true
+ }
+ }
+ return false
+}
+
+type Union struct {
+ srcName string
+ xmlName string
+ Fields []Field
+}
+
+func (u *Union) SrcName() string {
+ return u.srcName
+}
+
+func (u *Union) XmlName() string {
+ return u.xmlName
+}
+
+// Size for Union is broken. At least, it's broken for XKB.
+// It *looks* like the protocol inherently relies on some amount of
+// memory unsafety, since some members of unions in XKB are *variable* in
+// length! The only thing I can come up with, maybe, is when a union has
+// variable size, simply return the raw bytes. Then it's up to the user to
+// pass those raw bytes into the appropriate New* constructor. GROSS!
+// As of now, just pluck out the first field and return that size. This
+// should work for union elements in randr.xml and xproto.xml.
+func (u *Union) Size() Size {
+ return u.Fields[0].Size()
+}
+
+func (u *Union) Initialize(p *Protocol) {
+ u.srcName = fmt.Sprintf("%sUnion", TypeSrcName(p, u))
+ for _, field := range u.Fields {
+ field.Initialize(p)
+ }
+}