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 tcard64 = SimpleType(('uint64_t',), 8)
107 tint8 = SimpleType(('int8_t',), 1)
108 tint16 = SimpleType(('int16_t',), 2)
109 tint32 = SimpleType(('int32_t',), 4)
110 tint64 = SimpleType(('int64_t',), 8)
111 tchar = SimpleType(('char',), 1)
112 tfloat = SimpleType(('float',), 4)
113 tdouble = SimpleType(('double',), 8)
116 class Enum(SimpleType):
118 Derived class which represents an enum. Fixed-size.
121 values contains a list of (name, value) tuples. value is empty, or a number.
122 bits contains a list of (name, bitnum) tuples. items only appear if specified as a bit. bitnum is a number.
124 def __init__(self, name, elt):
125 SimpleType.__init__(self, name, 4)
129 for item in list(elt):
130 if item.tag == 'doc':
131 self.doc = Doc(name, item)
133 # First check if we're using a default value
134 if len(list(item)) == 0:
135 self.values.append((item.get('name'), ''))
138 # An explicit value or bit was specified.
139 value = list(item)[0]
140 if value.tag == 'value':
141 self.values.append((item.get('name'), value.text))
142 elif value.tag == 'bit':
143 self.values.append((item.get('name'), '%u' % (1 << int(value.text, 0))))
144 self.bits.append((item.get('name'), value.text))
146 def resolve(self, module):
149 def fixed_size(self):
152 out = __main__.output['enum']
155 class ListType(Type):
157 Derived class which represents a list of some other datatype. Fixed- or variable-sized.
160 member is the datatype of the list elements.
161 parent is the structure type containing the list.
162 expr is an Expression object containing the length information, for variable-sized lists.
164 def __init__(self, elt, member, *parent):
165 Type.__init__(self, member.name)
168 self.parents = list(parent)
170 if elt.tag == 'list':
172 self.expr = Expression(elts[0] if len(elts) else elt, self)
173 elif elt.tag == 'valueparam':
174 self.expr = Expression(elt, self)
176 self.size = member.size if member.fixed_size() else None
177 self.nmemb = self.expr.nmemb if self.expr.fixed_size() else None
179 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
180 if not self.fixed_size():
181 # We need a length field.
182 # Ask our Expression object for it's name, type, and whether it's on the wire.
183 lenfid = self.expr.lenfield_type
184 lenfield_name = self.expr.lenfield_name
185 lenwire = self.expr.lenwire
188 # See if the length field is already in the structure.
189 for parent in self.parents:
190 for field in parent.fields:
191 if field.field_name == lenfield_name:
194 # It isn't, so we need to add it to the structure ourself.
196 type = module.get_type(lenfid)
197 lenfield_type = module.get_type_name(lenfid)
198 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
200 # Add ourself to the structure by calling our original method.
201 Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
203 def resolve(self, module):
206 self.member.resolve(module)
207 self.expr.resolve(module, self.parents)
209 # Find my length field again. We need the actual Field object in the expr.
210 # This is needed because we might have added it ourself above.
211 if not self.fixed_size():
212 for parent in self.parents:
213 for field in parent.fields:
214 if field.field_name == self.expr.lenfield_name and field.wire:
215 self.expr.lenfield = field
220 def fixed_size(self):
221 return self.member.fixed_size() and self.expr.fixed_size()
223 class ExprType(Type):
225 Derived class which represents an exprfield. Fixed size.
228 expr is an Expression object containing the value of the field.
230 def __init__(self, elt, member, *parents):
231 Type.__init__(self, member.name)
234 self.parents = parents
236 self.expr = Expression(list(elt)[0], self)
238 self.size = member.size
241 def resolve(self, module):
244 self.member.resolve(module)
247 def fixed_size(self):
252 Derived class which represents a padding field.
254 def __init__(self, elt):
255 Type.__init__(self, tcard8.name)
258 self.nmemb = 1 if (elt == None) else int(elt.get('bytes'), 0)
260 def resolve(self, module):
263 def fixed_size(self):
267 class ComplexType(Type):
269 Derived class which represents a structure. Base type for all structure types.
272 fields is an array of Field objects describing the structure fields.
274 def __init__(self, name, elt):
275 Type.__init__(self, name)
276 self.is_container = True
281 self.lenfield_parent = [self]
283 def resolve(self, module):
289 # Resolve all of our field datatypes.
290 for child in list(self.elt):
291 if child.tag == 'pad':
292 field_name = 'pad' + str(pads)
294 type = PadType(child)
297 elif child.tag == 'field':
298 field_name = child.get('name')
299 enum = child.get('enum')
300 fkey = child.get('type')
301 type = module.get_type(fkey)
303 elif child.tag == 'exprfield':
304 field_name = child.get('name')
305 fkey = child.get('type')
306 type = ExprType(child, module.get_type(fkey), *self.lenfield_parent)
308 elif child.tag == 'list':
309 field_name = child.get('name')
310 fkey = child.get('type')
311 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
313 elif child.tag == 'valueparam':
314 field_name = child.get('value-list-name')
316 type = ListType(child, module.get_type(fkey), *self.lenfield_parent)
318 elif child.tag == 'switch':
319 field_name = child.get('name')
320 # construct the switch type name from the parent type and the field name
321 field_type = self.name + (field_name,)
322 type = SwitchType(field_type, child, *self.lenfield_parent)
324 type.make_member_of(module, self, field_type, field_name, visible, True, False)
331 # Get the full type name for the field
332 field_type = module.get_type_name(fkey)
333 # Add the field to ourself
334 type.make_member_of(module, self, field_type, field_name, visible, True, False, enum)
335 # Recursively resolve the type (could be another structure, list)
338 self.calc_size() # Figure out how big we are
343 for m in self.fields:
346 if m.type.fixed_size():
347 self.size = self.size + (m.type.size * m.type.nmemb)
352 def fixed_size(self):
353 for m in self.fields:
354 if not m.type.fixed_size():
358 class SwitchType(ComplexType):
360 Derived class which represents a List of Items.
363 bitcases is an array of Bitcase objects describing the list items
366 def __init__(self, name, elt, *parents):
367 ComplexType.__init__(self, name, elt)
368 self.parents = parents
369 # FIXME: switch cannot store lenfields, so it should just delegate the parents
370 self.lenfield_parent = list(parents) + [self]
371 # self.fields contains all possible fields collected from the Bitcase objects,
372 # whereas self.items contains the Bitcase objects themselves
375 self.is_switch = True
377 self.expr = Expression(elts[0] if len(elts) else elt, self)
379 def resolve(self, module):
384 parents = list(self.parents) + [self]
386 # Resolve all of our field datatypes.
387 for index, child in enumerate(list(self.elt)):
388 if child.tag == 'bitcase':
389 field_name = child.get('name')
390 if field_name is None:
391 field_type = self.name + ('bitcase%d' % index,)
393 field_type = self.name + (field_name,)
395 # use self.parent to indicate anchestor,
396 # as switch does not contain named fields itself
397 type = BitcaseType(index, field_type, child, *parents)
398 # construct the switch type name from the parent type and the field name
399 if field_name is None:
400 type.has_name = False
401 # Get the full type name for the field
402 field_type = type.name
405 # add the field to ourself
406 type.make_member_of(module, self, field_type, field_name, visible, True, False)
408 # recursively resolve the type (could be another structure, list)
411 for new_field in type.fields:
412 # We dump the _placeholder_byte if any fields are added.
413 for (idx, field) in enumerate(self.fields):
414 if field == _placeholder_byte:
415 self.fields[idx] = new_field
418 if False == inserted:
419 self.fields.append(new_field)
421 self.calc_size() # Figure out how big we are
424 def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum=None):
425 if not self.fixed_size():
426 # We need a length field.
427 # Ask our Expression object for it's name, type, and whether it's on the wire.
428 lenfid = self.expr.lenfield_type
429 lenfield_name = self.expr.lenfield_name
430 lenwire = self.expr.lenwire
433 # See if the length field is already in the structure.
434 for parent in self.parents:
435 for field in parent.fields:
436 if field.field_name == lenfield_name:
439 # It isn't, so we need to add it to the structure ourself.
441 type = module.get_type(lenfid)
442 lenfield_type = module.get_type_name(lenfid)
443 type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False, enum)
445 # Add ourself to the structure by calling our original method.
446 Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto, enum)
448 # size for switch can only be calculated at runtime
452 # note: switch is _always_ of variable size, but we indicate here wether
453 # it contains elements that are variable-sized themselves
454 def fixed_size(self):
456 # for m in self.fields:
457 # if not m.type.fixed_size():
462 class Struct(ComplexType):
464 Derived class representing a struct data type.
466 out = __main__.output['struct']
469 class Union(ComplexType):
471 Derived class representing a union data type.
473 def __init__(self, name, elt):
474 ComplexType.__init__(self, name, elt)
477 out = __main__.output['union']
480 class BitcaseType(ComplexType):
482 Derived class representing a struct data type.
484 def __init__(self, index, name, elt, *parent):
489 if elt.tag == 'enumref':
490 self.expr.append(Expression(elt, self))
493 ComplexType.__init__(self, name, fields)
496 self.lenfield_parent = list(parent) + [self]
497 self.parents = list(parent)
498 self.is_bitcase = True
500 def make_member_of(self, module, switch_type, field_type, field_name, visible, wire, auto, enum=None):
502 register BitcaseType with the corresponding SwitchType
504 module is the global module object.
505 complex_type is the structure object.
506 see Field for the meaning of the other parameters.
508 new_field = Field(self, field_type, field_name, visible, wire, auto, enum)
510 # We dump the _placeholder_byte if any bitcases are added.
511 for (idx, field) in enumerate(switch_type.bitcases):
512 if field == _placeholder_byte:
513 switch_type.bitcases[idx] = new_field
516 switch_type.bitcases.append(new_field)
518 def resolve(self, module):
523 e.resolve(module, self.parents+[self])
525 # Resolve the bitcase expression
526 ComplexType.resolve(self, module)
529 class Reply(ComplexType):
531 Derived class representing a reply. Only found as a field of Request.
533 def __init__(self, name, elt):
534 ComplexType.__init__(self, name, elt)
538 for child in list(elt):
539 if child.tag == 'doc':
540 self.doc = Doc(name, child)
542 def resolve(self, module):
545 # Add the automatic protocol fields
546 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
547 self.fields.append(_placeholder_byte)
548 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
549 self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
550 ComplexType.resolve(self, module)
553 class Request(ComplexType):
555 Derived class representing a request.
558 reply contains the reply datatype or None for void requests.
559 opcode contains the request number.
561 def __init__(self, name, elt):
562 ComplexType.__init__(self, name, elt)
565 self.opcode = elt.get('opcode')
567 for child in list(elt):
568 if child.tag == 'reply':
569 self.reply = Reply(name, child)
570 if child.tag == 'doc':
571 self.doc = Doc(name, child)
573 def resolve(self, module):
576 # Add the automatic protocol fields
577 if module.namespace.is_ext:
578 self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
579 self.fields.append(Field(tcard8, tcard8.name, 'minor_opcode', False, True, True))
580 self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
581 ComplexType.resolve(self, module)
583 self.fields.append(Field(tcard8, tcard8.name, 'major_opcode', False, True, True))
584 self.fields.append(_placeholder_byte)
585 self.fields.append(Field(tcard16, tcard16.name, 'length', False, True, True))
586 ComplexType.resolve(self, module)
589 self.reply.resolve(module)
591 out = __main__.output['request']
594 class Event(ComplexType):
596 Derived class representing an event data type.
599 opcodes is a dictionary of name -> opcode number, for eventcopies.
601 def __init__(self, name, elt):
602 ComplexType.__init__(self, name, elt)
605 self.has_seq = not bool(elt.get('no-sequence-number'))
607 self.is_ge_event = bool(elt.get('xge'))
610 for item in list(elt):
611 if item.tag == 'doc':
612 self.doc = Doc(name, item)
614 def add_opcode(self, opcode, name, main):
615 self.opcodes[name] = opcode
619 def resolve(self, module):
620 def add_event_header():
621 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
623 self.fields.append(_placeholder_byte)
624 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
626 def add_ge_event_header():
627 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
628 self.fields.append(Field(tcard8, tcard8.name, 'extension', False, True, True))
629 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
630 self.fields.append(Field(tcard32, tcard32.name, 'length', False, True, True))
631 self.fields.append(Field(tcard16, tcard16.name, 'event_type', False, True, True))
636 # Add the automatic protocol fields
638 add_ge_event_header()
642 ComplexType.resolve(self, module)
644 out = __main__.output['event']
647 class Error(ComplexType):
649 Derived class representing an error data type.
652 opcodes is a dictionary of name -> opcode number, for errorcopies.
654 def __init__(self, name, elt):
655 ComplexType.__init__(self, name, elt)
658 def add_opcode(self, opcode, name, main):
659 self.opcodes[name] = opcode
663 def resolve(self, module):
667 # Add the automatic protocol fields
668 self.fields.append(Field(tcard8, tcard8.name, 'response_type', False, True, True))
669 self.fields.append(Field(tcard8, tcard8.name, 'error_code', False, True, True))
670 self.fields.append(Field(tcard16, tcard16.name, 'sequence', False, True, True))
671 ComplexType.resolve(self, module)
673 out = __main__.output['error']
678 Class representing a <doc> tag.
680 def __init__(self, name, elt):
682 self.description = None
683 self.brief = 'BRIEF DESCRIPTION MISSING'
689 for child in list(elt):
690 text = child.text if child.text else ''
691 if child.tag == 'description':
692 self.description = text.strip()
693 if child.tag == 'brief':
694 self.brief = text.strip()
695 if child.tag == 'field':
696 self.fields[child.get('name')] = text.strip()
697 if child.tag == 'error':
698 self.errors[child.get('type')] = text.strip()
699 if child.tag == 'see':
700 self.see[child.get('name')] = child.get('type')
701 if child.tag == 'example':
702 self.example = text.strip()
706 _placeholder_byte = Field(PadType(None), tcard8.name, 'pad0', False, True, False)