2 This module contains helper classes for structure fields and length expressions.
6 Represents a field of a structure.
8 type is the datatype object for the field.
9 field_type is the name of the type (string tuple)
10 field_name is the name of the structure field.
11 visible is true iff the field should be in the request API.
12 wire is true iff the field should be in the request structure.
13 auto is true iff the field is on the wire but not in the request API (e.g. opcode)
14 enum is the enum name this field refers to, if any.
16 def __init__(self, type, field_type, field_name, visible, wire, auto, enum=None, isfd=False):
18 self.field_type = field_type
19 self.field_name = field_name
21 self.visible = visible
28 class Expression(object):
30 Represents a mathematical expression for a list length or exprfield.
33 op is the operation (text +,*,/,<<,~) or None.
34 lhs and rhs are the sub-Expressions if op is set.
35 lenfield_name is the name of the length field, or None for request lists.
36 lenfield is the Field object for the length field, or None.
37 bitfield is True if the length field is a bitmask instead of a number.
38 nmemb is the fixed size (value)of the expression, or None
40 def __init__(self, elt, parent):
45 self.lenfield_name = None
46 self.lenfield_type = None
47 self.lenfield_parent = None
56 self.contains_listelement_ref = False
59 # List going into a request, which has no length field (inferred by server)
60 self.lenfield_name = elt.get('name') + '_len'
61 self.lenfield_type = 'CARD32'
63 elif elt.tag == 'fieldref':
64 # Standard list with a fieldref
65 self.lenfield_name = elt.text
67 elif elt.tag == 'paramref':
68 self.lenfield_name = elt.text
69 self.lenfield_type = elt.get('type')
71 elif elt.tag == 'valueparam':
72 # Value-mask. The length bitmask is described by attributes.
73 self.lenfield_name = elt.get('value-mask-name')
74 self.lenfield_type = elt.get('value-mask-type')
79 # Op field. Need to recurse.
80 self.op = elt.get('op')
81 self.lhs = Expression(list(elt)[0], parent)
82 self.rhs = Expression(list(elt)[1], parent)
84 # Hopefully we don't have two separate length fields...
85 self.lenfield_name = self.lhs.lenfield_name
86 if self.lenfield_name == None:
87 self.lenfield_name = self.rhs.lenfield_name
89 elif elt.tag == 'unop':
90 # Op field. Need to recurse.
91 self.op = elt.get('op')
92 self.rhs = Expression(list(elt)[0], parent)
94 self.lenfield_name = self.rhs.lenfield_name
96 elif elt.tag == 'value':
98 self.nmemb = int(elt.text, 0)
100 elif elt.tag == 'popcount':
102 self.rhs = Expression(list(elt)[0], parent)
103 self.lenfield_name = self.rhs.lenfield_name
104 # xcb_popcount returns 'int' - handle the type in the language-specific part
106 elif elt.tag == 'enumref':
108 self.lenfield_name = (elt.get('ref'), elt.text)
110 elif elt.tag == 'sumof':
112 self.lenfield_name = elt.get('ref')
113 subexpressions = list(elt)
114 if len(subexpressions) > 0:
115 # sumof with a nested expression which is to be evaluated
116 # for each list-element in the context of that list-element.
117 # sumof then returns the sum of the results of these evaluations
118 self.rhs = Expression(subexpressions[0], parent)
120 elif elt.tag == 'listelement-ref':
121 # current list element inside iterating expressions such as sumof
122 self.op = 'listelement-ref'
123 self.contains_listelement_ref = True
127 raise Exception("undefined tag '%s'" % elt.tag)
129 def fixed_size(self):
130 return self.nmemb != None
132 def recursive_resolve_tasks(self, module, parents):
133 for subexpr in (self.lhs, self.rhs):
135 subexpr.recursive_resolve_tasks(module, parents)
136 self.contains_listelement_ref |= subexpr.contains_listelement_ref
138 def resolve(self, module, parents):
139 if self.op == 'enumref':
140 self.lenfield_type = module.get_type(self.lenfield_name[0])
141 self.lenfield_name = self.lenfield_name[1]
142 elif self.op == 'sumof':
143 # need to find the field with lenfield_name
144 for p in reversed(parents):
145 fields = dict([(f.field_name, f) for f in p.fields])
146 if self.lenfield_name in fields.keys():
147 if p.is_case_or_bitcase:
148 # switch is the anchestor
149 self.lenfield_parent = p.parents[-1]
151 self.lenfield_parent = p
152 self.lenfield_type = fields[self.lenfield_name].field_type
155 self.recursive_resolve_tasks(module, parents)