summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Linhart <chris@DemoRecorder.com>2014-09-09 23:26:40 +0200
committerChristian Linhart <chris@demorecorder.com>2014-10-20 12:21:21 +0200
commita7c75be5b1e2da32f7ce2c255972178e7d4b7598 (patch)
tree2e038343192a3da0e8b26bfb79684ddef1cd6453
parent277ea629def6728c9d826ff88e95b31c3e25915f (diff)
generator: fix align-pads for switches which start at unaligned pos
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. V3: patch revised according to suggestion by Ran Benita: * only create and use xcb_padding_offset for switch Message-ID: <1410298000-24734-1-git-send-email-chris@demorecorder.com> Patch-Thread-Subject: [Xcb] xinput:QueryDeviceState: full-support: generator and xml-changes Patch-Set: QueryDeviceState Patch-Number: libxcb 4/4 Patch-Version: V3 Signed-off-by: Christian Linhart <chris@DemoRecorder.com> Reviewed-By: Ran Benita <ran234@gmail.com>
-rw-r--r--src/c_client.py26
1 files changed, 21 insertions, 5 deletions
diff --git a/src/c_client.py b/src/c_client.py
index 1d1bbf6..0a1f877 100644
--- a/src/c_client.py
+++ b/src/c_client.py
@@ -657,9 +657,15 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
return (param_fields, wire_fields, params)
# get_serialize_params()
-def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
+def _c_serialize_helper_insert_padding(context, code_lines, space, postpone, is_case_or_bitcase):
code_lines.append('%s /* insert padding */' % space)
- code_lines.append('%s xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
+ if is_case_or_bitcase:
+ code_lines.append(
+ '%s xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);'
+ % space)
+ else:
+ code_lines.append(
+ '%s xcb_pad = -xcb_block_len & (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 +683,8 @@ 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)
+ if is_case_or_bitcase:
+ code_lines.append('%s xcb_padding_offset = 0;' % space)
# keep tracking of xcb_parts entries for serialize
return 1
@@ -1005,13 +1013,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)
+ self.c_var_followed_by_fixed_fields,
+ is_case_or_bitcase)
continue
else:
# switch/bitcase: always calculate padding before and after variable sized fields
if need_padding or is_case_or_bitcase:
count += _c_serialize_helper_insert_padding(context, code_lines, space,
- self.c_var_followed_by_fixed_fields)
+ self.c_var_followed_by_fixed_fields,
+ is_case_or_bitcase)
value, length = _c_serialize_helper_fields_variable_size(context, self, field,
code_lines, temp_vars,
@@ -1100,7 +1110,7 @@ def _c_serialize_helper(context, complex_type,
code_lines, temp_vars,
space, prefix, False)
# "final padding"
- count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
+ count += _c_serialize_helper_insert_padding(context, code_lines, space, False, self.is_switch)
return count
# _c_serialize_helper()
@@ -1170,6 +1180,8 @@ 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;')
prefix = [('_aux', '->', self)]
aux_ptr = 'xcb_out'
@@ -1193,6 +1205,8 @@ 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;')
elif 'sizeof' == context:
param_names = [p[2] for p in params]
@@ -1210,6 +1224,8 @@ def _c_serialize(context, self):
else:
_c(' char *xcb_tmp = (char *)_buffer;')
prefix = [('_aux', '->', self)]
+ if self.is_switch:
+ _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'