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 }