generator: fix align-pads for switches which start at unaligned pos QueryDeviceState-V2
authorChristian Linhart <chris@DemoRecorder.com>
Tue, 2 Sep 2014 16:13:04 +0000 (18:13 +0200)
committerChristian Linhart <chris@demorecorder.com>
Sat, 6 Sep 2014 18:26:35 +0000 (20:26 +0200)
Fix the alignment computation inside switches which start at
an unaligned pos.
This affects both explicit and implicit align pads.

The alignment offset is derived from the lowest 3 bits of
the pointer to the protocol-data at the start of the switch.
This is sufficient for correcting all alignments up to 8-byte alignment.
As far as I know there is no bigger alignment than 8-byte for the
X-protocol.

Example:
struct InputState, where the switch starts after two 1-byte fields,
which is a 2 byte offset for 4-byte and 8-byte alignment.

The previous problem can be demonstrated when adding a
<pad align="4"/> at the end of case "key".

(Or when finding a testcase which reports the case "valuator" not
at the last position of the QueryDeviceState-reply.
I didn't find such a testcase, so I have used the pad align
as described above.)

V2: patch modified in order to fix bugs which I found when working on the
next issue:
* xcb_padding_offset has to be set 0 when xcb_block_len is set 0
* xcb_padding_offset cannot be "const" therefore
* for unpack and unserialize, the padding_offset must computed
  from _buffer instead of from the aux_var.

Message-ID: <5405EC90.4040203@DemoRecorder.com>
Patch-Thread-Subject: [Xcb] xinput:QueryDeviceState: full-support: generator and xml-changes
Patch-Set: QueryDeviceState
Patch-Number: libxcb 4/4
Patch-Version: V2
Signed-off-by: Christian Linhart <chris@DemoRecorder.com>
src/c_client.py

index d25696c..f448863 100644 (file)
@@ -659,7 +659,9 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
 
 def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
     code_lines.append('%s    /* insert padding */' % space)
-    code_lines.append('%s    xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
+    code_lines.append(
+        '%s    xcb_pad = -( xcb_block_len + xcb_padding_offset ) & (xcb_align_to - 1);'
+        % space)
 #    code_lines.append('%s    printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
     code_lines.append('%s    xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
 
@@ -677,6 +679,7 @@ def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
         code_lines.append('%s    }' % space)
 
     code_lines.append('%s    xcb_block_len = 0;' % space)
+    code_lines.append('%s    xcb_padding_offset = 0;' % space)
 
     # keep tracking of xcb_parts entries for serialize
     return 1
@@ -1095,6 +1098,7 @@ def _c_serialize_helper(context, complex_type,
             code_lines.append('%s    xcb_tmp += xcb_block_len;' % space)
             code_lines.append('%s    xcb_buffer_len += xcb_block_len;' % space)
             code_lines.append('%s    xcb_block_len = 0;' % space)
+            code_lines.append('%s    xcb_padding_offset = 0;' % space)
 
         count += _c_serialize_helper_fields(context, self,
                                             code_lines, temp_vars,
@@ -1170,6 +1174,10 @@ def _c_serialize(context, self):
             _c('    char *xcb_out = *_buffer;')
             _c('    unsigned int xcb_buffer_len = 0;')
             _c('    unsigned int xcb_align_to = 0;')
+        if self.is_switch:
+           _c('    unsigned int xcb_padding_offset = ((size_t)xcb_out) & 7;')
+        else:
+           _c('    unsigned int xcb_padding_offset = 0;')
         prefix = [('_aux', '->', self)]
         aux_ptr = 'xcb_out'
 
@@ -1193,6 +1201,10 @@ def _c_serialize(context, self):
         _c('    unsigned int xcb_block_len = 0;')
         _c('    unsigned int xcb_pad = 0;')
         _c('    unsigned int xcb_align_to = 0;')
+        if self.is_switch:
+            _c('    unsigned int xcb_padding_offset = ((size_t)_buffer) & 7;')
+        else:
+            _c('    unsigned int xcb_padding_offset = 0;')
 
     elif 'sizeof' == context:
         param_names = [p[2] for p in params]
@@ -1210,6 +1222,7 @@ def _c_serialize(context, self):
         else:
             _c('    char *xcb_tmp = (char *)_buffer;')
             prefix = [('_aux', '->', self)]
+            _c('    unsigned int xcb_padding_offset = 0;')
 
     count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
     # update variable size fields (only important for context=='serialize'