aboutsummaryrefslogtreecommitdiff
path: root/nexgb/xgbgen/go_error.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/go_error.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/go_error.go')
-rw-r--r--nexgb/xgbgen/go_error.go179
1 files changed, 179 insertions, 0 deletions
diff --git a/nexgb/xgbgen/go_error.go b/nexgb/xgbgen/go_error.go
new file mode 100644
index 0000000..55fd28b
--- /dev/null
+++ b/nexgb/xgbgen/go_error.go
@@ -0,0 +1,179 @@
+package main
+
+import (
+ "fmt"
+)
+
+// Error types
+func (e *Error) Define(c *Context) {
+ c.Putln("// %s is the error number for a %s.", e.ErrConst(), e.ErrConst())
+ c.Putln("const %s = %d", e.ErrConst(), e.Number)
+ c.Putln("")
+ c.Putln("type %s struct {", e.ErrType())
+ c.Putln("Sequence uint16")
+ c.Putln("NiceName string")
+ for _, field := range e.Fields {
+ field.Define(c)
+ }
+ c.Putln("}")
+ c.Putln("")
+
+ // Read defines a function that transforms a byte slice into this
+ // error struct.
+ e.Read(c)
+
+ // Makes sure this error type implements the xgb.Error interface.
+ e.ImplementsError(c)
+
+ // Let's the XGB event loop read this error.
+ c.Putln("func init() {")
+ if c.protocol.isExt() {
+ c.Putln("xgb.NewExtErrorFuncs[\"%s\"][%d] = %sNew",
+ c.protocol.ExtXName, e.Number, e.ErrType())
+ } else {
+ c.Putln("xgb.NewErrorFuncs[%d] = %sNew", e.Number, e.ErrType())
+ }
+ c.Putln("}")
+ c.Putln("")
+}
+
+func (e *Error) Read(c *Context) {
+ c.Putln("// %sNew constructs a %s value that implements xgb.Error from "+
+ "a byte slice.", e.ErrType(), e.ErrType())
+ c.Putln("func %sNew(buf []byte) xgb.Error {", e.ErrType())
+ c.Putln("v := %s{}", e.ErrType())
+ c.Putln("v.NiceName = \"%s\"", e.SrcName())
+ c.Putln("")
+ c.Putln("b := 1 // skip error determinant")
+ c.Putln("b += 1 // don't read error number")
+ c.Putln("")
+ c.Putln("v.Sequence = xgb.Get16(buf[b:])")
+ c.Putln("b += 2")
+ c.Putln("")
+ for _, field := range e.Fields {
+ field.Read(c, "v.")
+ c.Putln("")
+ }
+ c.Putln("return v")
+ c.Putln("}")
+ c.Putln("")
+}
+
+// ImplementsError writes functions to implement the XGB Error interface.
+func (e *Error) ImplementsError(c *Context) {
+ c.Putln("// SequenceId returns the sequence id attached to the %s error.",
+ e.ErrConst())
+ c.Putln("// This is mostly used internally.")
+ c.Putln("func (err %s) SequenceId() uint16 {", e.ErrType())
+ c.Putln("return err.Sequence")
+ c.Putln("}")
+ c.Putln("")
+ c.Putln("// BadId returns the 'BadValue' number if one exists for the "+
+ "%s error. If no bad value exists, 0 is returned.", e.ErrConst())
+ c.Putln("func (err %s) BadId() uint32 {", e.ErrType())
+ if !c.protocol.isExt() {
+ c.Putln("return err.BadValue")
+ } else {
+ c.Putln("return 0")
+ }
+ c.Putln("}")
+ c.Putln("// Error returns a rudimentary string representation of the %s "+
+ "error.", e.ErrConst())
+ c.Putln("")
+ c.Putln("func (err %s) Error() string {", e.ErrType())
+ ErrorFieldString(c, e.Fields, e.ErrConst())
+ c.Putln("}")
+ c.Putln("")
+}
+
+// ErrorCopy types
+func (e *ErrorCopy) Define(c *Context) {
+ c.Putln("// %s is the error number for a %s.", e.ErrConst(), e.ErrConst())
+ c.Putln("const %s = %d", e.ErrConst(), e.Number)
+ c.Putln("")
+ c.Putln("type %s %s", e.ErrType(), e.Old.(*Error).ErrType())
+ c.Putln("")
+
+ // Read defines a function that transforms a byte slice into this
+ // error struct.
+ e.Read(c)
+
+ // Makes sure this error type implements the xgb.Error interface.
+ e.ImplementsError(c)
+
+ // Let's the XGB know how to read this error.
+ c.Putln("func init() {")
+ if c.protocol.isExt() {
+ c.Putln("xgb.NewExtErrorFuncs[\"%s\"][%d] = %sNew",
+ c.protocol.ExtXName, e.Number, e.ErrType())
+ } else {
+ c.Putln("xgb.NewErrorFuncs[%d] = %sNew", e.Number, e.ErrType())
+ }
+ c.Putln("}")
+ c.Putln("")
+}
+
+func (e *ErrorCopy) Read(c *Context) {
+ c.Putln("// %sNew constructs a %s value that implements xgb.Error from "+
+ "a byte slice.", e.ErrType(), e.ErrType())
+ c.Putln("func %sNew(buf []byte) xgb.Error {", e.ErrType())
+ c.Putln("v := %s(%sNew(buf).(%s))",
+ e.ErrType(), e.Old.(*Error).ErrType(), e.Old.(*Error).ErrType())
+ c.Putln("v.NiceName = \"%s\"", e.SrcName())
+ c.Putln("return v")
+ c.Putln("}")
+ c.Putln("")
+}
+
+// ImplementsError writes functions to implement the XGB Error interface.
+func (e *ErrorCopy) ImplementsError(c *Context) {
+ c.Putln("// SequenceId returns the sequence id attached to the %s error.",
+ e.ErrConst())
+ c.Putln("// This is mostly used internally.")
+ c.Putln("func (err %s) SequenceId() uint16 {", e.ErrType())
+ c.Putln("return err.Sequence")
+ c.Putln("}")
+ c.Putln("")
+ c.Putln("// BadId returns the 'BadValue' number if one exists for the "+
+ "%s error. If no bad value exists, 0 is returned.", e.ErrConst())
+ c.Putln("func (err %s) BadId() uint32 {", e.ErrType())
+ if !c.protocol.isExt() {
+ c.Putln("return err.BadValue")
+ } else {
+ c.Putln("return 0")
+ }
+ c.Putln("}")
+ c.Putln("")
+ c.Putln("// Error returns a rudimentary string representation of the %s "+
+ "error.", e.ErrConst())
+ c.Putln("func (err %s) Error() string {", e.ErrType())
+ ErrorFieldString(c, e.Old.(*Error).Fields, e.ErrConst())
+ c.Putln("}")
+ c.Putln("")
+}
+
+// ErrorFieldString works for both Error and ErrorCopy. It assembles all of the
+// fields in an error and formats them into a single string.
+func ErrorFieldString(c *Context, fields []Field, errName string) {
+ c.Putln("fieldVals := make([]string, 0, %d)", len(fields))
+ c.Putln("fieldVals = append(fieldVals, \"NiceName: \" + err.NiceName)")
+ c.Putln("fieldVals = append(fieldVals, "+
+ "xgb.Sprintf(\"Sequence: %s\", err.Sequence))", "%d")
+ for _, field := range fields {
+ switch field.(type) {
+ case *PadField:
+ continue
+ default:
+ if field.SrcType() == "string" {
+ c.Putln("fieldVals = append(fieldVals, \"%s: \" + err.%s)",
+ field.SrcName(), field.SrcName())
+ } else {
+ format := fmt.Sprintf("xgb.Sprintf(\"%s: %s\", err.%s)",
+ field.SrcName(), "%d", field.SrcName())
+ c.Putln("fieldVals = append(fieldVals, %s)", format)
+ }
+ }
+ }
+ c.Putln("return \"%s {\" + xgb.StringsJoin(fieldVals, \", \") + \"}\"",
+ errName)
+}