xv: Add align. pad in struct AdaptorInfo
[free-sw/xcb/proto] / xcbgen / expr.py
index ed4b975..f9d5179 100644 (file)
@@ -11,14 +11,17 @@ class Field(object):
     visible is true iff the field should be in the request API.
     wire is true iff the field should be in the request structure.
     auto is true iff the field is on the wire but not in the request API (e.g. opcode)
+    enum is the enum name this field refers to, if any.
     '''
-    def __init__(self, type, field_type, field_name, visible, wire, auto):
+    def __init__(self, type, field_type, field_name, visible, wire, auto, enum=None, isfd=False):
         self.type = type
         self.field_type = field_type
         self.field_name = field_name
+        self.enum = enum
         self.visible = visible
         self.wire = wire
         self.auto = auto
+        self.isfd = isfd
 
 
 class Expression(object):
@@ -26,7 +29,7 @@ class Expression(object):
     Represents a mathematical expression for a list length or exprfield.
 
     Public fields:
-    op is the operation (text +,*,/,<<) or None.
+    op is the operation (text +,*,/,<<,~) or None.
     lhs and rhs are the sub-Expressions if op is set.
     lenfield_name is the name of the length field, or None for request lists.
     lenfield is the Field object for the length field, or None.
@@ -40,6 +43,7 @@ class Expression(object):
 
         self.lenfield_name = None
         self.lenfield_type = None
+        self.lenfield_parent = None
         self.lenfield = None
         self.lenwire = False
         self.bitfield = False
@@ -75,14 +79,52 @@ class Expression(object):
             if self.lenfield_name == None:
                 self.lenfield_name = self.rhs.lenfield_name
 
+        elif elt.tag == 'unop':
+            # Op field.  Need to recurse.
+            self.op = elt.get('op')
+            self.rhs = Expression(list(elt)[0], parent)
+
+            self.lenfield_name = self.rhs.lenfield_name
+            
         elif elt.tag == 'value':
             # Constant expression
             self.nmemb = int(elt.text, 0)
 
+        elif elt.tag == 'popcount':
+            self.op = 'popcount'
+            self.rhs = Expression(list(elt)[0], parent)
+            self.lenfield_name = self.rhs.lenfield_name
+            # xcb_popcount returns 'int' - handle the type in the language-specific part
+
+        elif elt.tag == 'enumref':
+            self.op = 'enumref'
+            self.lenfield_name = (elt.get('ref'), elt.text)
+            
+        elif elt.tag == 'sumof':
+            self.op = 'sumof'
+            self.lenfield_name = elt.get('ref')
+
         else:
             # Notreached
-            raise Exception('XXX')
-
+            raise Exception("undefined tag '%s'" % elt.tag)
 
     def fixed_size(self):
         return self.nmemb != None
+
+    def resolve(self, module, parents):
+        if self.op == 'enumref':
+            self.lenfield_type = module.get_type(self.lenfield_name[0])
+            self.lenfield_name = self.lenfield_name[1]
+        elif self.op == 'sumof':
+            # need to find the field with lenfield_name
+            for p in reversed(parents): 
+                fields = dict([(f.field_name, f) for f in p.fields])
+                if self.lenfield_name in fields.keys():
+                    if p.is_bitcase:
+                        # switch is the anchestor 
+                        self.lenfield_parent = p.parents[-1]
+                    else:
+                        self.lenfield_parent = p
+                    self.lenfield_type = fields[self.lenfield_name].field_type
+                    break
+