[Xcb] [PATCH libxcb 1/9 V4] generator: fix absname for fields with only accessor function

Christian Linhart chris at DemoRecorder.com
Sun Nov 2 04:45:12 PST 2014


Fix _c_helper_absolute_name for fields which cannot be accessed
as a struct/union member but which can be accessed by an
accessor function.

The fix generates calls to the accessor function in these cases.

Example:
<struct name="AbsnameTest">
<field type="CARD32" name="len" />
<list type="CARD8" name="mylist1">
   <fieldref>len</fieldref>
</list>
<list type="CARD8" name="mylist2">
   <sumof ref="mylist1"/>
</list>
</struct>

The sumof-expression ( <sumof ref="mylist1"/> ) refers to mylist1
which is only acessible by an accessor function.

Previously, sumof was only used inside bitcases,
where such lists are accessible by members of the
deserialized parent struct.
(there is a difference between deserialization of switches
and structs.)

V2 of this patch:
* replaced "!= None" with "is not None" because that's more pythonic.
(according to suggestion from Ran Benita)

V3 of this patch: simplification:
* fixed the recursion in _c_type_setup
  so that _c_helper_absolute_name does not need check
  a gazillion things as a workaround anymore.

* simplified _c_helper_absolute_name
  - remove unneeded check for empty string before
    append of last_sep to prefix_str

  - removed those if-conditions which are not
    needed anymore after fixing the recursion
    in _c_type_setup.

  - extract functionality for checking whether a field
    needs an accessor ( and which type of accessor )
    in functions.
    (also extracted from _c_accessors)

  - rearrange the condition branches and actions for
    more readability.

V3 generates exactly the same *.c and *.h files as V2.

V4 of this patch:
* improve formatting as per suggestions of Ran

Signed-off-by: Christian Linhart <chris at DemoRecorder.com>
Reviewed-by: Ran Benita <ran234 at gmail.com>

---
 src/c_client.py | 65 ++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 53 insertions(+), 12 deletions(-)

diff --git a/src/c_client.py b/src/c_client.py
index 56a1766..4b35ec8 100644
--- a/src/c_client.py
+++ b/src/c_client.py
@@ -332,20 +332,14 @@ def _c_type_setup(self, name, postfix):
 
         self.c_container = 'union' if self.is_union else 'struct'
         prev_varsized_field = None
         prev_varsized_offset = 0
         first_field_after_varsized = None
 
         for field in self.fields:
-            _c_type_setup(field.type, field.field_type, ())
-            if field.type.is_list:
-                _c_type_setup(field.type.member, field.field_type, ())
-                if (field.type.nmemb is None):
-                    self.c_need_sizeof = True
-
             field.c_field_type = _t(field.field_type)
             field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
             field.c_field_name = _cpp(field.field_name)
             field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb and field.type.nmemb > 1) else ''
             field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
 
             # correct the c_pointer field for variable size non-list types
@@ -387,14 +381,23 @@ def _c_type_setup(self, name, postfix):
                 prev_varsized_field = field
                 prev_varsized_offset = 0
 
             if self.c_var_followed_by_fixed_fields:
                 if field.type.fixed_size():
                     field.prev_varsized_field = None
 
+            # recurse into this field this has to be done here, i.e.,
+            # after the field has been set up. Otherwise the function
+            # _c_helper_absolute_name will produce garbage or crash
+            _c_type_setup(field.type, field.field_type, ())
+            if field.type.is_list:
+                _c_type_setup(field.type.member, field.field_type, ())
+                if (field.type.nmemb is None):
+                    self.c_need_sizeof = True
+
     if self.c_need_serialize:
         # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
         self.c_need_sizeof = True
 
     # as switch does never appear at toplevel,
     # continue here with type construction
     if self.is_switch:
@@ -423,31 +428,68 @@ def _c_type_setup(self, name, postfix):
         if self.c_need_sizeof:
             if self.c_sizeof_name not in finished_sizeof:
                 if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
                     finished_sizeof.append(self.c_sizeof_name)
                     _c_serialize('sizeof', self)
 # _c_type_setup()
 
+# Functions for querying field properties
+def _c_field_needs_list_accessor(field):
+    return field.type.is_list and not field.type.fixed_size()
+
+def _c_field_needs_field_accessor(field):
+    if field.type.is_list:
+        return False
+    else:
+        return (field.prev_varsized_field is not None or
+                not field.type.fixed_size())
+
+def _c_field_needs_accessor(field):
+    return (_c_field_needs_list_accessor(field) or
+            _c_field_needs_field_accessor(field))
+
+def _c_field_is_member_of_case_or_bitcase(field):
+    return field.parent and field.parent.is_case_or_bitcase
+
 def _c_helper_absolute_name(prefix, field=None):
     """
     turn prefix, which is a list of tuples (name, separator, Type obj) into a string
     representing a valid name in C (based on the context)
     if field is not None, append the field name as well
     """
     prefix_str = ''
+    last_sep =''
     for name, sep, obj in prefix:
-        prefix_str += name
+        prefix_str += last_sep + name
         if '' == sep:
             sep = '->'
             if ((obj.is_case_or_bitcase and obj.has_name) or     # named bitcase
                 (obj.is_switch and len(obj.parents)>1)):
                 sep = '.'
-        prefix_str += sep
-    if field is not None:
-        prefix_str += _cpp(field.field_name)
+        last_sep = sep
+
+    if field is None:
+        # add separator for access to a yet unknown field
+        prefix_str += last_sep
+    else:
+        if _c_field_needs_accessor(field):
+            if _c_field_is_member_of_case_or_bitcase(field):
+                # case members are available in the deserialized struct,
+                # so there is no need to use the accessor function
+                # (also, their accessor function needs a different arglist
+                # so this would require special treatment here)
+                # Therefore: Access as struct member
+                prefix_str += last_sep + _cpp(field.field_name)
+            else:
+                # Access with the accessor function
+                prefix_str = field.c_accessor_name + "(" + prefix_str + ")"
+        else:
+            # Access as struct member
+            prefix_str += last_sep + _cpp(field.field_name)
+
     return prefix_str
 # _c_absolute_name
 
 def _c_helper_field_mapping(complex_type, prefix, flat=False):
     """
     generate absolute names, based on prefix, for all fields starting from complex_type
     if flat == True, nested complex types are not taken into account
@@ -1730,17 +1784,17 @@ def _c_accessors(self, name, base):
     # switch always needs to be unpacked explicitly
 #    if self.is_switch:
 #        pass
 #    else:
     if True:
         for field in self.fields:
             if not field.type.is_pad:
-                if field.type.is_list and not field.type.fixed_size():
+                if _c_field_needs_list_accessor(field):
                     _c_accessors_list(self, field)
-                elif field.prev_varsized_field is not None or not field.type.fixed_size():
+                elif _c_field_needs_field_accessor(field):
                     _c_accessors_field(self, field)
 
 def c_simple(self, name):
     '''
     Exported function that handles cardinal type declarations.
     These are types which are typedef'd to one of the CARDx's, char, float, etc.
     '''
-- 2.0.1 _______________________________________________ Xcb mailing list Xcb at lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/xcb



More information about the Xcb mailing list