2 This module contains the classes which represent XCB data types.
4 from xcbgen.expr import Field, Expression
9 Abstract base class for all XCB data types.
10 Contains default fields, and some abstract methods.
12 def __init__(self, name):
14 Default structure initializer. Sets up default fields.
17 name is a tuple of strings specifying the full type name.
18 size is the size of the datatype in bytes, or None if variable-sized.
19 nmemb is 1 for non-list types, None for variable-sized lists, otherwise number of elts.
20 booleans for identifying subclasses, because I can't figure out isinstance().
28 self.is_simple = False
31 self.is_container = False
35 self.is_switch = False
36 self.is_bitcase = False
38 def resolve(self, module):
40 Abstract method for resolving a type.
41 This should make sure any referenced types are already declared.
43 raise Exception('abstract resolve method not overridden!')
47 Abstract method for outputting code.
48 These are declared in the language-specific modules, and
49 there must be a dictionary containing them declared when this module is imported!
51 raise Exception('abstract out method not overridden!')
55 Abstract method for determining if the data type is fixed-size.
57 raise Exception('abstract fixed_size method not overridden!')
59 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
61 Default method for making a data type a member of a structure.
62 Extend this if the data type needs to add an additional length field or something.
64 module is the global module object.
65 complex_type is the structure object.
66 see Field for the meaning of the other parameters.
68 new_field = Field(self, field_type, field_name, visible, wire, auto, enum)
70 # We dump the _placeholder_byte if any fields are added.
71 for (idx, field) in enumerate(complex_type.fields):
72 if field == _placeholder_byte:
73 complex_type.fields[idx] = new_field
76 complex_type.fields.append(new_field)
79 class SimpleType(Type):
81 Derived class which represents a cardinal type like CARD32 or char.
82 Any type which is typedef'ed to cardinal will be one of these.
87 def __init__(self, name, size):
88 Type.__init__(self, name)
93 def resolve(self, module):
99 out = __main__.output['simple']
102 # Cardinal datatype globals. See module __init__ method.
103 tcard8 = SimpleType(('uint8_t',), 1)
104 tcard16 = SimpleType(('uint16_t',), 2)
105 tcard32 = SimpleType(('uint32_t',), 4)
106 tint8 = SimpleType(('int8_t',), 1)
107 tint16 = SimpleType(('int16_t',), 2)
108 tint32 = SimpleType(('int32_t',), 4)
109 tchar = SimpleType(('char',), 1)
110 tfloat = SimpleType(('float',), 4)
111 tdouble = SimpleType(('double',), 8)
114 class Enum(SimpleType):
116 Derived class which represents an enum. Fixed-size.
119 values contains a list of (name, value) tuples. value is empty, or a number.
120 bits contains a list of (name, bitnum) tuples. items only appear if specified as a bit. bitnum is a number.
122 def __init__(self, name, elt):
123 SimpleType.__init__(self, name, 4)
127 for item in list(elt):
128 if item.tag == 'doc':
129 self.doc = Doc(name, item)
131 # First check if we're using a default value
132 if len(list(item)) == 0:
133 self.values.append((item.get('name'), ''))
136 # An explicit value or bit was specified.
137 value = list(item)[0]
138 if value.tag == 'value':
139 self.values.append((item.get('name'), value.text))
140 elif value.tag == 'bit':
141 self.values.append((item.get('name'), '%u' % (1 << int(value.text, 0))))
142 self.bits.append((item.get('name'), value.text))
144 def resolve(self, module):
147 def fixed_size(self):
150 out = __main__.output['enum']
153 class ListType(Type):
155 Derived class which represents a list of some other datatype. Fixed- or variable-sized.
158 member is the datatype of the list elements.
159 parent is the structure type containing the list.
160 expr is an Expression object containing the length information, for variable-sized lists.
162 def __init__(self, elt, member, *parent):
163 Type.__init__(self, member.name)
166 self.parents = list(parent)
168 if elt.tag == 'list':
170 self.expr = Expression(elts[0] if len(elts) else elt, self)
171 elif elt.tag == 'valueparam':
172 self.expr = Expression(elt, self)
174 self.size = member.size if member.fixed_size() else None
175 self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None
177 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
178 if not self.fixed_size():
179 # We need a length field.
180 # Ask our Expression object for it's name, type, and whether it's on the wire.
181 lenfid = self.expr.lenfield_type
182 lenfield_name = self.expr.lenfield_name
183 lenwire = self.expr.lenwire
186 # See if the length field is already in the structure.
187 for parent in self.parents:
188 for field in parent.fields:
189 if field.field_name == lenfield_name:
192 # It isn't, so we need to add it to the structure ourself.
194 type = module.get_type(lenfid)
195 lenfield_type = module.get_type_name(lenfid)
196 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
198 # Add ourself to the structure by calling our original method.
199 Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
201 def resolve(self, module):
204 self.member.resolve(module)
205 self.expr.resolve(module, self.parents)
207 # Find my length field again. We need the actual Field object in the expr.
208 # This is needed because we might have added it ourself above.
209 if not self.fixed_size():
210 for parent in self.parents:
211 for field in parent.fields:
212 if field.field_name == self.expr.lenfield_name and field.wire:
213 self.expr.lenfield = field
218 def fixed_size(self):
219 return self.member.fixed_size() and self.expr.fixed_size()
221 class ExprType(Type):
223 Derived class which represents an exprfield. Fixed size.
226 expr is an Expression object containing the value of the field.
228 def __init__(self, elt, member, *parents):
229 Type.__init__(self, member.name)
232 self.parents = parents
234 self.expr = Expression(list(elt)[0], self)
236 self.size = member.size
239 def resolve(self, module):
242 self.member.resolve(module)
245 def fixed_size(self):
250 Derived class which represents a padding field.
252 def __init__(self, elt):
253 Type.__init__(self, tcard8.name)
256 self.nmemb = 1 if (elt == None) else int(elt.get('bytes'), 0)
258 def resolve(self, module):
261 def fixed_size(self):
265 class ComplexType(Type):
267 Derived class which represents a structure. Base type for all structure types.
270 fields is an array of Field objects describing the structure fields.
272 def __init__(self, name, elt):
273 Type.__init__(self, name)
274 self.is_container = True
279 self.lenfield_parent = [self]
281 def resolve(self, module):
287 # Resolve all of our field datatypes.
288 for child in list(self.elt):
289 if child.tag == 'pad':
290 field_name = 'pad' + str(pads)
292 type = PadType(child)
295 elif child.tag == 'field':
296 field_name = child.get('name')
297 enum = child.get('enum')
298 fkey = child.get('type')
299 type = module.get_type(fkey)
301 elif child.tag == 'exprfield':
302 field_name = child.get('name')
303 fkey = child.get('type')
304 type = ExprType(child, module.get_type(fkey), *self.lenfield_parent)
306 elif child.tag == 'list':
307 field_name = child.get('name')
308 fkey = child.get('type')
309 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
311 elif child.tag == 'valueparam':
312 field_name = child.get('value-list-name')
314 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
316 elif child.tag == 'switch':
317 field_name = child.get('name')
318 # construct the switch type name from the parent type and the field name
319 field_type = self.name + (field_name,)
320 type = SwitchType(field_type, child, *self.lenfield_parent)
322 type.make_member_of(module, self, field_type, field_name, visible, True, False)
329 # Get the full type name for the field
330 field_type = module.get_type_name(fkey)
331 # Add the field to ourself
332 type.make_member_of(module, self, field_type, field_name, visible, True, False, enum)
333 # Recursively resolve the type (could be another structure, list)
336 self.calc_size() # Figure out how big we are
341 for m in self.fields:
344 if m.type.fixed_size():
345 self.size = self.size + (m.type.size * m.type.nmemb)
350 def fixed_size(self):
351 for m in self.fields:
352 if not m.type.fixed_size():
356 class SwitchType(ComplexType):
358 Derived class which represents a List of Items.
361 bitcases is an array of Bitcase objects describing the list items
364 def __init__(self, name, elt, *parents):
365 ComplexType.__init__(self, name, elt)
366 self.parents = parents
367 # FIXME: switch cannot store lenfields, so it should just delegate the parents
368 self.lenfield_parent = list(parents) + [self]
369 # self.fields contains all possible fields collected from the Bitcase objects,
370 # whereas self.items contains the Bitcase objects themselves
373 self.is_switch = True
375 self.expr = Expression(elts[0] if len(elts) else elt, self)
377 def resolve(self, module):
382 parents = list(self.parents) + [self]
384 # Resolve all of our field datatypes.
385 for index, child in enumerate(list(self.elt)):
386 if child.tag == 'bitcase':
387 field_name = child.get('name')
388 if field_name is None:
389 field_type = self.name + ('bitcase%d' % index,)
391 field_type = self.name + (field_name,)
393 # use self.parent to indicate anchestor,
394 # as switch does not contain named fields itself
395 type = BitcaseType(index, field_type, child, *parents)
396 # construct the switch type name from the parent type and the field name
397 if field_name is None:
398 type.has_name = False
399 # Get the full type name for the field
400 field_type = type.name
403 # add the field to ourself
404 type.make_member_of(module, self, field_type, field_name, visible, True, False)
406 # recursively resolve the type (could be another structure, list)
409 for new_field in type.fields:
410 # We dump the _placeholder_byte if any fields are added.
411 for (idx, field) in enumerate(self.fields):
412 if field == _placeholder_byte:
413 self.fields[idx] = new_field
416 if False == inserted:
417 self.fields.append(new_field)
419 self.calc_size() # Figure out how big we are
422 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
423 if not self.fixed_size():
424 # We need a length field.
425 # Ask our Expression object for it's name, type, and whether it's on the wire.
426 lenfid = self.expr.lenfield_type
427 lenfield_name = self.expr.lenfield_name
428 lenwire = self.expr.lenwire
431 # See if the length field is already in the structure.
432 for parent in self.parents:
433 for field in parent.fields:
434 if field.field_name == lenfield_name:
437 # It isn't, so we need to add it to the structure ourself.
439 type = module.get_type(lenfid)
440 lenfield_type = module.get_type_name(lenfid)
441 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
443 # Add ourself to the structure by calling our original method.
444 Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
446 # size for switch can only be calculated at runtime
450 # note: switch is _always_ of variable size, but we indicate here wether
451 # it contains elements that are variable-sized themselves
452 def fixed_size(self):
454 # for m in self.fields:
455 # if not m.type.fixed_size():
460 class Struct(ComplexType):
462 Derived class representing a struct data type.
464 out = __main__.output['struct']
467 class Union(ComplexType):
469 Derived class representing a union data type.
471 def __init__(self, name, elt):
472 ComplexType.__init__(self, name, elt)
475 out = __main__.output['union']
478 class BitcaseType(ComplexType):
480 Derived class representing a struct data type.
482 def __init__(self, index, name, elt, *parent):
487 if elt.tag == 'enumref':
488 self.expr.append(Expression(elt, self))
491 ComplexType.__init__(self, name, fields)
494 self.lenfield_parent = list(parent) + [self]
495 self.parents = list(parent)
496 self.is_bitcase = True
498 def make_member_of(self, module, switch_type, field_type, field_name, visible, wire, auto, enum=None):
500 register BitcaseType with the corresponding SwitchType
502 module is the global module object.
503 complex_type is the structure object.
504 see Field for the meaning of the other parameters.
506 new_field = Field(self, field_type, field_name, visible, wire, auto, enum)
508 # We dump the _placeholder_byte if any bitcases are added.
509 for (idx, field) in enumerate(switch_type.bitcases):
510 if field == _placeholder_byte:
511 switch_type.bitcases[idx] = new_field
514 switch_type.bitcases.append(new_field)
516 def resolve(self, module):
521 e.resolve(module, self.parents+[self])
523 # Resolve the bitcase expression
524 ComplexType.resolve(self, module)
527 class Reply(ComplexType):
529 Derived class representing a reply. Only found as a field of Request.
531 def __init__(self, name, elt):
532 ComplexType.__init__(self, name, elt)
536 for child in list(elt):
537 if child.tag == 'doc':
538 self.doc = Doc(name, child)
540 def resolve(self, module):
543 # Add the automatic protocol fields
544 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
545 self.fields.append(_placeholder_byte)
546 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
547 self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
548 ComplexType.resolve(self, module)
551 class Request(ComplexType):
553 Derived class representing a request.
556 reply contains the reply datatype or None for void requests.
557 opcode contains the request number.
559 def __init__(self, name, elt):
560 ComplexType.__init__(self, name, elt)
563 self.opcode = elt.get('opcode')
565 for child in list(elt):
566 if child.tag == 'reply':
567 self.reply = Reply(name, child)
568 if child.tag == 'doc':
569 self.doc = Doc(name, child)
571 def resolve(self, module):
574 # Add the automatic protocol fields
575 if module.namespace.is_ext:
576 self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
577 self.fields.append(Field(tcard8, tcard8.name, 'minor_opcode', False, True, True))
578 self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
579 ComplexType.resolve(self, module)
581 self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
582 self.fields.append(_placeholder_byte)
583 self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
584 ComplexType.resolve(self, module)
587 self.reply.resolve(module)
589 out = __main__.output['request']
592 class Event(ComplexType):
594 Derived class representing an event data type.
597 opcodes is a dictionary of name -> opcode number, for eventcopies.
599 def __init__(self, name, elt):
600 ComplexType.__init__(self, name, elt)
603 self.has_seq = not bool(elt.get('no-sequence-number'))
606 for item in list(elt):
607 if item.tag == 'doc':
608 self.doc = Doc(name, item)
610 def add_opcode(self, opcode, name, main):
611 self.opcodes[name] = opcode
615 def resolve(self, module):
619 # Add the automatic protocol fields
620 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
622 self.fields.append(_placeholder_byte)
623 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
624 ComplexType.resolve(self, module)
626 out = __main__.output['event']
629 class Error(ComplexType):
631 Derived class representing an error data type.
634 opcodes is a dictionary of name -> opcode number, for errorcopies.
636 def __init__(self, name, elt):
637 ComplexType.__init__(self, name, elt)
640 def add_opcode(self, opcode, name, main):
641 self.opcodes[name] = opcode
645 def resolve(self, module):
649 # Add the automatic protocol fields
650 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
651 self.fields.append(Field(tcard8, tcard8.name, 'error_code', False, True, True))
652 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
653 ComplexType.resolve(self, module)
655 out = __main__.output['error']
660 Class representing a <doc> tag.
662 def __init__(self, name, elt):
664 self.description = None
665 self.brief = 'BRIEF DESCRIPTION MISSING'
671 for child in list(elt):
672 text = child.text if child.text else ''
673 if child.tag == 'description':
674 self.description = text.strip()
675 if child.tag == 'brief':
676 self.brief = text.strip()
677 if child.tag == 'field':
678 self.fields[child.get('name')] = text.strip()
679 if child.tag == 'error':
680 self.errors[child.get('type')] = text.strip()
681 if child.tag == 'see':
682 self.see[child.get('name')] = child.get('type')
683 if child.tag == 'example':
684 self.example = text.strip()
688 _placeholder_byte = Field(PadType(None), tcard8.name, 'pad0', False, True, False)