[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