github.com/BurntSushi/xgb@v0.0.0-20210121224620-deaf085860bc/xgbgen/field.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 ) 8 9 // Field corresponds to any field described in an XML protocol description 10 // file. This includes struct fields, union fields, request fields, 11 // reply fields and so on. 12 // To make code generation easier, fields that have types are also stored. 13 // Note that not all fields support all methods defined in this interface. 14 // For instance, a padding field does not have a source name. 15 type Field interface { 16 // Initialize sets up the source name of this field. 17 Initialize(p *Protocol) 18 19 // SrcName is the Go source name of this field. 20 SrcName() string 21 22 // XmlName is the name of this field from the XML file. 23 XmlName() string 24 25 // SrcType is the Go source type name of this field. 26 SrcType() string 27 28 // Size returns an expression that computes the size (in bytes) 29 // of this field. 30 Size() Size 31 32 // Define writes the Go code to declare this field (in a struct definition). 33 Define(c *Context) 34 35 // Read writes the Go code to convert a byte slice to a Go value 36 // of this field. 37 // 'prefix' is the prefix of the name of the Go value. 38 Read(c *Context, prefix string) 39 40 // Write writes the Go code to convert a Go value to a byte slice of 41 // this field. 42 // 'prefix' is the prefix of the name of the Go value. 43 Write(c *Context, prefix string) 44 } 45 46 func (pad *PadField) Initialize(p *Protocol) {} 47 48 // PadField represents any type of padding. It is omitted from 49 // definitions, but is used in Read/Write to increment the buffer index. 50 // It is also used in size calculation. 51 type PadField struct { 52 Bytes uint 53 Align uint16 54 } 55 56 func (p *PadField) SrcName() string { 57 panic("illegal to take source name of a pad field") 58 } 59 60 func (p *PadField) XmlName() string { 61 panic("illegal to take XML name of a pad field") 62 } 63 64 func (f *PadField) SrcType() string { 65 panic("it is illegal to call SrcType on a PadField field") 66 } 67 68 func (p *PadField) Size() Size { 69 if p.Align > 0 { 70 return newFixedSize(uint(p.Align), false) 71 } else { 72 return newFixedSize(p.Bytes, true) 73 } 74 } 75 76 // SingleField represents most of the fields in an XML protocol description. 77 // It corresponds to any single value. 78 type SingleField struct { 79 srcName string 80 xmlName string 81 Type Type 82 } 83 84 func (f *SingleField) Initialize(p *Protocol) { 85 f.srcName = SrcName(p, f.XmlName()) 86 f.Type = f.Type.(*Translation).RealType(p) 87 } 88 89 func (f *SingleField) SrcName() string { 90 if f.srcName == "Bytes" { 91 return "Bytes_" 92 } 93 return f.srcName 94 } 95 96 func (f *SingleField) XmlName() string { 97 return f.xmlName 98 } 99 100 func (f *SingleField) SrcType() string { 101 return f.Type.SrcName() 102 } 103 104 func (f *SingleField) Size() Size { 105 return f.Type.Size() 106 } 107 108 // ListField represents a list of values. 109 type ListField struct { 110 srcName string 111 xmlName string 112 Type Type 113 LengthExpr Expression 114 } 115 116 func (f *ListField) SrcName() string { 117 return f.srcName 118 } 119 120 func (f *ListField) XmlName() string { 121 return f.xmlName 122 } 123 124 func (f *ListField) SrcType() string { 125 if strings.ToLower(f.Type.XmlName()) == "char" { 126 return fmt.Sprintf("string") 127 } 128 return fmt.Sprintf("[]%s", f.Type.SrcName()) 129 } 130 131 // Length computes the *number* of values in a list. 132 // If this ListField does not have any length expression, we throw our hands 133 // up and simply compute the 'len' of the field name of this list. 134 func (f *ListField) Length() Size { 135 if f.LengthExpr == nil { 136 return newExpressionSize(&Function{ 137 Name: "len", 138 Expr: &FieldRef{ 139 Name: f.SrcName(), 140 }, 141 }, true) 142 } 143 return newExpressionSize(f.LengthExpr, true) 144 } 145 146 // Size computes the *size* of a list (in bytes). 147 // It it typically a simple matter of multiplying the length of the list by 148 // the size of the type of the list. 149 // But if it's a list of struct where the struct has a list field, we use a 150 // special function written in go_struct.go to compute the size (since the 151 // size in this case can only be computed recursively). 152 func (f *ListField) Size() Size { 153 elsz := f.Type.Size() 154 simpleLen := &Padding{ 155 Expr: newBinaryOp("*", f.Length().Expression, elsz.Expression), 156 } 157 158 switch field := f.Type.(type) { 159 case *Struct: 160 if field.HasList() { 161 sizeFun := &Function{ 162 Name: fmt.Sprintf("%sListSize", f.Type.SrcName()), 163 Expr: &FieldRef{Name: f.SrcName()}, 164 } 165 return newExpressionSize(sizeFun, elsz.exact) 166 } else { 167 return newExpressionSize(simpleLen, elsz.exact) 168 } 169 case *Union: 170 return newExpressionSize(simpleLen, elsz.exact) 171 case *Base: 172 return newExpressionSize(simpleLen, elsz.exact) 173 case *Resource: 174 return newExpressionSize(simpleLen, elsz.exact) 175 case *TypeDef: 176 return newExpressionSize(simpleLen, elsz.exact) 177 default: 178 log.Panicf("Cannot compute list size with type '%T'.", f.Type) 179 } 180 panic("unreachable") 181 } 182 183 func (f *ListField) Initialize(p *Protocol) { 184 f.srcName = SrcName(p, f.XmlName()) 185 f.Type = f.Type.(*Translation).RealType(p) 186 if f.LengthExpr != nil { 187 f.LengthExpr.Initialize(p) 188 } 189 } 190 191 // LocalField is exactly the same as a regular SingleField, except it isn't 192 // sent over the wire. (i.e., it's probably used to compute an ExprField). 193 type LocalField struct { 194 *SingleField 195 } 196 197 // ExprField is a field that is not parameterized, but is computed from values 198 // of other fields. 199 type ExprField struct { 200 srcName string 201 xmlName string 202 Type Type 203 Expr Expression 204 } 205 206 func (f *ExprField) SrcName() string { 207 return f.srcName 208 } 209 210 func (f *ExprField) XmlName() string { 211 return f.xmlName 212 } 213 214 func (f *ExprField) SrcType() string { 215 return f.Type.SrcName() 216 } 217 218 func (f *ExprField) Size() Size { 219 return f.Type.Size() 220 } 221 222 func (f *ExprField) Initialize(p *Protocol) { 223 f.srcName = SrcName(p, f.XmlName()) 224 f.Type = f.Type.(*Translation).RealType(p) 225 f.Expr.Initialize(p) 226 } 227 228 // ValueField represents two fields in one: a mask and a list of 4-byte 229 // integers. The mask specifies which kinds of values are in the list. 230 // (i.e., See ConfigureWindow, CreateWindow, ChangeWindowAttributes, etc.) 231 type ValueField struct { 232 Parent interface{} 233 MaskType Type 234 MaskName string 235 ListName string 236 } 237 238 func (f *ValueField) SrcName() string { 239 panic("it is illegal to call SrcName on a ValueField field") 240 } 241 242 func (f *ValueField) XmlName() string { 243 panic("it is illegal to call XmlName on a ValueField field") 244 } 245 246 func (f *ValueField) SrcType() string { 247 return f.MaskType.SrcName() 248 } 249 250 // Size computes the size in bytes of the combination of the mask and list 251 // in this value field. 252 // The expression to compute this looks complicated, but it's really just 253 // the number of bits set in the mask multiplied 4 (and padded of course). 254 func (f *ValueField) Size() Size { 255 maskSize := f.MaskType.Size() 256 listSize := newExpressionSize(&Function{ 257 Name: "xgb.Pad", 258 Expr: &BinaryOp{ 259 Op: "*", 260 Expr1: &Value{v: 4}, 261 Expr2: &PopCount{ 262 Expr: &Function{ 263 Name: "int", 264 Expr: &FieldRef{ 265 Name: f.MaskName, 266 }, 267 }, 268 }, 269 }, 270 }, true) 271 return maskSize.Add(listSize) 272 } 273 274 func (f *ValueField) ListLength() Size { 275 return newExpressionSize(&PopCount{ 276 Expr: &Function{ 277 Name: "int", 278 Expr: &FieldRef{ 279 Name: f.MaskName, 280 }, 281 }, 282 }, true) 283 } 284 285 func (f *ValueField) Initialize(p *Protocol) { 286 f.MaskType = f.MaskType.(*Translation).RealType(p) 287 f.MaskName = SrcName(p, f.MaskName) 288 f.ListName = SrcName(p, f.ListName) 289 } 290 291 // SwitchField represents a 'switch' element in the XML protocol description 292 // file. It is not currently used. (i.e., it is XKB voodoo.) 293 type SwitchField struct { 294 Name string 295 Expr Expression 296 Bitcases []*Bitcase 297 } 298 299 func (f *SwitchField) SrcName() string { 300 panic("it is illegal to call SrcName on a SwitchField field") 301 } 302 303 func (f *SwitchField) XmlName() string { 304 panic("it is illegal to call XmlName on a SwitchField field") 305 } 306 307 func (f *SwitchField) SrcType() string { 308 panic("it is illegal to call SrcType on a SwitchField field") 309 } 310 311 // XXX: This is a bit tricky. The size has to be represented as a non-concrete 312 // expression that finds *which* bitcase fields are included, and sums the 313 // sizes of those fields. 314 func (f *SwitchField) Size() Size { 315 return newFixedSize(0, true) 316 } 317 318 func (f *SwitchField) Initialize(p *Protocol) { 319 f.Name = SrcName(p, f.Name) 320 f.Expr.Initialize(p) 321 for _, bitcase := range f.Bitcases { 322 bitcase.Expr.Initialize(p) 323 for _, field := range bitcase.Fields { 324 field.Initialize(p) 325 } 326 } 327 } 328 329 // Bitcase represents a single bitcase inside a switch expression. 330 // It is not currently used. (i.e., it's XKB voodoo.) 331 type Bitcase struct { 332 Fields []Field 333 Expr Expression 334 }