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_case_or_bitcase = False
37 self.is_bitcase = False
40 def resolve(self, module):
42 Abstract method for resolving a type.
43 This should make sure any referenced types are already declared.
45 raise Exception('abstract resolve method not overridden!')
49 Abstract method for outputting code.
50 These are declared in the language-specific modules, and
51 there must be a dictionary containing them declared when this module is imported!
53 raise Exception('abstract out method not overridden!')
57 Abstract method for determining if the data type is fixed-size.
59 raise Exception('abstract fixed_size method not overridden!')
61 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
63 Default method for making a data type a member of a structure.
64 Extend this if the data type needs to add an additional length field or something.
66 module is the global module object.
67 complex_type is the structure object.
68 see Field for the meaning of the other parameters.
70 new_field = Field(self, field_type, field_name, visible, wire, auto, enum)
72 # We dump the _placeholder_byte if any fields are added.
73 for (idx, field) in enumerate(complex_type.fields):
74 if field == _placeholder_byte:
75 complex_type.fields[idx] = new_field
78 complex_type.fields.append(new_field)
80 def make_fd_of(self, module, complex_type, fd_name):
82 Method for making a fd member of a structure.
84 new_fd = Field(self, module.get_type_name('INT32'), fd_name, True, False, False, None, True)
85 # We dump the _placeholder_byte if any fields are added.
86 for (idx, field) in enumerate(complex_type.fields):
87 if field == _placeholder_byte:
88 complex_type.fields[idx] = new_fd
91 complex_type.fields.append(new_fd)
93 class SimpleType(Type):
95 Derived class which represents a cardinal type like CARD32 or char.
96 Any type which is typedef'ed to cardinal will be one of these.
101 def __init__(self, name, size):
102 Type.__init__(self, name)
103 self.is_simple = True
107 def resolve(self, module):
110 def fixed_size(self):
113 out = __main__.output['simple']
116 # Cardinal datatype globals. See module __init__ method.
117 tcard8 = SimpleType(('uint8_t',), 1)
118 tcard16 = SimpleType(('uint16_t',), 2)
119 tcard32 = SimpleType(('uint32_t',), 4)
120 tcard64 = SimpleType(('uint64_t',), 8)
121 tint8 = SimpleType(('int8_t',), 1)
122 tint16 = SimpleType(('int16_t',), 2)
123 tint32 = SimpleType(('int32_t',), 4)
124 tint64 = SimpleType(('int64_t',), 8)
125 tchar = SimpleType(('char',), 1)
126 tfloat = SimpleType(('float',), 4)
127 tdouble = SimpleType(('double',), 8)
130 class Enum(SimpleType):
132 Derived class which represents an enum. Fixed-size.
135 values contains a list of (name, value) tuples. value is empty, or a number.
136 bits contains a list of (name, bitnum) tuples. items only appear if specified as a bit. bitnum is a number.
138 def __init__(self, name, elt):
139 SimpleType.__init__(self, name, 4)
143 for item in list(elt):
144 if item.tag == 'doc':
145 self.doc = Doc(name, item)
147 # First check if we're using a default value
148 if len(list(item)) == 0:
149 self.values.append((item.get('name'), ''))
152 # An explicit value or bit was specified.
153 value = list(item)[0]
154 if value.tag == 'value':
155 self.values.append((item.get('name'), value.text))
156 elif value.tag == 'bit':
157 self.values.append((item.get('name'), '%u' % (1 << int(value.text, 0))))
158 self.bits.append((item.get('name'), value.text))
160 def resolve(self, module):
163 def fixed_size(self):
166 out = __main__.output['enum']
169 class ListType(Type):
171 Derived class which represents a list of some other datatype. Fixed- or variable-sized.
174 member is the datatype of the list elements.
175 parent is the structure type containing the list.
176 expr is an Expression object containing the length information, for variable-sized lists.
178 def __init__(self, elt, member, *parent):
179 Type.__init__(self, member.name)
182 self.parents = list(parent)
184 if elt.tag == 'list':
186 self.expr = Expression(elts[0] if len(elts) else elt, self)
187 elif elt.tag == 'valueparam':
188 self.expr = Expression(elt, self)
190 self.size = member.size if member.fixed_size() else None
191 self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None
193 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
194 if not self.fixed_size():
195 # We need a length field.
196 # Ask our Expression object for it's name, type, and whether it's on the wire.
197 lenfid = self.expr.lenfield_type
198 lenfield_name = self.expr.lenfield_name
199 lenwire = self.expr.lenwire
202 # See if the length field is already in the structure.
203 for parent in self.parents:
204 for field in parent.fields:
205 if field.field_name == lenfield_name:
208 # It isn't, so we need to add it to the structure ourself.
210 type = module.get_type(lenfid)
211 lenfield_type = module.get_type_name(lenfid)
212 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
214 # Add ourself to the structure by calling our original method.
215 Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
217 def resolve(self, module):
220 self.member.resolve(module)
221 self.expr.resolve(module, self.parents)
223 # Find my length field again. We need the actual Field object in the expr.
224 # This is needed because we might have added it ourself above.
225 if not self.fixed_size():
226 for parent in self.parents:
227 for field in parent.fields:
228 if field.field_name == self.expr.lenfield_name and field.wire:
229 self.expr.lenfield = field
234 def fixed_size(self):
235 return self.member.fixed_size() and self.expr.fixed_size()
237 class ExprType(Type):
239 Derived class which represents an exprfield. Fixed size.
242 expr is an Expression object containing the value of the field.
244 def __init__(self, elt, member, *parents):
245 Type.__init__(self, member.name)
248 self.parents = parents
250 self.expr = Expression(list(elt)[0], self)
252 self.size = member.size
255 def resolve(self, module):
258 self.member.resolve(module)
261 def fixed_size(self):
266 Derived class which represents a padding field.
268 def __init__(self, elt):
269 Type.__init__(self, tcard8.name)
275 self.nmemb = int(elt.get('bytes', "1"), 0)
276 self.align = int(elt.get('align', "1"), 0)
278 def resolve(self, module):
281 def fixed_size(self):
282 return self.align <= 1
285 class ComplexType(Type):
287 Derived class which represents a structure. Base type for all structure types.
290 fields is an array of Field objects describing the structure fields.
292 def __init__(self, name, elt):
293 Type.__init__(self, name)
294 self.is_container = True
299 self.lenfield_parent = [self]
302 def resolve(self, module):
307 # Resolve all of our field datatypes.
308 for child in list(self.elt):
309 if child.tag == 'pad':
310 field_name = 'pad' + str(module.pads)
312 type = PadType(child)
313 module.pads = module.pads + 1
315 elif child.tag == 'field':
316 field_name = child.get('name')
317 enum = child.get('enum')
318 fkey = child.get('type')
319 type = module.get_type(fkey)
321 elif child.tag == 'exprfield':
322 field_name = child.get('name')
323 fkey = child.get('type')
324 type = ExprType(child, module.get_type(fkey), *self.lenfield_parent)
326 elif child.tag == 'list':
327 field_name = child.get('name')
328 fkey = child.get('type')
329 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
331 elif child.tag == 'valueparam':
332 field_name = child.get('value-list-name')
334 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
336 elif child.tag == 'switch':
337 field_name = child.get('name')
338 # construct the switch type name from the parent type and the field name
339 field_type = self.name + (field_name,)
340 type = SwitchType(field_type, child, *self.lenfield_parent)
342 type.make_member_of(module, self, field_type, field_name, visible, True, False)
345 elif child.tag == 'fd':
346 fd_name = child.get('name')
347 type = module.get_type('INT32')
348 type.make_fd_of(module, self, fd_name)
354 # Get the full type name for the field
355 field_type = module.get_type_name(fkey)
356 # Add the field to ourself
357 type.make_member_of(module, self, field_type, field_name, visible, True, False, enum)
358 # Recursively resolve the type (could be another structure, list)
361 self.calc_size() # Figure out how big we are
366 for m in self.fields:
369 if m.type.fixed_size():
370 self.size = self.size + (m.type.size * m.type.nmemb)
375 def fixed_size(self):
376 for m in self.fields:
377 if not m.type.fixed_size():
381 class SwitchType(ComplexType):
383 Derived class which represents a List of Items.
386 bitcases is an array of Bitcase objects describing the list items
389 def __init__(self, name, elt, *parents):
390 ComplexType.__init__(self, name, elt)
391 self.parents = parents
392 # FIXME: switch cannot store lenfields, so it should just delegate the parents
393 self.lenfield_parent = list(parents) + [self]
394 # self.fields contains all possible fields collected from the Bitcase objects,
395 # whereas self.items contains the Bitcase objects themselves
398 self.is_switch = True
400 self.expr = Expression(elts[0] if len(elts) else elt, self)
402 def resolve(self, module):
406 parents = list(self.parents) + [self]
408 # Resolve all of our field datatypes.
409 for index, child in enumerate(list(self.elt)):
410 if child.tag == 'bitcase' or child.tag == 'case':
411 field_name = child.get('name')
412 if field_name is None:
413 field_type = self.name + ('%s%d' % ( child.tag, index ),)
415 field_type = self.name + (field_name,)
417 # use self.parent to indicate anchestor,
418 # as switch does not contain named fields itself
419 if child.tag == 'bitcase':
420 type = BitcaseType(index, field_type, child, *parents)
422 type = CaseType(index, field_type, child, *parents)
424 # construct the switch type name from the parent type and the field name
425 if field_name is None:
426 type.has_name = False
427 # Get the full type name for the field
428 field_type = type.name
431 # add the field to ourself
432 type.make_member_of(module, self, field_type, field_name, visible, True, False)
434 # recursively resolve the type (could be another structure, list)
437 for new_field in type.fields:
438 # We dump the _placeholder_byte if any fields are added.
439 for (idx, field) in enumerate(self.fields):
440 if field == _placeholder_byte:
441 self.fields[idx] = new_field
444 if False == inserted:
445 self.fields.append(new_field)
447 self.calc_size() # Figure out how big we are
450 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
451 if not self.fixed_size():
452 # We need a length field.
453 # Ask our Expression object for it's name, type, and whether it's on the wire.
454 lenfid = self.expr.lenfield_type
455 lenfield_name = self.expr.lenfield_name
456 lenwire = self.expr.lenwire
459 # See if the length field is already in the structure.
460 for parent in self.parents:
461 for field in parent.fields:
462 if field.field_name == lenfield_name:
465 # It isn't, so we need to add it to the structure ourself.
467 type = module.get_type(lenfid)
468 lenfield_type = module.get_type_name(lenfid)
469 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
471 # Add ourself to the structure by calling our original method.
472 Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
474 # size for switch can only be calculated at runtime
478 # note: switch is _always_ of variable size, but we indicate here wether
479 # it contains elements that are variable-sized themselves
480 def fixed_size(self):
482 # for m in self.fields:
483 # if not m.type.fixed_size():
488 class Struct(ComplexType):
490 Derived class representing a struct data type.
492 out = __main__.output['struct']
495 class Union(ComplexType):
497 Derived class representing a union data type.
499 def __init__(self, name, elt):
500 ComplexType.__init__(self, name, elt)
503 out = __main__.output['union']
506 class CaseOrBitcaseType(ComplexType):
508 Derived class representing a case or bitcase.
510 def __init__(self, index, name, elt, *parent):
515 if elt.tag == 'enumref':
516 self.expr.append(Expression(elt, self))
519 ComplexType.__init__(self, name, fields)
522 self.lenfield_parent = list(parent) + [self]
523 self.parents = list(parent)
524 self.is_case_or_bitcase = True
526 def make_member_of(self, module, switch_type, field_type, field_name, visible, wire, auto, enum=None):
528 register BitcaseType with the corresponding SwitchType
530 module is the global module object.
531 complex_type is the structure object.
532 see Field for the meaning of the other parameters.
534 new_field = Field(self, field_type, field_name, visible, wire, auto, enum)
536 # We dump the _placeholder_byte if any bitcases are added.
537 for (idx, field) in enumerate(switch_type.bitcases):
538 if field == _placeholder_byte:
539 switch_type.bitcases[idx] = new_field
542 switch_type.bitcases.append(new_field)
544 def resolve(self, module):
549 e.resolve(module, self.parents+[self])
551 # Resolve the bitcase expression
552 ComplexType.resolve(self, module)
555 class BitcaseType(CaseOrBitcaseType):
557 Derived class representing a bitcase.
559 def __init__(self, index, name, elt, *parent):
560 CaseOrBitcaseType.__init__(self, index, name, elt, *parent)
561 self.is_bitcase = True
563 class CaseType(CaseOrBitcaseType):
565 Derived class representing a case.
567 def __init__(self, index, name, elt, *parent):
568 CaseOrBitcaseType.__init__(self, index, name, elt, *parent)
572 class Reply(ComplexType):
574 Derived class representing a reply. Only found as a field of Request.
576 def __init__(self, name, elt):
577 ComplexType.__init__(self, name, elt)
581 for child in list(elt):
582 if child.tag == 'doc':
583 self.doc = Doc(name, child)
585 def resolve(self, module):
590 # Add the automatic protocol fields
591 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
592 self.fields.append(_placeholder_byte)
593 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
594 self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
595 ComplexType.resolve(self, module)
598 class Request(ComplexType):
600 Derived class representing a request.
603 reply contains the reply datatype or None for void requests.
604 opcode contains the request number.
606 def __init__(self, name, elt):
607 ComplexType.__init__(self, name, elt)
610 self.opcode = elt.get('opcode')
612 for child in list(elt):
613 if child.tag == 'reply':
614 self.reply = Reply(name, child)
615 if child.tag == 'doc':
616 self.doc = Doc(name, child)
618 def resolve(self, module):
621 # Add the automatic protocol fields
622 if module.namespace.is_ext:
623 self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
624 self.fields.append(Field(tcard8, tcard8.name, 'minor_opcode', False, True, True))
625 self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
626 ComplexType.resolve(self, module)
628 self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
629 self.fields.append(_placeholder_byte)
630 self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
631 ComplexType.resolve(self, module)
634 self.reply.resolve(module)
636 out = __main__.output['request']
639 class Event(ComplexType):
641 Derived class representing an event data type.
644 opcodes is a dictionary of name -> opcode number, for eventcopies.
646 def __init__(self, name, elt):
647 ComplexType.__init__(self, name, elt)
650 self.has_seq = not bool(elt.get('no-sequence-number'))
652 self.is_ge_event = bool(elt.get('xge'))
655 for item in list(elt):
656 if item.tag == 'doc':
657 self.doc = Doc(name, item)
659 def add_opcode(self, opcode, name, main):
660 self.opcodes[name] = opcode
664 def resolve(self, module):
665 def add_event_header():
666 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
668 self.fields.append(_placeholder_byte)
669 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
671 def add_ge_event_header():
672 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
673 self.fields.append(Field(tcard8, tcard8.name, 'extension', False, True, True))
674 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
675 self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
676 self.fields.append(Field(tcard16, tcard16.name, 'event_type', False, True, True))
681 # Add the automatic protocol fields
683 add_ge_event_header()
687 ComplexType.resolve(self, module)
689 out = __main__.output['event']
692 class Error(ComplexType):
694 Derived class representing an error data type.
697 opcodes is a dictionary of name -> opcode number, for errorcopies.
699 def __init__(self, name, elt):
700 ComplexType.__init__(self, name, elt)
703 def add_opcode(self, opcode, name, main):
704 self.opcodes[name] = opcode
708 def resolve(self, module):
712 # Add the automatic protocol fields
713 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
714 self.fields.append(Field(tcard8, tcard8.name, 'error_code', False, True, True))
715 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
716 ComplexType.resolve(self, module)
718 out = __main__.output['error']
723 Class representing a <doc> tag.
725 def __init__(self, name, elt):
727 self.description = None
728 self.brief = 'BRIEF DESCRIPTION MISSING'
734 for child in list(elt):
735 text = child.text if child.text else ''
736 if child.tag == 'description':
737 self.description = text.strip()
738 if child.tag == 'brief':
739 self.brief = text.strip()
740 if child.tag == 'field':
741 self.fields[child.get('name')] = text.strip()
742 if child.tag == 'error':
743 self.errors[child.get('type')] = text.strip()
744 if child.tag == 'see':
745 self.see[child.get('name')] = child.get('type')
746 if child.tag == 'example':
747 self.example = text.strip()
751 _placeholder_byte = Field(PadType(None), tcard8.name, 'pad0', False, True, False)