diff options
-rw-r--r-- | xcbgen/xtypes.py | 149 |
1 files changed, 147 insertions, 2 deletions
diff --git a/xcbgen/xtypes.py b/xcbgen/xtypes.py index 32ba8c1..046513e 100644 --- a/xcbgen/xtypes.py +++ b/xcbgen/xtypes.py @@ -32,6 +32,7 @@ class Type(object): self.is_reply = False self.is_union = False self.is_pad = False + self.is_switch = False def resolve(self, module): ''' @@ -73,6 +74,7 @@ class Type(object): complex_type.fields.append(new_field) + class SimpleType(Type): ''' Derived class which represents a cardinal type like CARD32 or char. @@ -156,7 +158,7 @@ class ListType(Type): Type.__init__(self, member.name) self.is_list = True self.member = member - self.parent = parent + self.parent = list(parent) if elt.tag == 'list': elts = list(elt) @@ -195,6 +197,7 @@ class ListType(Type): if self.resolved: return self.member.resolve(module) + self.expr.resolve(module, self.parent) # Find my length field again. We need the actual Field object in the expr. # This is needed because we might have added it ourself above. @@ -204,7 +207,7 @@ class ListType(Type): if field.field_name == self.expr.lenfield_name and field.wire: self.expr.lenfield = field break - + self.resolved = True def fixed_size(self): @@ -303,6 +306,15 @@ class ComplexType(Type): fkey = 'CARD32' type = ListType(child, module.get_type(fkey), *self.lenfield_parent) visible = True + elif child.tag == 'switch': + field_name = child.get('name') + # construct the switch type name from the parent type and the field name + field_type = self.name + (field_name,) + type = SwitchType(field_type, child, *self.lenfield_parent) + visible = True + type.make_member_of(module, self, field_type, field_name, visible, True, False) + type.resolve(module) + continue else: # Hit this on Reply continue @@ -334,6 +346,100 @@ class ComplexType(Type): return False return True +class SwitchType(ComplexType): + ''' + Derived class which represents a List of Items. + + Public fields added: + bitcases is an array of Bitcase objects describing the list items + ''' + + def __init__(self, name, elt, *parents): + ComplexType.__init__(self, name, elt) + self.parent = parents + # FIXME: switch cannot store lenfields, so it should just delegate the parents + self.lenfield_parent = list(parents) + [self] + # self.fields contains all possible fields collected from the Bitcase objects, + # whereas self.items contains the Bitcase objects themselves + self.bitcases = [] + + self.is_switch = True + elts = list(elt) + self.expr = Expression(elts[0] if len(elts) else elt, self) + + def resolve(self, module): + if self.resolved: + return +# pads = 0 + + # Resolve all of our field datatypes. + for index, child in enumerate(list(self.elt)): + if child.tag == 'bitcase': + # use self.parent to indicate anchestor, + # as switch does not contain named fields itself + type = BitcaseType(index, child, *self.parent) + visible = True + + # Get the full type name for the field + field_type = type.name + + # add the field to ourself + type.make_member_of(module, self, field_type, index, visible, True, False) + + # recursively resolve the type (could be another structure, list) + type.resolve(module) + inserted = False + for new_field in type.fields: + # We dump the _placeholder_byte if any fields are added. + for (idx, field) in enumerate(self.fields): + if field == _placeholder_byte: + self.fields[idx] = new_field + inserted = True + break + if False == inserted: + self.fields.append(new_field) + + self.calc_size() # Figure out how big we are + self.resolved = True + + # FIXME: really necessary for Switch?? + def make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto): + if not self.fixed_size(): + # We need a length field. + # Ask our Expression object for it's name, type, and whether it's on the wire. + lenfid = self.expr.lenfield_type + lenfield_name = self.expr.lenfield_name + lenwire = self.expr.lenwire + needlen = True + + # See if the length field is already in the structure. + for parent in self.parent: + for field in parent.fields: + if field.field_name == lenfield_name: + needlen = False + + # It isn't, so we need to add it to the structure ourself. + if needlen: + type = module.get_type(lenfid) + lenfield_type = module.get_type_name(lenfid) + type.make_member_of(module, complex_type, lenfield_type, lenfield_name, True, lenwire, False) + + # Add ourself to the structure by calling our original method. + Type.make_member_of(self, module, complex_type, field_type, field_name, visible, wire, auto) + + # size for switch can only be calculated at runtime + def calc_size(self): + pass + + # note: switch is _always_ of variable size, but we indicate here wether + # it contains elements that are variable-sized themselves + def fixed_size(self): + return False +# for m in self.fields: +# if not m.type.fixed_size(): +# return False +# return True + class Struct(ComplexType): ''' @@ -353,6 +459,45 @@ class Union(ComplexType): out = __main__.output['union'] +class BitcaseType(ComplexType): + ''' + Derived class representing a struct data type. + ''' + def __init__(self, index, elt, *parent): + elts = list(elt) + self.expr = Expression(elts[0] if len(elts) else elt, self) + ComplexType.__init__(self, ('bitcase%d' % index,), elts[1:]) + self.lenfield_parent = list(parent) + [self] + self.parents = list(parent) + + def make_member_of(self, module, switch_type, field_type, field_name, visible, wire, auto): + ''' + register BitcaseType with the corresponding SwitchType + + module is the global module object. + complex_type is the structure object. + see Field for the meaning of the other parameters. + ''' + new_field = Field(self, field_type, field_name, visible, wire, auto) + + # We dump the _placeholder_byte if any bitcases are added. + for (idx, field) in enumerate(switch_type.bitcases): + if field == _placeholder_byte: + switch_type.bitcases[idx] = new_field + return + + switch_type.bitcases.append(new_field) + + def resolve(self, module): + if self.resolved: + return + + self.expr.resolve(module, self.parents+[self]) + + # Resolve the bitcase expression + ComplexType.resolve(self, module) + + class Reply(ComplexType): ''' Derived class representing a reply. Only found as a field of Request. |