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
This commit is contained in:
Christian Linhart 2014-11-02 13:45:12 +01:00 committed by Christian Linhart
parent fdb291b414
commit 265d38882c

View File

@ -336,12 +336,6 @@ def _c_type_setup(self, name, postfix):
first_field_after_varsized = None first_field_after_varsized = None
for field in self.fields: 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_type = _t(field.field_type)
field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_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_field_name = _cpp(field.field_name)
@ -391,6 +385,15 @@ def _c_type_setup(self, name, postfix):
if field.type.fixed_size(): if field.type.fixed_size():
field.prev_varsized_field = None 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: if self.c_need_serialize:
# when _unserialize() is wanted, create _sizeof() as well for consistency reasons # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
self.c_need_sizeof = True self.c_need_sizeof = True
@ -427,6 +430,24 @@ def _c_type_setup(self, name, postfix):
_c_serialize('sizeof', self) _c_serialize('sizeof', self)
# _c_type_setup() # _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): def _c_helper_absolute_name(prefix, field=None):
""" """
turn prefix, which is a list of tuples (name, separator, Type obj) into a string 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 if field is not None, append the field name as well
""" """
prefix_str = '' prefix_str = ''
last_sep =''
for name, sep, obj in prefix: for name, sep, obj in prefix:
prefix_str += name prefix_str += last_sep + name
if '' == sep: if '' == sep:
sep = '->' sep = '->'
if ((obj.is_case_or_bitcase and obj.has_name) or # named bitcase if ((obj.is_case_or_bitcase and obj.has_name) or # named bitcase
(obj.is_switch and len(obj.parents)>1)): (obj.is_switch and len(obj.parents)>1)):
sep = '.' sep = '.'
prefix_str += sep last_sep = sep
if field is not None:
prefix_str += _cpp(field.field_name) 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 return prefix_str
# _c_absolute_name # _c_absolute_name
@ -1734,9 +1774,9 @@ def _c_accessors(self, name, base):
if True: if True:
for field in self.fields: for field in self.fields:
if not field.type.is_pad: 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) _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) _c_accessors_field(self, field)
def c_simple(self, name): def c_simple(self, name):