[Xcb] [PATCH libxcb 2/3] generator: support lists of structs which contain a switch

Christian Linhart chris at demorecorder.com
Thu Aug 21 13:35:55 PDT 2014

This essentially requires to have a correct sizeof-function
for the struct.
This in turn requires a sizeof-function for the switch, too.

Making a sizeof-function for the switch is triggered by
replacing "elif" by "if" in the first change of this patch.
This way, c_need_sizeof is also set to True for switches if appropriate.

The _c_serialize_helper_switch_field function has to support
the context "sizeof":
This is done in the second change of this patch

The third change of this patch fixes an alignment error:
It does not make sense to base the padding on the struct-type
which is generated for switch because this struct does not
represent the protocol. Rather it is the output of deserialization.
( The implicit padding for var-sized fields has other issues, IMHO,
but I am not touching these now...)

The effect on the generated code for the current xml-files
is as follows:
* several additional sizeof-functions are generated
* the fix of the alignment error only changes one place
  in the XKB-extension for the GetKbdByName-reply.
  This is no problem because that reply in its current form
  is broken/unfinished anyways.

This patch also fixes a problem in the generator when
a fixed-size list is the last field of a case or bitcase.

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

diff --git a/src/c_client.py b/src/c_client.py
index fa59fff..1ed486c 100644
--- a/src/c_client.py
+++ b/src/c_client.py
@@ -354,15 +354,16 @@ def _c_type_setup(self, name, postfix):
             if field.type.is_list and not field.type.member.fixed_size():
                 field.c_pointer = '*'
             if field.type.is_switch:
                 field.c_pointer = '*'
                 field.c_field_const_type = 'const ' + field.c_field_type
                 self.c_need_aux = True
-            elif not field.type.fixed_size() and not field.type.is_case_or_bitcase:
+            if not field.type.fixed_size() and not field.type.is_case_or_bitcase:
                 self.c_need_sizeof = True
             field.c_iterator_type = _t(field.field_type + ('iterator',))      # xcb_fieldtype_iterator_t
             field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
             field.c_accessor_name = _n(name + (field.field_name,))            # xcb_container_field
             field.c_length_name = _n(name + (field.field_name, 'length'))     # xcb_container_field_length
             field.c_end_name = _n(name + (field.field_name, 'end'))           # xcb_container_field_end
@@ -766,14 +767,18 @@ def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, pr
     # call _serialize()/_unpack() to determine the actual size
     if 'serialize' == context:
         length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
                                        c_field_names, prefix_str, field.c_field_name)
     elif context in ('unserialize', 'unpack'):
         length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
                                            c_field_names, prefix_str, field.c_field_name)
+    elif 'sizeof' == context:
+        #remove trailing ", " from c_field_names because it will be used at end of arglist
+        my_c_field_names = c_field_names[:-2]
+        length = "%s( xcb_tmp, %s )" % ( field.type.c_sizeof_name, my_c_field_names )
     return length
 # _c_serialize_helper_switch_field()
 def _c_serialize_helper_list_field(context, self, field,
                                    code_lines, temp_vars,
                                    space, prefix):
@@ -1042,15 +1047,20 @@ def _c_serialize_helper_fields(context, self,
         if 'serialize' == context:
             if '' != length:
                 code_lines.append('%s    xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
             code_lines.append('%s    xcb_parts_idx++;' % space)
             count += 1
-        code_lines.append('%s    xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type))
+        code_lines.append(
+            '%s    xcb_align_to = ALIGNOF(%s);'
+             % (space,
+                 'char'
+                  if field.c_field_type == 'void' or field.type.is_switch
+                  else field.c_field_type))
         need_padding = True
         if self.c_var_followed_by_fixed_fields:
             need_padding = False
     return count
 # _c_serialize_helper_fields()

More information about the Xcb mailing list