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)
79 new_field.parent = complex_type
81 def make_fd_of(self, module, complex_type, fd_name):
83 Method for making a fd member of a structure.
85 new_fd = Field(self, module.get_type_name('INT32'), fd_name, True, False, False, None, True)
86 # We dump the _placeholder_byte if any fields are added.
87 for (idx, field) in enumerate(complex_type.fields):
88 if field == _placeholder_byte:
89 complex_type.fields[idx] = new_fd
92 complex_type.fields.append(new_fd)
94 class SimpleType(Type):
96 Derived class which represents a cardinal type like CARD32 or char.
97 Any type which is typedef'ed to cardinal will be one of these.
102 def __init__(self, name, size):
103 Type.__init__(self, name)
104 self.is_simple = True
108 def resolve(self, module):
111 def fixed_size(self):
114 out = __main__.output['simple']
117 # Cardinal datatype globals. See module __init__ method.
118 tcard8 = SimpleType(('uint8_t',), 1)
119 tcard16 = SimpleType(('uint16_t',), 2)
120 tcard32 = SimpleType(('uint32_t',), 4)
121 tcard64 = SimpleType(('uint64_t',), 8)
122 tint8 = SimpleType(('int8_t',), 1)
123 tint16 = SimpleType(('int16_t',), 2)
124 tint32 = SimpleType(('int32_t',), 4)
125 tint64 = SimpleType(('int64_t',), 8)
126 tchar = SimpleType(('char',), 1)
127 tfloat = SimpleType(('float',), 4)
128 tdouble = SimpleType(('double',), 8)
131 class Enum(SimpleType):
133 Derived class which represents an enum. Fixed-size.
136 values contains a list of (name, value) tuples. value is empty, or a number.
137 bits contains a list of (name, bitnum) tuples. items only appear if specified as a bit. bitnum is a number.
139 def __init__(self, name, elt):
140 SimpleType.__init__(self, name, 4)
144 for item in list(elt):
145 if item.tag == 'doc':
146 self.doc = Doc(name, item)
148 # First check if we're using a default value
149 if len(list(item)) == 0:
150 self.values.append((item.get('name'), ''))
153 # An explicit value or bit was specified.
154 value = list(item)[0]
155 if value.tag == 'value':
156 self.values.append((item.get('name'), value.text))
157 elif value.tag == 'bit':
158 self.values.append((item.get('name'), '%u' % (1 << int(value.text, 0))))
159 self.bits.append((item.get('name'), value.text))
161 def resolve(self, module):
164 def fixed_size(self):
167 out = __main__.output['enum']
170 class ListType(Type):
172 Derived class which represents a list of some other datatype. Fixed- or variable-sized.
175 member is the datatype of the list elements.
176 parent is the structure type containing the list.
177 expr is an Expression object containing the length information, for variable-sized lists.
179 def __init__(self, elt, member, *parent):
180 Type.__init__(self, member.name)
183 self.parents = list(parent)
185 if elt.tag == 'list':
187 self.expr = Expression(elts[0] if len(elts) else elt, self)
188 elif elt.tag == 'valueparam':
189 self.expr = Expression(elt, self)
191 self.size = member.size if member.fixed_size() else None
192 self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None
194 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
195 if not self.fixed_size():
196 # We need a length field.
197 # Ask our Expression object for it's name, type, and whether it's on the wire.
198 lenfid = self.expr.lenfield_type
199 lenfield_name = self.expr.lenfield_name
200 lenwire = self.expr.lenwire
203 # See if the length field is already in the structure.
204 for parent in self.parents:
205 for field in parent.fields:
206 if field.field_name == lenfield_name:
209 # It isn't, so we need to add it to the structure ourself.
211 type = module.get_type(lenfid)
212 lenfield_type = module.get_type_name(lenfid)
213 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
215 # Add ourself to the structure by calling our original method.
216 Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
218 def resolve(self, module):
221 self.member.resolve(module)
222 self.expr.resolve(module, self.parents)
224 # Find my length field again. We need the actual Field object in the expr.
225 # This is needed because we might have added it ourself above.
226 if not self.fixed_size():
227 for parent in self.parents:
228 for field in parent.fields:
229 if field.field_name == self.expr.lenfield_name and field.wire:
230 self.expr.lenfield = field
235 def fixed_size(self):
236 return self.member.fixed_size() and self.expr.fixed_size()
238 class ExprType(Type):
240 Derived class which represents an exprfield. Fixed size.
243 expr is an Expression object containing the value of the field.
245 def __init__(self, elt, member, *parents):
246 Type.__init__(self, member.name)
249 self.parents = parents
251 self.expr = Expression(list(elt)[0], self)
253 self.size = member.size
256 def resolve(self, module):
259 self.member.resolve(module)
262 def fixed_size(self):
267 Derived class which represents a padding field.
269 def __init__(self, elt):
270 Type.__init__(self, tcard8.name)
276 self.nmemb = int(elt.get('bytes', "1"), 0)
277 self.align = int(elt.get('align', "1"), 0)
279 def resolve(self, module):
282 def fixed_size(self):
283 return self.align <= 1
286 class ComplexType(Type):
288 Derived class which represents a structure. Base type for all structure types.
291 fields is an array of Field objects describing the structure fields.
293 def __init__(self, name, elt):
294 Type.__init__(self, name)
295 self.is_container = True
300 self.lenfield_parent = [self]
303 def resolve(self, module):
308 # Resolve all of our field datatypes.
309 for child in list(self.elt):
310 if child.tag == 'pad':
311 field_name = 'pad' + str(module.pads)
313 type = PadType(child)
314 module.pads = module.pads + 1
316 elif child.tag == 'field':
317 field_name = child.get('name')
318 enum = child.get('enum')
319 fkey = child.get('type')
320 type = module.get_type(fkey)
322 elif child.tag == 'exprfield':
323 field_name = child.get('name')
324 fkey = child.get('type')
325 type = ExprType(child, module.get_type(fkey), *self.lenfield_parent)
327 elif child.tag == 'list':
328 field_name = child.get('name')
329 fkey = child.get('type')
330 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
332 elif child.tag == 'valueparam':
333 field_name = child.get('value-list-name')
335 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
337 elif child.tag == 'switch':
338 field_name = child.get('name')
339 # construct the switch type name from the parent type and the field name
340 field_type = self.name + (field_name,)
341 type = SwitchType(field_type, child, *self.lenfield_parent)
343 type.make_member_of(module, self, field_type, field_name, visible, True, False)
346 elif child.tag == 'fd':
347 fd_name = child.get('name')
348 type = module.get_type('INT32')
349 type.make_fd_of(module, self, fd_name)
355 # Get the full type name for the field
356 field_type = module.get_type_name(fkey)
357 # Add the field to ourself
358 type.make_member_of(module, self, field_type, field_name, visible, True, False, enum)
359 # Recursively resolve the type (could be another structure, list)
362 self.calc_size() # Figure out how big we are
367 for m in self.fields:
370 if m.type.fixed_size():
371 self.size = self.size + (m.type.size * m.type.nmemb)
376 def fixed_size(self):
377 for m in self.fields:
378 if not m.type.fixed_size():
382 class SwitchType(ComplexType):
384 Derived class which represents a List of Items.
387 bitcases is an array of Bitcase objects describing the list items
390 def __init__(self, name, elt, *parents):
391 ComplexType.__init__(self, name, elt)
392 self.parents = parents
393 # FIXME: switch cannot store lenfields, so it should just delegate the parents
394 self.lenfield_parent = list(parents) + [self]
395 # self.fields contains all possible fields collected from the Bitcase objects,
396 # whereas self.items contains the Bitcase objects themselves
399 self.is_switch = True
401 self.expr = Expression(elts[0] if len(elts) else elt, self)
403 def resolve(self, module):
407 parents = list(self.parents) + [self]
409 # Resolve all of our field datatypes.
410 for index, child in enumerate(list(self.elt)):
411 if child.tag == 'bitcase' or child.tag == 'case':
412 field_name = child.get('name')
413 if field_name is None:
414 field_type = self.name + ('%s%d' % ( child.tag, index ),)
416 field_type = self.name + (field_name,)
418 # use self.parent to indicate anchestor,
419 # as switch does not contain named fields itself
420 if child.tag == 'bitcase':
421 type = BitcaseType(index, field_type, child, *parents)
423 type = CaseType(index, field_type, child, *parents)
425 # construct the switch type name from the parent type and the field name
426 if field_name is None:
427 type.has_name = False
428 # Get the full type name for the field
429 field_type = type.name
432 # add the field to ourself
433 type.make_member_of(module, self, field_type, field_name, visible, True, False)
435 # recursively resolve the type (could be another structure, list)
438 for new_field in type.fields:
439 # We dump the _placeholder_byte if any fields are added.
440 for (idx, field) in enumerate(self.fields):
441 if field == _placeholder_byte:
442 self.fields[idx] = new_field
445 if False == inserted:
446 self.fields.append(new_field)
448 self.calc_size() # Figure out how big we are
451 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
452 if not self.fixed_size():
453 # We need a length field.
454 # Ask our Expression object for it's name, type, and whether it's on the wire.
455 lenfid = self.expr.lenfield_type
456 lenfield_name = self.expr.lenfield_name
457 lenwire = self.expr.lenwire
460 # See if the length field is already in the structure.
461 for parent in self.parents:
462 for field in parent.fields:
463 if field.field_name == lenfield_name:
466 # It isn't, so we need to add it to the structure ourself.
468 type = module.get_type(lenfid)
469 lenfield_type = module.get_type_name(lenfid)
470 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
472 # Add ourself to the structure by calling our original method.
473 Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
475 # size for switch can only be calculated at runtime
479 # note: switch is _always_ of variable size, but we indicate here wether
480 # it contains elements that are variable-sized themselves
481 def fixed_size(self):
483 # for m in self.fields:
484 # if not m.type.fixed_size():
489 class Struct(ComplexType):
491 Derived class representing a struct data type.
493 out = __main__.output['struct']
496 class Union(ComplexType):
498 Derived class representing a union data type.
500 def __init__(self, name, elt):
501 ComplexType.__init__(self, name, elt)
504 out = __main__.output['union']
507 class CaseOrBitcaseType(ComplexType):
509 Derived class representing a case or bitcase.
511 def __init__(self, index, name, elt, *parent):
516 if elt.tag == 'enumref':
517 self.expr.append(Expression(elt, self))
520 ComplexType.__init__(self, name, fields)
523 self.lenfield_parent = list(parent) + [self]
524 self.parents = list(parent)
525 self.is_case_or_bitcase = True
527 def make_member_of(self, module, switch_type, field_type, field_name, visible, wire, auto, enum=None):
529 register BitcaseType with the corresponding SwitchType
531 module is the global module object.
532 complex_type is the structure object.
533 see Field for the meaning of the other parameters.
535 new_field = Field(self, field_type, field_name, visible, wire, auto, enum)
537 # We dump the _placeholder_byte if any bitcases are added.
538 for (idx, field) in enumerate(switch_type.bitcases):
539 if field == _placeholder_byte:
540 switch_type.bitcases[idx] = new_field
543 switch_type.bitcases.append(new_field)
545 def resolve(self, module):
550 e.resolve(module, self.parents+[self])
552 # Resolve the bitcase expression
553 ComplexType.resolve(self, module)
556 class BitcaseType(CaseOrBitcaseType):
558 Derived class representing a bitcase.
560 def __init__(self, index, name, elt, *parent):
561 CaseOrBitcaseType.__init__(self, index, name, elt, *parent)
562 self.is_bitcase = True
564 class CaseType(CaseOrBitcaseType):
566 Derived class representing a case.
568 def __init__(self, index, name, elt, *parent):
569 CaseOrBitcaseType.__init__(self, index, name, elt, *parent)
573 class Reply(ComplexType):
575 Derived class representing a reply. Only found as a field of Request.
577 def __init__(self, name, elt):
578 ComplexType.__init__(self, name, elt)
582 for child in list(elt):
583 if child.tag == 'doc':
584 self.doc = Doc(name, child)
586 def resolve(self, module):
591 # Add the automatic protocol fields
592 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
593 self.fields.append(_placeholder_byte)
594 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
595 self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
596 ComplexType.resolve(self, module)
599 class Request(ComplexType):
601 Derived class representing a request.
604 reply contains the reply datatype or None for void requests.
605 opcode contains the request number.
607 def __init__(self, name, elt):
608 ComplexType.__init__(self, name, elt)
611 self.opcode = elt.get('opcode')
613 for child in list(elt):
614 if child.tag == 'reply':
615 self.reply = Reply(name, child)
616 if child.tag == 'doc':
617 self.doc = Doc(name, child)
619 def resolve(self, module):
622 # Add the automatic protocol fields
623 if module.namespace.is_ext:
624 self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
625 self.fields.append(Field(tcard8, tcard8.name, 'minor_opcode', False, True, True))
626 self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
627 ComplexType.resolve(self, module)
629 self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
630 self.fields.append(_placeholder_byte)
631 self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
632 ComplexType.resolve(self, module)
635 self.reply.resolve(module)
637 out = __main__.output['request']
640 class Event(ComplexType):
642 Derived class representing an event data type.
645 opcodes is a dictionary of name -> opcode number, for eventcopies.
647 def __init__(self, name, elt):
648 ComplexType.__init__(self, name, elt)
651 self.has_seq = not bool(elt.get('no-sequence-number'))
653 self.is_ge_event = bool(elt.get('xge'))
656 for item in list(elt):
657 if item.tag == 'doc':
658 self.doc = Doc(name, item)
660 def add_opcode(self, opcode, name, main):
661 self.opcodes[name] = opcode
665 def resolve(self, module):
666 def add_event_header():
667 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
669 self.fields.append(_placeholder_byte)
670 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
672 def add_ge_event_header():
673 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
674 self.fields.append(Field(tcard8, tcard8.name, 'extension', False, True, True))
675 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
676 self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
677 self.fields.append(Field(tcard16, tcard16.name, 'event_type', False, True, True))
682 # Add the automatic protocol fields
684 add_ge_event_header()
688 ComplexType.resolve(self, module)
690 out = __main__.output['event']
693 class Error(ComplexType):
695 Derived class representing an error data type.
698 opcodes is a dictionary of name -> opcode number, for errorcopies.
700 def __init__(self, name, elt):
701 ComplexType.__init__(self, name, elt)
704 def add_opcode(self, opcode, name, main):
705 self.opcodes[name] = opcode
709 def resolve(self, module):
713 # Add the automatic protocol fields
714 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
715 self.fields.append(Field(tcard8, tcard8.name, 'error_code', False, True, True))
716 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
717 ComplexType.resolve(self, module)
719 out = __main__.output['error']
724 Class representing a <doc> tag.
726 def __init__(self, name, elt):
728 self.description = None
729 self.brief = 'BRIEF DESCRIPTION MISSING'
735 for child in list(elt):
736 text = child.text if child.text else ''
737 if child.tag == 'description':
738 self.description = text.strip()
739 if child.tag == 'brief':
740 self.brief = text.strip()
741 if child.tag == 'field':
742 self.fields[child.get('name')] = text.strip()
743 if child.tag == 'error':
744 self.errors[child.get('type')] = text.strip()
745 if child.tag == 'see':
746 self.see[child.get('name')] = child.get('type')
747 if child.tag == 'example':
748 self.example = text.strip()
752 _placeholder_byte = Field(PadType(None), tcard8.name, 'pad0', False, True, False)