github.com/robotn/xgb@v0.0.0-20190912153532-2cb92d044934/xgbgen/go.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  )
     6  
     7  // BaseTypeMap is a map from X base types to Go types.
     8  // X base types should correspond to the smallest set of X types
     9  // that can be used to rewrite ALL X types in terms of Go types.
    10  // That is, if you remove any of the following types, at least one
    11  // XML protocol description will produce an invalid Go program.
    12  // The types on the left *never* show themselves in the source.
    13  var BaseTypeMap = map[string]string{
    14  	"CARD8":  "byte",
    15  	"CARD16": "uint16",
    16  	"CARD32": "uint32",
    17  	"INT8":   "int8",
    18  	"INT16":  "int16",
    19  	"INT32":  "int32",
    20  	"BYTE":   "byte",
    21  	"BOOL":   "bool",
    22  	"float":  "float64",
    23  	"double": "float64",
    24  	"char":   "byte",
    25  	"void":   "byte",
    26  }
    27  
    28  // BaseTypeSizes should have precisely the same keys as in BaseTypeMap,
    29  // and the values should correspond to the size of the type in bytes.
    30  var BaseTypeSizes = map[string]uint{
    31  	"CARD8":  1,
    32  	"CARD16": 2,
    33  	"CARD32": 4,
    34  	"INT8":   1,
    35  	"INT16":  2,
    36  	"INT32":  4,
    37  	"BYTE":   1,
    38  	"BOOL":   1,
    39  	"float":  4,
    40  	"double": 8,
    41  	"char":   1,
    42  	"void":   1,
    43  
    44  	// Id is a special type used to determine the size of all Xid types.
    45  	// "Id" is not actually written in the source.
    46  	"Id": 4,
    47  }
    48  
    49  // TypeMap is a map from types in the XML to type names that is used
    50  // in the functions that follow. Basically, every occurrence of the key
    51  // type is replaced with the value type.
    52  var TypeMap = map[string]string{
    53  	"VISUALTYPE": "VisualInfo",
    54  	"DEPTH":      "DepthInfo",
    55  	"SCREEN":     "ScreenInfo",
    56  	"Setup":      "SetupInfo",
    57  }
    58  
    59  // NameMap is the same as TypeMap, but for names.
    60  var NameMap = map[string]string{}
    61  
    62  // Reading, writing and defining...
    63  
    64  // Base types
    65  func (b *Base) Define(c *Context) {
    66  	c.Putln("// Skipping definition for base type '%s'",
    67  		SrcName(c.protocol, b.XmlName()))
    68  	c.Putln("")
    69  }
    70  
    71  // Enum types
    72  func (enum *Enum) Define(c *Context) {
    73  	c.Putln("const (")
    74  	for _, item := range enum.Items {
    75  		c.Putln("%s%s = %d", enum.SrcName(), item.srcName, item.Expr.Eval())
    76  	}
    77  	c.Putln(")")
    78  	c.Putln("")
    79  }
    80  
    81  // Resource types
    82  func (res *Resource) Define(c *Context) {
    83  	c.Putln("type %s uint32", res.SrcName())
    84  	c.Putln("")
    85  	c.Putln("func New%sId(c *xgb.Conn) (%s, error) {",
    86  		res.SrcName(), res.SrcName())
    87  	c.Putln("id, err := c.NewId()")
    88  	c.Putln("if err != nil {")
    89  	c.Putln("return 0, err")
    90  	c.Putln("}")
    91  	c.Putln("return %s(id), nil", res.SrcName())
    92  	c.Putln("}")
    93  	c.Putln("")
    94  }
    95  
    96  // TypeDef types
    97  func (td *TypeDef) Define(c *Context) {
    98  	c.Putln("type %s %s", td.srcName, td.Old.SrcName())
    99  	c.Putln("")
   100  }
   101  
   102  // Field definitions, reads and writes.
   103  
   104  // Pad fields
   105  func (f *PadField) Define(c *Context) {
   106  	if f.Align > 0 {
   107  		c.Putln("// alignment gap to multiple of %d", f.Align)
   108  	} else {
   109  		c.Putln("// padding: %d bytes", f.Bytes)
   110  	}
   111  }
   112  
   113  func (f *PadField) Read(c *Context, prefix string) {
   114  	if f.Align > 0 {
   115  		c.Putln("b = (b + %d) & ^%d // alignment gap", f.Align-1, f.Align-1)
   116  	} else {
   117  		c.Putln("b += %s // padding", f.Size())
   118  	}
   119  }
   120  
   121  func (f *PadField) Write(c *Context, prefix string) {
   122  	if f.Align > 0 {
   123  		c.Putln("b = (b + %d) & ^%d // alignment gap", f.Align-1, f.Align-1)
   124  	} else {
   125  		c.Putln("b += %s // padding", f.Size())
   126  	}
   127  }
   128  
   129  // Local fields
   130  func (f *LocalField) Define(c *Context) {
   131  	c.Putln("// local field: %s %s", f.SrcName(), f.Type.SrcName())
   132  	panic("unreachable")
   133  }
   134  
   135  func (f *LocalField) Read(c *Context, prefix string) {
   136  	c.Putln("// reading local field: %s (%s) :: %s",
   137  		f.SrcName(), f.Size(), f.Type.SrcName())
   138  	panic("unreachable")
   139  }
   140  
   141  func (f *LocalField) Write(c *Context, prefix string) {
   142  	c.Putln("// skip writing local field: %s (%s) :: %s",
   143  		f.SrcName(), f.Size(), f.Type.SrcName())
   144  }
   145  
   146  // Expr fields
   147  func (f *ExprField) Define(c *Context) {
   148  	c.Putln("// expression field: %s %s (%s)",
   149  		f.SrcName(), f.Type.SrcName(), f.Expr)
   150  	panic("unreachable")
   151  }
   152  
   153  func (f *ExprField) Read(c *Context, prefix string) {
   154  	c.Putln("// reading expression field: %s (%s) (%s) :: %s",
   155  		f.SrcName(), f.Size(), f.Expr, f.Type.SrcName())
   156  	panic("unreachable")
   157  }
   158  
   159  func (f *ExprField) Write(c *Context, prefix string) {
   160  	// Special case for bools, grrr.
   161  	if f.Type.SrcName() == "bool" {
   162  		c.Putln("buf[b] = byte(%s)", f.Expr.Reduce(prefix))
   163  		c.Putln("b += 1")
   164  	} else {
   165  		WriteSimpleSingleField(c, f.Expr.Reduce(prefix), f.Type)
   166  	}
   167  }
   168  
   169  // Value field
   170  func (f *ValueField) Define(c *Context) {
   171  	c.Putln("%s %s", f.MaskName, f.SrcType())
   172  	c.Putln("%s []uint32", f.ListName)
   173  }
   174  
   175  func (f *ValueField) Read(c *Context, prefix string) {
   176  	ReadSimpleSingleField(c,
   177  		fmt.Sprintf("%s%s", prefix, f.MaskName), f.MaskType)
   178  	c.Putln("")
   179  	c.Putln("%s%s = make([]uint32, %s)",
   180  		prefix, f.ListName, f.ListLength().Reduce(prefix))
   181  	c.Putln("for i := 0; i < %s; i++ {", f.ListLength().Reduce(prefix))
   182  	c.Putln("%s%s[i] = xgb.Get32(buf[b:])", prefix, f.ListName)
   183  	c.Putln("b += 4")
   184  	c.Putln("}")
   185  	c.Putln("b = xgb.Pad(b)")
   186  }
   187  
   188  func (f *ValueField) Write(c *Context, prefix string) {
   189  	// big time mofos
   190  	if rq, ok := f.Parent.(*Request); !ok || rq.SrcName() != "ConfigureWindow" {
   191  		WriteSimpleSingleField(c,
   192  			fmt.Sprintf("%s%s", prefix, f.MaskName), f.MaskType)
   193  	}
   194  	c.Putln("for i := 0; i < %s; i++ {", f.ListLength().Reduce(prefix))
   195  	c.Putln("xgb.Put32(buf[b:], %s%s[i])", prefix, f.ListName)
   196  	c.Putln("b += 4")
   197  	c.Putln("}")
   198  	c.Putln("b = xgb.Pad(b)")
   199  }
   200  
   201  // Switch field
   202  func (f *SwitchField) Define(c *Context) {
   203  	c.Putln("// switch field: %s (%s)", f.Name, f.Expr)
   204  	panic("todo")
   205  }
   206  
   207  func (f *SwitchField) Read(c *Context, prefix string) {
   208  	c.Putln("// reading switch field: %s (%s)", f.Name, f.Expr)
   209  	panic("todo")
   210  }
   211  
   212  func (f *SwitchField) Write(c *Context, prefix string) {
   213  	c.Putln("// writing switch field: %s (%s)", f.Name, f.Expr)
   214  	panic("todo")
   215  }