aboutsummaryrefslogtreecommitdiff
path: root/nexgb/xgbgen/go.go
diff options
context:
space:
mode:
Diffstat (limited to 'nexgb/xgbgen/go.go')
-rw-r--r--nexgb/xgbgen/go.go255
1 files changed, 255 insertions, 0 deletions
diff --git a/nexgb/xgbgen/go.go b/nexgb/xgbgen/go.go
new file mode 100644
index 0000000..eb3f0fb
--- /dev/null
+++ b/nexgb/xgbgen/go.go
@@ -0,0 +1,255 @@
+package main
+/*
+ To the best of my ability, these are all of the Go specific formatting
+ functions. If I've designed xgbgen correctly, this should be only the
+ place that you change things to generate code for a new language.
+
+ This file is organized as follows:
+
+ * Imports and helper variables.
+ * Manual type and name override maps.
+ * Helper morphing functions.
+ * Morphing functions for each "unit".
+ * Morphing functions for collections of "units".
+*/
+
+import (
+ "strings"
+)
+
+/******************************************************************************/
+// Manual type and name overrides.
+/******************************************************************************/
+
+// BaseTypeMap is a map from X base types to Go types.
+// X base types should correspond to the smallest set of X types
+// that can be used to rewrite ALL X types in terms of Go types.
+// That is, if you remove any of the following types, at least one
+// XML protocol description will produce an invalid Go program.
+// The types on the left *never* show themselves in the source.
+var BaseTypeMap = map[string]string{
+ "CARD8": "byte",
+ "CARD16": "uint16",
+ "CARD32": "uint32",
+ "INT8": "int8",
+ "INT16": "int16",
+ "INT32": "int32",
+ "BYTE": "byte",
+ "BOOL": "bool",
+ "float": "float64",
+ "double": "float64",
+}
+
+// TypeMap is a map from types in the XML to type names that is used
+// in the functions that follow. Basically, every occurrence of the key
+// type is replaced with the value type.
+var TypeMap = map[string]string{
+ "VISUALTYPE": "VisualInfo",
+ "DEPTH": "DepthInfo",
+ "SCREEN": "ScreenInfo",
+ "Setup": "SetupInfo",
+}
+
+// NameMap is the same as TypeMap, but for names.
+var NameMap = map[string]string{ }
+
+/******************************************************************************/
+// Helper functions that aide in morphing repetive constructs.
+// i.e., "structure contents", expressions, type and identifier names, etc.
+/******************************************************************************/
+
+// Morph changes every TYPE (not names) into something suitable
+// for your language.
+func (typ Type) Morph(c *Context) string {
+ t := string(typ)
+
+ // If this is a base type, then write the raw Go type.
+ if newt, ok := BaseTypeMap[t]; ok {
+ return newt
+ }
+
+ // If it's in the type map, use that translation.
+ if newt, ok := TypeMap[t]; ok {
+ return newt
+ }
+
+ // If it's a resource type, just use 'Id'.
+ if c.xml.IsResource(typ) {
+ return "Id"
+ }
+
+ // If there's a namespace to this type, just use it and be done.
+ if colon := strings.Index(t, ":"); colon > -1 {
+ namespace := t[:colon]
+ rest := t[colon+1:]
+ return splitAndTitle(namespace) + splitAndTitle(rest)
+ }
+
+ // Since there is no namespace, we need to look for a namespace
+ // in the current context.
+ return c.TypePrefix(typ) + splitAndTitle(t)
+}
+
+// Morph changes every identifier (NOT type) into something suitable
+// for your language.
+func (name Name) Morph(c *Context) string {
+ n := string(name)
+
+ // If it's in the name map, use that translation.
+ if newn, ok := NameMap[n]; ok {
+ return newn
+ }
+
+ return splitAndTitle(n)
+}
+
+/******************************************************************************/
+// Per element morphing.
+// Below are functions that morph a single unit.
+/******************************************************************************/
+
+// Import morphing.
+func (imp *Import) Morph(c *Context) {
+ c.Putln("// import \"%s\"", imp.Name)
+}
+
+// Enum morphing.
+func (enum *Enum) Morph(c *Context) {
+ c.Putln("const (")
+ for _, item := range enum.Items {
+ c.Putln("%s%s = %d", enum.Name.Morph(c), item.Name.Morph(c),
+ item.Expr.Eval())
+ }
+ c.Putln(")\n")
+}
+
+// Xid morphing.
+func (xid *Xid) Morph(c *Context) {
+ // Don't emit anything for xid types for now.
+ // We're going to force them all to simply be 'Id'
+ // to avoid excessive type converting.
+ // c.Putln("type %s Id", xid.Name.Morph(c))
+}
+
+// TypeDef morphing.
+func (typedef *TypeDef) Morph(c *Context) {
+ c.Putln("type %s %s", typedef.Old.Morph(c), typedef.New.Morph(c))
+}
+
+// Struct morphing.
+func (strct *Struct) Morph(c *Context) {
+}
+
+// Union morphing.
+func (union *Union) Morph(c *Context) {
+}
+
+// Request morphing.
+func (request *Request) Morph(c *Context) {
+}
+
+// Event morphing.
+func (ev *Event) Morph(c *Context) {
+}
+
+// EventCopy morphing.
+func (evcopy *EventCopy) Morph(c *Context) {
+}
+
+// Error morphing.
+func (err *Error) Morph(c *Context) {
+}
+
+// ErrorCopy morphing.
+func (errcopy *ErrorCopy) Morph(c *Context) {
+}
+
+/******************************************************************************/
+// Collection morphing.
+// Below are functions that morph a collections of units.
+// Most of these can probably remain unchanged, but they are useful if you
+// need to group all of some "unit" in a single block or something.
+/******************************************************************************/
+func (imports Imports) Morph(c *Context) {
+ if len(imports) == 0 {
+ return
+ }
+
+ c.Putln("// Imports are not required for XGB since everything is in")
+ c.Putln("// a single package. Still these may be useful for ")
+ c.Putln("// reference purposes.")
+ for _, imp := range imports {
+ imp.Morph(c)
+ }
+}
+
+func (enums Enums) Morph(c *Context) {
+ c.Putln("// Enums\n")
+ for _, enum := range enums {
+ enum.Morph(c)
+ }
+}
+
+func (xids Xids) Morph(c *Context) {
+ c.Putln("// Xids\n")
+ for _, xid := range xids {
+ xid.Morph(c)
+ }
+}
+
+func (typedefs TypeDefs) Morph(c *Context) {
+ c.Putln("// TypeDefs\n")
+ for _, typedef := range typedefs {
+ typedef.Morph(c)
+ }
+}
+
+func (strct Structs) Morph(c *Context) {
+ c.Putln("// Structs\n")
+ for _, typedef := range strct {
+ typedef.Morph(c)
+ }
+}
+
+func (union Unions) Morph(c *Context) {
+ c.Putln("// Unions\n")
+ for _, typedef := range union {
+ typedef.Morph(c)
+ }
+}
+
+func (request Requests) Morph(c *Context) {
+ c.Putln("// Requests\n")
+ for _, typedef := range request {
+ typedef.Morph(c)
+ }
+}
+
+func (event Events) Morph(c *Context) {
+ c.Putln("// Events\n")
+ for _, typedef := range event {
+ typedef.Morph(c)
+ }
+}
+
+func (evcopy EventCopies) Morph(c *Context) {
+ c.Putln("// Event Copies\n")
+ for _, typedef := range evcopy {
+ typedef.Morph(c)
+ }
+}
+
+func (err Errors) Morph(c *Context) {
+ c.Putln("// Errors\n")
+ for _, typedef := range err {
+ typedef.Morph(c)
+ }
+}
+
+func (errcopy ErrorCopies) Morph(c *Context) {
+ c.Putln("// Error copies\n")
+ for _, typedef := range errcopy {
+ typedef.Morph(c)
+ }
+}
+