summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Linhart <chris@DemoRecorder.com>2014-11-02 13:45:12 +0100
committerChristian Linhart <chris@demorecorder.com>2014-11-03 11:23:16 +0100
commit265d38882cffce597367cc8bb2160b9e2482a80f (patch)
treeab98fec2079940108973cf92f6c9627a004caff3
parentfdb291b414a7afc2c2326124b8ca11d6846cd7b9 (diff)
generator: fix absname for fields with only accessor function
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@DemoRecorder.com> Reviewed-by: Ran Benita <ran234@gmail.com> Message-ID: <54562758.5090107@DemoRecorder.com> Patch-Thread-Subject: [Xcb] [PATCHSET] ListInputDevices revision 2 Patch-Set: ListInputDevices Patch-Number: libxcb 1/9 Patch-Version: V4
-rw-r--r--src/c_client.py64
1 files changed, 52 insertions, 12 deletions
diff --git a/src/c_client.py b/src/c_client.py
index 56a1766..ac5b6dc 100644
--- a/src/c_client.py
+++ b/src/c_client.py
@@ -336,12 +336,6 @@ def _c_type_setup(self, name, postfix):
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)
@@ -391,6 +385,15 @@ def _c_type_setup(self, name, postfix):
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
@@ -427,6 +430,24 @@ def _c_type_setup(self, name, postfix):
_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
@@ -434,16 +455,35 @@ def _c_helper_absolute_name(prefix, field=None):
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
@@ -1734,9 +1774,9 @@ def _c_accessors(self, name, base):
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):