[Xcb] [PATCH libxcb 3/3 V2] generator: optionally enable/disable implicit_padding

Christian Linhart chris at DemoRecorder.com
Wed Aug 27 03:35:10 PDT 2014


This is controlled by the new ComplexType-member "implicit_padding"
which is set by the parser.
(See corresponding patch for the parser for xcb/proto)

The first change: ( lines 892+ )
use xcb_pad0 also for pads of size 1.
reasons:
* the previously used variable xcb_pad is actually used
  for another purpose elsewhere and therefore its value 
  may be non-zero.
* with this simplification it is easier to determine
  which variables for padding have to be defined.

The second change: ( lines 1005+ )
For inserting the padding before or after var-size fields
it adds the condition that implicit_padding must be true.

The third change: ( lines 1047+ )
Compute align_to only when implicit_padding is enabled

The fourth change (lines 1096+ ) handles final padding.
In that case, alternative code has to be provided if implicit_padding
is switched off in order to update the value of xcb_buffer_len
accordingly.

>From the fifth change until the change before the last change:
Only declare variables that are used, in order to avoid
C-compiler warnings.

The last change makes protocol-representing structs packed when
implicit_padding is disabled.
Structs from a switch do not represent the protocol.
Rather they are the output of deserialization, etc.
Therefore packing is not enabled for structs of a switch.

V2: patch revised because it has generated uncompilable code
when fixed size pads occur in structs where implicit padding
was switched off. V2 fixes that.
---
 src/c_client.py | 63 ++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 42 insertions(+), 21 deletions(-)

diff --git a/src/c_client.py b/src/c_client.py
index 6af21fb..a32fd32 100644
--- a/src/c_client.py
+++ b/src/c_client.py
@@ -892,20 +892,17 @@ def _c_serialize_helper_fields_fixed_size(context, self, field,
                                 (field.field_name, _c_accessor_get_expr(field.type.expr)))
 
             temp_vars.append('    %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
                                                            _c_accessor_get_expr(field.type.expr, prefix)))
             value += "&xcb_expr_%s;" % _cpp(field.field_name)
 
         elif field.type.is_pad:
-            if field.type.nmemb == 1:
-                value += "&xcb_pad;"
-            else:
-                # we could also set it to 0, see definition of xcb_send_request()
-                value = '    xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
-                length += "*%d" % field.type.nmemb
+            # we could also set it to 0, see definition of xcb_send_request()
+            value = '    xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
+            length += "*%d" % field.type.nmemb
 
         else:
             # non-list type with fixed size
             if field.type.nmemb == 1:
                 value += "&%s;" % (abs_field_name)
 
             # list with nmemb (fixed size) elements
@@ -1005,15 +1002,15 @@ def _c_serialize_helper_fields(context, self,
                 # Variable length pad is <pad align= />
                 code_lines.append('%s    xcb_align_to = %d;' % (space, field.type.align))
                 count += _c_serialize_helper_insert_padding(context, code_lines, space,
                                                         self.c_var_followed_by_fixed_fields)
                 continue
             else:
                 # switch/bitcase: always calculate padding before and after variable sized fields
-                if need_padding or is_case_or_bitcase:
+                if ( need_padding or is_case_or_bitcase ) and self.implicit_padding:
                     count += _c_serialize_helper_insert_padding(context, code_lines, space,
                                                             self.c_var_followed_by_fixed_fields)
 
                 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
                                                                          code_lines, temp_vars,
                                                                          space, prefix)
                 prev_field_was_variable = True
@@ -1047,20 +1044,21 @@ 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' or field.type.is_switch
-                  else field.c_field_type))
+        if self.implicit_padding:
+            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()
@@ -1096,15 +1094,19 @@ def _c_serialize_helper(context, complex_type,
             code_lines.append('%s    xcb_buffer_len += xcb_block_len;' % space)
             code_lines.append('%s    xcb_block_len = 0;' % space)
 
         count += _c_serialize_helper_fields(context, self,
                                             code_lines, temp_vars,
                                             space, prefix, False)
     # "final padding"
-    count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
+    if self.implicit_padding:
+        count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
+    else:
+        code_lines.append('%s    xcb_buffer_len += xcb_block_len;' % space)
+        code_lines.append('%s    xcb_block_len = 0;' % space)
 
     return count
 # _c_serialize_helper()
 
 def _c_serialize(context, self):
     """
     depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
@@ -1161,19 +1163,21 @@ def _c_serialize(context, self):
     prefix = []
 
     if 'serialize' == context:
         if not self.is_switch and not self.c_var_followed_by_fixed_fields:
             _c('    %s *xcb_out = *_buffer;', self.c_type)
             _c('    unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
             _c('    unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
-            _c('    unsigned int xcb_align_to = 0;')
         else:
             _c('    char *xcb_out = *_buffer;')
             _c('    unsigned int xcb_buffer_len = 0;')
+
+        if self.implicit_padding or self.contains_explicit_alignpads:
             _c('    unsigned int xcb_align_to = 0;')
+
         prefix = [('_aux', '->', self)]
         aux_ptr = 'xcb_out'
 
     elif context in ('unserialize', 'unpack'):
         _c('    char *xcb_tmp = (char *)_buffer;')
         if not self.is_switch:
             if not self.c_var_followed_by_fixed_fields:
@@ -1187,16 +1191,17 @@ def _c_serialize(context, self):
             # note: unserialize not generated for switch
             if 'unserialize' == context:
                 aux_var = '(*_aux)' # unserialize: double pointer (!)
             prefix = [(aux_var, '->', self)]
         aux_ptr = '*_aux'
         _c('    unsigned int xcb_buffer_len = 0;')
         _c('    unsigned int xcb_block_len = 0;')
-        _c('    unsigned int xcb_pad = 0;')
-        _c('    unsigned int xcb_align_to = 0;')
+        if self.implicit_padding or self.contains_explicit_alignpads:
+            _c('    unsigned int xcb_pad = 0;')
+            _c('    unsigned int xcb_align_to = 0;')
 
     elif 'sizeof' == context:
         param_names = [p[2] for p in params]
         if self.is_switch:
             # switch: call _unpack()
             _c('    %s _aux;', self.c_type)
             _c('    return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
@@ -1211,16 +1216,27 @@ def _c_serialize(context, self):
             _c('    char *xcb_tmp = (char *)_buffer;')
             prefix = [('_aux', '->', self)]
 
     count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
     # update variable size fields (only important for context=='serialize'
     variable_size_fields = count
     if 'serialize' == context:
-        temp_vars.append('    unsigned int xcb_pad = 0;')
-        temp_vars.append('    char xcb_pad0[3] = {0, 0, 0};')
+        if (
+            self.implicit_padding
+            or self.contains_explicit_alignpads
+        ):
+            temp_vars.append('    unsigned int xcb_pad = 0;')
+
+        if (
+            self.implicit_padding
+            or self.contains_explicit_alignpads
+            or self.contains_fixedpads
+        ):
+            temp_vars.append('    char xcb_pad0[3] = {0, 0, 0};')
+
         temp_vars.append('    struct iovec xcb_parts[%d];' % count)
         temp_vars.append('    unsigned int xcb_parts_idx = 0;')
         temp_vars.append('    unsigned int xcb_block_len = 0;')
         temp_vars.append('    unsigned int i;')
         temp_vars.append('    char *xcb_tmp;')
     elif 'sizeof' == context:
         # neither switch nor intermixed fixed and variable size fields:
@@ -1232,16 +1248,17 @@ def _c_serialize(context, self):
                 if not self.c_var_followed_by_fixed_fields:
                     _c('    const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
                 else:
                     _c('    %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
 
             _c('    unsigned int xcb_buffer_len = 0;')
             _c('    unsigned int xcb_block_len = 0;')
-            _c('    unsigned int xcb_pad = 0;')
-            _c('    unsigned int xcb_align_to = 0;')
+            if self.implicit_padding or self.contains_explicit_alignpads:
+                _c('    unsigned int xcb_pad = 0;')
+                _c('    unsigned int xcb_align_to = 0;')
 
     _c('')
     for t in temp_vars:
         _c(t)
     _c('')
     for l in code_lines:
         _c(l)
@@ -1741,14 +1758,18 @@ def c_simple(self, name):
         _c_iterator(self, name)
 
 def _c_complex(self, force_packed = False):
     '''
     Helper function for handling all structure types.
     Called for all structs, requests, replies, events, errors.
     '''
+
+    if self.implicit_padding == False and not self.is_switch:
+        force_packed = True
+
     _h_setlevel(0)
     _h('')
     _h('/**')
     _h(' * @brief %s', self.c_type)
     _h(' **/')
     _h('typedef %s %s {', self.c_container, self.c_type)
 
-- 
2.0.1



More information about the Xcb mailing list