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)
78 def make_fd_of(self, module, complex_type, fd_name):
80 Method for making a fd member of a structure.
82 new_fd = Field(self, module.get_type_name('INT32'), fd_name, True, False, False, None, True)
83 # We dump the _placeholder_byte if any fields are added.
84 for (idx, field) in enumerate(complex_type.fields):
85 if field == _placeholder_byte:
86 complex_type.fields[idx] = new_fd
89 complex_type.fields.append(new_fd)
91 class SimpleType(Type):
93 Derived class which represents a cardinal type like CARD32 or char.
94 Any type which is typedef'ed to cardinal will be one of these.
99 def __init__(self, name, size):
100 Type.__init__(self, name)
101 self.is_simple = True
105 def resolve(self, module):
108 def fixed_size(self):
111 out = __main__.output['simple']
114 # Cardinal datatype globals. See module __init__ method.
115 tcard8 = SimpleType(('uint8_t',), 1)
116 tcard16 = SimpleType(('uint16_t',), 2)
117 tcard32 = SimpleType(('uint32_t',), 4)
118 tcard64 = SimpleType(('uint64_t',), 8)
119 tint8 = SimpleType(('int8_t',), 1)
120 tint16 = SimpleType(('int16_t',), 2)
121 tint32 = SimpleType(('int32_t',), 4)
122 tint64 = SimpleType(('int64_t',), 8)
123 tchar = SimpleType(('char',), 1)
124 tfloat = SimpleType(('float',), 4)
125 tdouble = SimpleType(('double',), 8)
128 class Enum(SimpleType):
130 Derived class which represents an enum. Fixed-size.
133 values contains a list of (name, value) tuples. value is empty, or a number.
134 bits contains a list of (name, bitnum) tuples. items only appear if specified as a bit. bitnum is a number.
136 def __init__(self, name, elt):
137 SimpleType.__init__(self, name, 4)
141 for item in list(elt):
142 if item.tag == 'doc':
143 self.doc = Doc(name, item)
145 # First check if we're using a default value
146 if len(list(item)) == 0:
147 self.values.append((item.get('name'), ''))
150 # An explicit value or bit was specified.
151 value = list(item)[0]
152 if value.tag == 'value':
153 self.values.append((item.get('name'), value.text))
154 elif value.tag == 'bit':
155 self.values.append((item.get('name'), '%u' % (1 << int(value.text, 0))))
156 self.bits.append((item.get('name'), value.text))
158 def resolve(self, module):
161 def fixed_size(self):
164 out = __main__.output['enum']
167 class ListType(Type):
169 Derived class which represents a list of some other datatype. Fixed- or variable-sized.
172 member is the datatype of the list elements.
173 parent is the structure type containing the list.
174 expr is an Expression object containing the length information, for variable-sized lists.
176 def __init__(self, elt, member, *parent):
177 Type.__init__(self, member.name)
180 self.parents = list(parent)
182 if elt.tag == 'list':
184 self.expr = Expression(elts[0] if len(elts) else elt, self)
185 elif elt.tag == 'valueparam':
186 self.expr = Expression(elt, self)
188 self.size = member.size if member.fixed_size() else None
189 self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None
191 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
192 if not self.fixed_size():
193 # We need a length field.
194 # Ask our Expression object for it's name, type, and whether it's on the wire.
195 lenfid = self.expr.lenfield_type
196 lenfield_name = self.expr.lenfield_name
197 lenwire = self.expr.lenwire
200 # See if the length field is already in the structure.
201 for parent in self.parents:
202 for field in parent.fields:
203 if field.field_name == lenfield_name:
206 # It isn't, so we need to add it to the structure ourself.
208 type = module.get_type(lenfid)
209 lenfield_type = module.get_type_name(lenfid)
210 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
212 # Add ourself to the structure by calling our original method.
213 Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
215 def resolve(self, module):
218 self.member.resolve(module)
219 self.expr.resolve(module, self.parents)
221 # Find my length field again. We need the actual Field object in the expr.
222 # This is needed because we might have added it ourself above.
223 if not self.fixed_size():
224 for parent in self.parents:
225 for field in parent.fields:
226 if field.field_name == self.expr.lenfield_name and field.wire:
227 self.expr.lenfield = field
232 def fixed_size(self):
233 return self.member.fixed_size() and self.expr.fixed_size()
235 class ExprType(Type):
237 Derived class which represents an exprfield. Fixed size.
240 expr is an Expression object containing the value of the field.
242 def __init__(self, elt, member, *parents):
243 Type.__init__(self, member.name)
246 self.parents = parents
248 self.expr = Expression(list(elt)[0], self)
250 self.size = member.size
253 def resolve(self, module):
256 self.member.resolve(module)
259 def fixed_size(self):
264 Derived class which represents a padding field.
266 def __init__(self, elt):
267 Type.__init__(self, tcard8.name)
273 self.nmemb = int(elt.get('bytes', "1"), 0)
274 self.align = int(elt.get('align', "1"), 0)
276 def resolve(self, module):
279 def fixed_size(self):
280 return self.align <= 1
283 class ComplexType(Type):
285 Derived class which represents a structure. Base type for all structure types.
288 fields is an array of Field objects describing the structure fields.
290 def __init__(self, name, elt):
291 Type.__init__(self, name)
292 self.is_container = True
297 self.lenfield_parent = [self]
300 def resolve(self, module):
305 # Resolve all of our field datatypes.
306 for child in list(self.elt):
307 if child.tag == 'pad':
308 field_name = 'pad' + str(module.pads)
310 type = PadType(child)
311 module.pads = module.pads + 1
313 elif child.tag == 'field':
314 field_name = child.get('name')
315 enum = child.get('enum')
316 fkey = child.get('type')
317 type = module.get_type(fkey)
319 elif child.tag == 'exprfield':
320 field_name = child.get('name')
321 fkey = child.get('type')
322 type = ExprType(child, module.get_type(fkey), *self.lenfield_parent)
324 elif child.tag == 'list':
325 field_name = child.get('name')
326 fkey = child.get('type')
327 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
329 elif child.tag == 'valueparam':
330 field_name = child.get('value-list-name')
332 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
334 elif child.tag == 'switch':
335 field_name = child.get('name')
336 # construct the switch type name from the parent type and the field name
337 field_type = self.name + (field_name,)
338 type = SwitchType(field_type, child, *self.lenfield_parent)
340 type.make_member_of(module, self, field_type, field_name, visible, True, False)
343 elif child.tag == 'fd':
344 fd_name = child.get('name')
345 type = module.get_type('INT32')
346 type.make_fd_of(module, self, fd_name)
352 # Get the full type name for the field
353 field_type = module.get_type_name(fkey)
354 # Add the field to ourself
355 type.make_member_of(module, self, field_type, field_name, visible, True, False, enum)
356 # Recursively resolve the type (could be another structure, list)
359 self.calc_size() # Figure out how big we are
364 for m in self.fields:
367 if m.type.fixed_size():
368 self.size = self.size + (m.type.size * m.type.nmemb)
373 def fixed_size(self):
374 for m in self.fields:
375 if not m.type.fixed_size():
379 class SwitchType(ComplexType):
381 Derived class which represents a List of Items.
384 bitcases is an array of Bitcase objects describing the list items
387 def __init__(self, name, elt, *parents):
388 ComplexType.__init__(self, name, elt)
389 self.parents = parents
390 # FIXME: switch cannot store lenfields, so it should just delegate the parents
391 self.lenfield_parent = list(parents) + [self]
392 # self.fields contains all possible fields collected from the Bitcase objects,
393 # whereas self.items contains the Bitcase objects themselves
396 self.is_switch = True
398 self.expr = Expression(elts[0] if len(elts) else elt, self)
400 def resolve(self, module):
404 parents = list(self.parents) + [self]
406 # Resolve all of our field datatypes.
407 for index, child in enumerate(list(self.elt)):
408 if child.tag == 'bitcase':
409 field_name = child.get('name')
410 if field_name is None:
411 field_type = self.name + ('bitcase%d' % index,)
413 field_type = self.name + (field_name,)
415 # use self.parent to indicate anchestor,
416 # as switch does not contain named fields itself
417 type = BitcaseType(index, field_type, child, *parents)
418 # construct the switch type name from the parent type and the field name
419 if field_name is None:
420 type.has_name = False
421 # Get the full type name for the field
422 field_type = type.name
425 # add the field to ourself
426 type.make_member_of(module, self, field_type, field_name, visible, True, False)
428 # recursively resolve the type (could be another structure, list)
431 for new_field in type.fields:
432 # We dump the _placeholder_byte if any fields are added.
433 for (idx, field) in enumerate(self.fields):
434 if field == _placeholder_byte:
435 self.fields[idx] = new_field
438 if False == inserted:
439 self.fields.append(new_field)
441 self.calc_size() # Figure out how big we are
444 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
445 if not self.fixed_size():
446 # We need a length field.
447 # Ask our Expression object for it's name, type, and whether it's on the wire.
448 lenfid = self.expr.lenfield_type
449 lenfield_name = self.expr.lenfield_name
450 lenwire = self.expr.lenwire
453 # See if the length field is already in the structure.
454 for parent in self.parents:
455 for field in parent.fields:
456 if field.field_name == lenfield_name:
459 # It isn't, so we need to add it to the structure ourself.
461 type = module.get_type(lenfid)
462 lenfield_type = module.get_type_name(lenfid)
463 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
465 # Add ourself to the structure by calling our original method.
466 Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
468 # size for switch can only be calculated at runtime
472 # note: switch is _always_ of variable size, but we indicate here wether
473 # it contains elements that are variable-sized themselves
474 def fixed_size(self):
476 # for m in self.fields:
477 # if not m.type.fixed_size():
482 class Struct(ComplexType):
484 Derived class representing a struct data type.
486 out = __main__.output['struct']
489 class Union(ComplexType):
491 Derived class representing a union data type.
493 def __init__(self, name, elt):
494 ComplexType.__init__(self, name, elt)
497 out = __main__.output['union']
500 class BitcaseType(ComplexType):
502 Derived class representing a struct data type.
504 def __init__(self, index, name, elt, *parent):
509 if elt.tag == 'enumref':
510 self.expr.append(Expression(elt, self))
513 ComplexType.__init__(self, name, fields)
516 self.lenfield_parent = list(parent) + [self]
517 self.parents = list(parent)
518 self.is_bitcase = True
520 def make_member_of(self, module, switch_type, field_type, field_name, visible, wire, auto, enum=None):
522 register BitcaseType with the corresponding SwitchType
524 module is the global module object.
525 complex_type is the structure object.
526 see Field for the meaning of the other parameters.
528 new_field = Field(self, field_type, field_name, visible, wire, auto, enum)
530 # We dump the _placeholder_byte if any bitcases are added.
531 for (idx, field) in enumerate(switch_type.bitcases):
532 if field == _placeholder_byte:
533 switch_type.bitcases[idx] = new_field
536 switch_type.bitcases.append(new_field)
538 def resolve(self, module):
543 e.resolve(module, self.parents+[self])
545 # Resolve the bitcase expression
546 ComplexType.resolve(self, module)
549 class Reply(ComplexType):
551 Derived class representing a reply. Only found as a field of Request.
553 def __init__(self, name, elt):
554 ComplexType.__init__(self, name, elt)
558 for child in list(elt):
559 if child.tag == 'doc':
560 self.doc = Doc(name, child)
562 def resolve(self, module):
567 # Add the automatic protocol fields
568 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
569 self.fields.append(_placeholder_byte)
570 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
571 self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
572 ComplexType.resolve(self, module)
575 class Request(ComplexType):
577 Derived class representing a request.
580 reply contains the reply datatype or None for void requests.
581 opcode contains the request number.
583 def __init__(self, name, elt):
584 ComplexType.__init__(self, name, elt)
587 self.opcode = elt.get('opcode')
589 for child in list(elt):
590 if child.tag == 'reply':
591 self.reply = Reply(name, child)
592 if child.tag == 'doc':
593 self.doc = Doc(name, child)
595 def resolve(self, module):
598 # Add the automatic protocol fields
599 if module.namespace.is_ext:
600 self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
601 self.fields.append(Field(tcard8, tcard8.name, 'minor_opcode', False, True, True))
602 self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
603 ComplexType.resolve(self, module)
605 self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
606 self.fields.append(_placeholder_byte)
607 self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
608 ComplexType.resolve(self, module)
611 self.reply.resolve(module)
613 out = __main__.output['request']
616 class Event(ComplexType):
618 Derived class representing an event data type.
621 opcodes is a dictionary of name -> opcode number, for eventcopies.
623 def __init__(self, name, elt):
624 ComplexType.__init__(self, name, elt)
627 self.has_seq = not bool(elt.get('no-sequence-number'))
629 self.is_ge_event = bool(elt.get('xge'))
632 for item in list(elt):
633 if item.tag == 'doc':
634 self.doc = Doc(name, item)
636 def add_opcode(self, opcode, name, main):
637 self.opcodes[name] = opcode
641 def resolve(self, module):
642 def add_event_header():
643 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
645 self.fields.append(_placeholder_byte)
646 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
648 def add_ge_event_header():
649 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
650 self.fields.append(Field(tcard8, tcard8.name, 'extension', False, True, True))
651 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
652 self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
653 self.fields.append(Field(tcard16, tcard16.name, 'event_type', False, True, True))
658 # Add the automatic protocol fields
660 add_ge_event_header()
664 ComplexType.resolve(self, module)
666 out = __main__.output['event']
669 class Error(ComplexType):
671 Derived class representing an error data type.
674 opcodes is a dictionary of name -> opcode number, for errorcopies.
676 def __init__(self, name, elt):
677 ComplexType.__init__(self, name, elt)
680 def add_opcode(self, opcode, name, main):
681 self.opcodes[name] = opcode
685 def resolve(self, module):
689 # Add the automatic protocol fields
690 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
691 self.fields.append(Field(tcard8, tcard8.name, 'error_code', False, True, True))
692 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
693 ComplexType.resolve(self, module)
695 out = __main__.output['error']
700 Class representing a <doc> tag.
702 def __init__(self, name, elt):
704 self.description = None
705 self.brief = 'BRIEF DESCRIPTION MISSING'
711 for child in list(elt):
712 text = child.text if child.text else ''
713 if child.tag == 'description':
714 self.description = text.strip()
715 if child.tag == 'brief':
716 self.brief = text.strip()
717 if child.tag == 'field':
718 self.fields[child.get('name')] = text.strip()
719 if child.tag == 'error':
720 self.errors[child.get('type')] = text.strip()
721 if child.tag == 'see':
722 self.see[child.get('name')] = child.get('type')
723 if child.tag == 'example':
724 self.example = text.strip()
728 _placeholder_byte = Field(PadType(None), tcard8.name, 'pad0', False, True, False)