aboutsummaryrefslogtreecommitdiff
path: root/nexgb/xgbgen/xml_fields.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/xml_fields.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/xml_fields.go')
-rw-r--r--nexgb/xgbgen/xml_fields.go86
1 files changed, 86 insertions, 0 deletions
diff --git a/nexgb/xgbgen/xml_fields.go b/nexgb/xgbgen/xml_fields.go
new file mode 100644
index 0000000..8b7b5c7
--- /dev/null
+++ b/nexgb/xgbgen/xml_fields.go
@@ -0,0 +1,86 @@
+package main
+
+import (
+ "encoding/xml"
+ "log"
+)
+
+type XMLField struct {
+ XMLName xml.Name
+
+ // For 'pad' element
+ Bytes uint `xml:"bytes,attr"`
+ Align uint16 `xml:"align,attr"`
+
+ // For 'field', 'list', 'localfield', 'exprfield' and 'switch' elements.
+ Name string `xml:"name,attr"`
+
+ // For 'field', 'list', 'localfield', and 'exprfield' elements.
+ Type string `xml:"type,attr"`
+
+ // For 'list', 'exprfield' and 'switch' elements.
+ Expr *XMLExpression `xml:",any"`
+
+ // For 'valueparm' element.
+ ValueMaskType string `xml:"value-mask-type,attr"`
+ ValueMaskName string `xml:"value-mask-name,attr"`
+ ValueListName string `xml:"value-list-name,attr"`
+
+ // For 'switch' element.
+ Bitcases []*XMLBitcase `xml:"bitcase"`
+
+ // I don't know which elements these are for. The documentation is vague.
+ // They also seem to be completely optional.
+ OptEnum string `xml:"enum,attr"`
+ OptMask string `xml:"mask,attr"`
+ OptAltEnum string `xml:"altenum,attr"`
+}
+
+// Bitcase represents a single expression followed by any number of fields.
+// Namely, if the switch's expression (all bitcases are inside a switch),
+// and'd with the bitcase's expression is equal to the bitcase expression,
+// then the fields should be included in its parent structure.
+// Note that since a bitcase is unique in that expressions and fields are
+// siblings, we must exhaustively search for one of them. Essentially,
+// it's the closest thing to a Union I can get to in Go without interfaces.
+// Would an '<expression>' tag have been too much to ask? :-(
+type XMLBitcase struct {
+ Fields []*XMLField `xml:",any"`
+
+ // All the different expressions.
+ // When it comes time to choose one, use the 'Expr' method.
+ ExprOp *XMLExpression `xml:"op"`
+ ExprUnOp *XMLExpression `xml:"unop"`
+ ExprField *XMLExpression `xml:"fieldref"`
+ ExprValue *XMLExpression `xml:"value"`
+ ExprBit *XMLExpression `xml:"bit"`
+ ExprEnum *XMLExpression `xml:"enumref"`
+ ExprSum *XMLExpression `xml:"sumof"`
+ ExprPop *XMLExpression `xml:"popcount"`
+}
+
+// Expr chooses the only non-nil Expr* field from Bitcase.
+// Panic if there is more than one non-nil expression.
+func (b *XMLBitcase) Expr() *XMLExpression {
+ choices := []*XMLExpression{
+ b.ExprOp, b.ExprUnOp, b.ExprField, b.ExprValue,
+ b.ExprBit, b.ExprEnum, b.ExprSum, b.ExprPop,
+ }
+
+ var choice *XMLExpression = nil
+ numNonNil := 0
+ for _, c := range choices {
+ if c != nil {
+ numNonNil++
+ choice = c
+ }
+ }
+
+ if choice == nil {
+ log.Panicf("No top level expression found in a bitcase.")
+ }
+ if numNonNil > 1 {
+ log.Panicf("More than one top-level expression was found in a bitcase.")
+ }
+ return choice
+}