branch 'ParametrizedStruct-V7'
This commit is contained in:
Christian Linhart 2015-02-10 10:13:04 +01:00
commit 5353c0216e

View File

@ -58,6 +58,107 @@ def _hc(fmt, *args):
_h(fmt, *args) _h(fmt, *args)
_c(fmt, *args) _c(fmt, *args)
def _c_wr_stringlist(indent, strlist):
'''
Writes the given list of strings to the source file.
Each line is prepended by the indent string
'''
for str in strlist:
_c("%s%s", indent, str)
class PreCode(object):
'''
For pre-code generated by expression generation
(for example, the for-loop of a sumof)
This has to account for recursiveness of the expression
generation, i.e., there may be pre-code for pre-code.
Therefore this is implemented as a stack of lists of lines.
If redirection is switched on, then all output is collected in
self.redirect_code and self.redirect_tempvars instead of
being sent to the output via _h und _c.
'''
def __init__(self):
self.nesting_level = 0
self.tempvars = []
self.codelines = []
self.redirect_code = None
self.redirect_tempvars = None
self.indent_str = ' '
self.indent_stack = []
self.tempvar_num = 0
# start and end of pre-code blocks
def start(self):
self.nesting_level += 1
def end(self):
self.nesting_level -= 1
if self.nesting_level == 0:
# lowest pre-code level is finished -> output to source
if self.redirect_tempvars is None:
_c_wr_stringlist('', self.tempvars)
self.tempvars = []
else:
self.redirect_tempvars.extend(self.tempvars)
self.tempvars = []
if self.redirect_code == None:
_c_wr_stringlist('', self.codelines)
self.codelines = []
else:
self.redirect_code.extend(self.codelines)
self.codelines = []
def output_tempvars(self):
if self.redirect_code == None:
_c_wr_stringlist('', self.tempvars)
self.tempvars = []
# output to precode
def code(self, fmt, *args):
self.codelines.append(self.indent_str + fmt % args)
def tempvar(self, fmt, *args):
self.tempvars.append(' ' + (fmt % args))
# get a unique name for a temporary variable
def get_tempvarname(self):
self.tempvar_num += 1
return "xcb_pre_tmp_%d" % self.tempvar_num
# indentation
def push_indent(self, indentstr):
self.indent_stack.append(self.indent_str)
self.indent_str = indentstr
def push_addindent(self, indent_add_str):
self.push_indent(self.indent_str + indent_add_str)
def indent(self):
self.push_addindent(' ')
def pop_indent(self):
self.indent_str = self.indent_stack.pop()
# redirection to lists
def redirect_start(self, redirect_code, redirect_tempvars=None):
self.redirect_code = redirect_code
self.redirect_tempvars = redirect_tempvars
if redirect_tempvars is not None:
self.tempvar_num = 0
def redirect_end(self):
self.redirect_code = None
self.redirect_tempvars = None
# global PreCode handler
_c_pre = PreCode()
# XXX See if this level thing is really necessary. # XXX See if this level thing is really necessary.
def _h_setlevel(idx): def _h_setlevel(idx):
''' '''
@ -336,12 +437,6 @@ def _c_type_setup(self, name, postfix):
first_field_after_varsized = None first_field_after_varsized = None
for field in self.fields: for field in self.fields:
_c_type_setup(field.type, field.field_type, ())
if field.type.is_list:
_c_type_setup(field.type.member, field.field_type, ())
if (field.type.nmemb is None):
self.c_need_sizeof = True
field.c_field_type = _t(field.field_type) field.c_field_type = _t(field.field_type)
field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
field.c_field_name = _cpp(field.field_name) field.c_field_name = _cpp(field.field_name)
@ -391,6 +486,15 @@ def _c_type_setup(self, name, postfix):
if field.type.fixed_size(): if field.type.fixed_size():
field.prev_varsized_field = None field.prev_varsized_field = None
# recurse into this field this has to be done here, i.e.,
# after the field has been set up. Otherwise the function
# _c_helper_fieldaccess_expr will produce garbage or crash
_c_type_setup(field.type, field.field_type, ())
if field.type.is_list:
_c_type_setup(field.type.member, field.field_type, ())
if (field.type.nmemb is None):
self.c_need_sizeof = True
if self.c_need_serialize: if self.c_need_serialize:
# when _unserialize() is wanted, create _sizeof() as well for consistency reasons # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
self.c_need_sizeof = True self.c_need_sizeof = True
@ -427,23 +531,64 @@ def _c_type_setup(self, name, postfix):
_c_serialize('sizeof', self) _c_serialize('sizeof', self)
# _c_type_setup() # _c_type_setup()
def _c_helper_absolute_name(prefix, field=None): # Functions for querying field properties
def _c_field_needs_list_accessor(field):
return field.type.is_list and not field.type.fixed_size()
def _c_field_needs_field_accessor(field):
if field.type.is_list:
return False
else:
return (field.prev_varsized_field is not None or
not field.type.fixed_size())
def _c_field_needs_accessor(field):
return (_c_field_needs_list_accessor(field) or
_c_field_needs_field_accessor(field))
def _c_field_is_member_of_case_or_bitcase(field):
return field.parent and field.parent.is_case_or_bitcase
def _c_helper_fieldaccess_expr(prefix, field=None):
""" """
turn prefix, which is a list of tuples (name, separator, Type obj) into a string turn prefix, which is a list of tuples (name, separator, Type obj) into a string
representing a valid name in C (based on the context) representing a valid field-access-expression in C (based on the context)
if field is not None, append the field name as well if field is not None, append access to the field as well.
"separator" is one of the C-operators "." or "->".
A field access expression can consist of the following components:
* struct/union member access from a value with the "."-operator
* struct/union member access from a pointer with "->"-operator
* function-call of an accessor function:
This is used when a xcb-field is not contained in a struct.
This can, e.g., happen for fields after var-sized fields, etc.
""" """
prefix_str = '' prefix_str = ''
last_sep =''
for name, sep, obj in prefix: for name, sep, obj in prefix:
prefix_str += name prefix_str += last_sep + name
if '' == sep: last_sep = sep
sep = '->'
if ((obj.is_case_or_bitcase and obj.has_name) or # named bitcase if field is None:
(obj.is_switch and len(obj.parents)>1)): # add separator for access to a yet unknown field
sep = '.' prefix_str += last_sep
prefix_str += sep else:
if field is not None: if _c_field_needs_accessor(field):
prefix_str += _cpp(field.field_name) if _c_field_is_member_of_case_or_bitcase(field):
# case members are available in the deserialized struct,
# so there is no need to use the accessor function
# (also, their accessor function needs a different arglist
# so this would require special treatment here)
# Therefore: Access as struct member
prefix_str += last_sep + _cpp(field.field_name)
else:
# Access with the accessor function
prefix_str = field.c_accessor_name + "(" + prefix_str + ")"
else:
# Access as struct member
prefix_str += last_sep + _cpp(field.field_name)
return prefix_str return prefix_str
# _c_absolute_name # _c_absolute_name
@ -465,7 +610,7 @@ def _c_helper_field_mapping(complex_type, prefix, flat=False):
all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat)) all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
else: else:
for f in complex_type.fields: for f in complex_type.fields:
fname = _c_helper_absolute_name(prefix, f) fname = _c_helper_fieldaccess_expr(prefix, f)
if f.field_name in all_fields: if f.field_name in all_fields:
raise Exception("field name %s has been registered before" % f.field_name) raise Exception("field name %s has been registered before" % f.field_name)
@ -578,6 +723,31 @@ def resolve_expr_fields(complex_obj):
return unresolved return unresolved
# resolve_expr_fields() # resolve_expr_fields()
def resolve_expr_fields_list(self, parents):
"""
Find expr fields appearing in a list and descendents
that cannot be resolved within the parents of the list.
These are normally fields that need to be given as function parameters
for length and iterator functions.
"""
all_fields = []
expr_fields = get_expr_fields(self)
unresolved = []
for complex_obj in parents:
for field in complex_obj.fields:
if field.wire:
all_fields.append(field)
# try to resolve expr fields
for e in expr_fields:
if e not in all_fields and e not in unresolved:
unresolved.append(e)
return unresolved
# resolve_expr_fields_list()
def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'): def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
""" """
functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters: functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
@ -750,7 +920,7 @@ def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, pr
# switch is handled by this function as a special case # switch is handled by this function as a special case
param_fields, wire_fields, params = get_serialize_params(context, self) param_fields, wire_fields, params = get_serialize_params(context, self)
field_mapping = _c_helper_field_mapping(self, prefix) field_mapping = _c_helper_field_mapping(self, prefix)
prefix_str = _c_helper_absolute_name(prefix) prefix_str = _c_helper_fieldaccess_expr(prefix)
# find the parameters that need to be passed to _serialize()/_unpack(): # find the parameters that need to be passed to _serialize()/_unpack():
# all switch expr fields must be given as parameters # all switch expr fields must be given as parameters
@ -787,6 +957,16 @@ def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, pr
return length return length
# _c_serialize_helper_switch_field() # _c_serialize_helper_switch_field()
def _c_get_additional_type_params(type):
"""
compute list of additional params for functions created for the given type
"""
if type.is_simple:
return []
else:
param_fields, wire_fields, params = get_serialize_params('sizeof', type)
return params[1:]
def _c_serialize_helper_list_field(context, self, field, def _c_serialize_helper_list_field(context, self, field,
code_lines, temp_vars, code_lines, temp_vars,
space, prefix): space, prefix):
@ -794,7 +974,7 @@ def _c_serialize_helper_list_field(context, self, field,
helper function to cope with lists of variable length helper function to cope with lists of variable length
""" """
expr = field.type.expr expr = field.type.expr
prefix_str = _c_helper_absolute_name(prefix) prefix_str = _c_helper_fieldaccess_expr(prefix)
param_fields, wire_fields, params = get_serialize_params('sizeof', self) param_fields, wire_fields, params = get_serialize_params('sizeof', self)
param_names = [p[2] for p in params] param_names = [p[2] for p in params]
@ -825,6 +1005,14 @@ def _c_serialize_helper_list_field(context, self, field,
# list with variable-sized elements # list with variable-sized elements
if not field.type.member.fixed_size(): if not field.type.member.fixed_size():
# compute string for argumentlist for member-type functions
member_params = _c_get_additional_type_params(field.type.member)
member_arg_names = [p[2] for p in member_params]
member_arg_str = ''
for member_arg_name in member_arg_names:
member_arg_str += ', ' + field_mapping[member_arg_name][0]
#
length = '' length = ''
if context in ('unserialize', 'sizeof', 'unpack'): if context in ('unserialize', 'sizeof', 'unpack'):
int_i = ' unsigned int i;' int_i = ' unsigned int i;'
@ -836,8 +1024,8 @@ def _c_serialize_helper_list_field(context, self, field,
# loop over all list elements and call sizeof repeatedly # loop over all list elements and call sizeof repeatedly
# this should be a bit faster than using the iterators # this should be a bit faster than using the iterators
code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length)) code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" % code_lines.append("%s xcb_tmp_len = %s(xcb_tmp%s);" %
(space, field.type.c_sizeof_name)) (space, field.type.c_sizeof_name, member_arg_str))
code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space) code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space) code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
code_lines.append("%s }" % space) code_lines.append("%s }" % space)
@ -846,7 +1034,7 @@ def _c_serialize_helper_list_field(context, self, field,
code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space) code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name)) code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length)) code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length))
code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name)) code_lines.append('%s xcb_block_len = %s(xcb_tmp%s);' % (space, field.type.c_sizeof_name, member_arg_str))
code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space) code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
code_lines.append('%s }' % space) code_lines.append('%s }' % space)
code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space) code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
@ -865,7 +1053,7 @@ def _c_serialize_helper_fields_fixed_size(context, self, field,
typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name) typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name)) code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
abs_field_name = _c_helper_absolute_name(prefix, field) abs_field_name = _c_helper_fieldaccess_expr(prefix, field)
# default for simple cases: call sizeof() # default for simple cases: call sizeof()
length = "sizeof(%s)" % field.c_field_type length = "sizeof(%s)" % field.c_field_type
@ -927,7 +1115,7 @@ def _c_serialize_helper_fields_fixed_size(context, self, field,
def _c_serialize_helper_fields_variable_size(context, self, field, def _c_serialize_helper_fields_variable_size(context, self, field,
code_lines, temp_vars, code_lines, temp_vars,
space, prefix): space, prefix):
prefix_str = _c_helper_absolute_name(prefix) prefix_str = _c_helper_fieldaccess_expr(prefix)
if context in ('unserialize', 'unpack', 'sizeof'): if context in ('unserialize', 'unpack', 'sizeof'):
value = '' value = ''
@ -984,6 +1172,8 @@ def _c_serialize_helper_fields(context, self,
need_padding = False need_padding = False
prev_field_was_variable = False prev_field_was_variable = False
_c_pre.push_indent(space + ' ')
for field in self.fields: for field in self.fields:
if not field.visible: if not field.visible:
if not ((field.wire and not field.auto) or 'unserialize' == context): if not ((field.wire and not field.auto) or 'unserialize' == context):
@ -1072,6 +1262,8 @@ def _c_serialize_helper_fields(context, self,
if self.c_var_followed_by_fixed_fields: if self.c_var_followed_by_fixed_fields:
need_padding = False need_padding = False
_c_pre.pop_indent()
return count return count
# _c_serialize_helper_fields() # _c_serialize_helper_fields()
@ -1170,6 +1362,8 @@ def _c_serialize(context, self):
temp_vars = [] temp_vars = []
prefix = [] prefix = []
_c_pre.redirect_start(code_lines, temp_vars)
if 'serialize' == context: if 'serialize' == context:
if not self.is_switch and not self.c_var_followed_by_fixed_fields: if not self.is_switch and not self.c_var_followed_by_fixed_fields:
_c(' %s *xcb_out = *_buffer;', self.c_type) _c(' %s *xcb_out = *_buffer;', self.c_type)
@ -1215,11 +1409,13 @@ def _c_serialize(context, self):
_c(' %s _aux;', self.c_type) _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)) _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
_c('}') _c('}')
_c_pre.redirect_end()
return return
elif self.c_var_followed_by_fixed_fields: elif self.c_var_followed_by_fixed_fields:
# special case: call _unserialize() # special case: call _unserialize()
_c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names)) _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
_c('}') _c('}')
_c_pre.redirect_end()
return return
else: else:
_c(' char *xcb_tmp = (char *)_buffer;') _c(' char *xcb_tmp = (char *)_buffer;')
@ -1255,6 +1451,8 @@ def _c_serialize(context, self):
_c(' unsigned int xcb_pad = 0;') _c(' unsigned int xcb_pad = 0;')
_c(' unsigned int xcb_align_to = 0;') _c(' unsigned int xcb_align_to = 0;')
_c_pre.redirect_end()
_c('') _c('')
for t in temp_vars: for t in temp_vars:
_c(t) _c(t)
@ -1347,6 +1545,14 @@ def _c_iterator(self, name):
_h(' %s *data; /**< */', self.c_type) _h(' %s *data; /**< */', self.c_type)
_h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2)) _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
_h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2)) _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
# add additional params of the type "self" as fields to the iterator struct
# so that they can be passed to the sizeof-function by the iterator's next-function
params = _c_get_additional_type_params(self)
for param in params:
_h(' %s%s %s; /**< */',
param[0],
' ' * (len(self.c_type) + 1 - len(param[0])),
param[2])
_h('} %s;', self.c_iterator_type) _h('} %s;', self.c_iterator_type)
_h_setlevel(1) _h_setlevel(1)
@ -1374,9 +1580,14 @@ def _c_iterator(self, name):
_c(' /* FIXME - determine the size of the union %s */', self.c_type) _c(' /* FIXME - determine the size of the union %s */', self.c_type)
else: else:
if self.c_need_sizeof: if self.c_need_sizeof:
# compute the string of additional arguments for the sizeof-function
additional_args = ''
for param in params:
additional_args += ', i->' + param[2]
_c(' xcb_generic_iterator_t child;') _c(' xcb_generic_iterator_t child;')
_c(' child.data = (%s *)(((char *)R) + %s(R));', _c(' child.data = (%s *)(((char *)R) + %s(R%s));',
self.c_type, self.c_sizeof_name) self.c_type, self.c_sizeof_name, additional_args)
_c(' i->index = (char *) child.data - (char *) i->data;') _c(' i->index = (char *) child.data - (char *) i->data;')
else: else:
_c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R')) _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
@ -1435,12 +1646,7 @@ def _c_accessor_get_length(expr, field_mapping=None):
if field_mapping is not None: if field_mapping is not None:
lenfield_name = field_mapping[lenfield_name][0] lenfield_name = field_mapping[lenfield_name][0]
if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None: if expr.lenfield_name is not None:
# special case: variable and fixed size fields are intermixed
# if the lenfield is among the fixed size fields, there is no need
# to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
return field_mapping(expr.lenfield_name)
elif expr.lenfield_name is not None:
return lenfield_name return lenfield_name
else: else:
return str(expr.nmemb) return str(expr.nmemb)
@ -1477,9 +1683,65 @@ def _c_accessor_get_expr(expr, field_mapping):
raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name) raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
list_name = field_mapping[field.c_field_name][0] list_name = field_mapping[field.c_field_name][0]
c_length_func = "%s(%s)" % (field.c_length_name, list_name) c_length_func = "%s(%s)" % (field.c_length_name, list_name)
# note: xcb_sumof() has only been defined for integers
c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping) c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
return 'xcb_sumof(%s, %s)' % (list_name, c_length_func) # create explicit code for computing the sum.
# This works for all C-types which can be added to int64_t with +=
_c_pre.start()
lengthvar = _c_pre.get_tempvarname()
loopvar = _c_pre.get_tempvarname()
sumvar = _c_pre.get_tempvarname()
listvar = _c_pre.get_tempvarname()
_c_pre.tempvar("int %s; /* sumof length */", lengthvar)
_c_pre.tempvar("int %s; /* sumof loop counter */", loopvar)
_c_pre.tempvar("int64_t %s; /* sumof sum */", sumvar)
_c_pre.tempvar("const %s* %s; /* sumof list ptr */", field.c_field_type, listvar)
_c_pre.code("/* sumof start */")
_c_pre.code("%s = %s;", lengthvar, c_length_func)
_c_pre.code("%s = 0;", sumvar)
_c_pre.code("%s = %s;", listvar, list_name)
_c_pre.code("for (%s = 0; %s < %s; %s++) {", loopvar, loopvar, lengthvar, loopvar)
_c_pre.indent()
# define and set xcb_listelement, so that it can be used by
# listelement-ref expressions.
if expr.contains_listelement_ref:
_c_pre.code(
"const %s *xcb_listelement = %s;",
field.c_field_type, listvar)
# summation
if expr.rhs is None:
_c_pre.code("%s += *%s;", sumvar, listvar)
else:
# sumof has a nested expression which has to be evaluated in
# the context of this list element
# field mapping for the subexpression needs to include
# the fields of the list-member type
scoped_field_mapping = field_mapping.copy()
if not field.type.member.is_simple:
scoped_field_mapping.update(
_c_helper_field_mapping(
field.type.member,
[(listvar, '->', field.type.member)]))
# cause pre-code of the subexpression be added right here
_c_pre.end()
# compute the subexpression
rhs_expr_str = _c_accessor_get_expr(expr.rhs, scoped_field_mapping)
# resume with our code
_c_pre.start()
# output the summation expression
_c_pre.code("%s += %s;", sumvar, rhs_expr_str)
_c_pre.code("%s++;", listvar)
_c_pre.pop_indent()
_c_pre.code("}")
_c_pre.code("/* sumof end. Result is in %s */", sumvar)
_c_pre.end()
return sumvar
elif expr.op == 'listelement-ref':
return '(*xcb_listelement)'
elif expr.op != None: elif expr.op != None:
return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) + return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
' ' + expr.op + ' ' + ' ' + expr.op + ' ' +
@ -1609,6 +1871,29 @@ def _c_accessors_list(self, field):
# auxiliary object for 'S' parameter # auxiliary object for 'S' parameter
S_obj = parents[1] S_obj = parents[1]
# for functions generated below:
# * compute list of additional parameters which contains as parameter
# any expr fields that cannot be resolved within self and descendants.
# * and make sure that they are accessed without prefix within the function.
unresolved_fields = resolve_expr_fields_list(list, parents)
additional_params = []
additional_param_names = set();
for f in unresolved_fields:
if f.c_field_name not in additional_param_names:
# add to the list of additional params
additional_params.append((f.c_field_type, f.c_field_name));
# make sure that the param is accessed without prefix within the function
fields[ f.c_field_name ] = (f.c_field_name, f)
# internal function to compute the parameterlist with given indentation
# such that the formatting of the additional parameters is consistent with
# the other parameters.
def additional_params_to_str(indent):
if len(additional_params) == 0:
return ''
else:
return (',\n' + indent).join([''] + ['%s %s /**< */' % p for p in additional_params])
_h_setlevel(1) _h_setlevel(1)
_c_setlevel(1) _c_setlevel(1)
if list.member.fixed_size(): if list.member.fixed_size():
@ -1639,31 +1924,32 @@ def _c_accessors_list(self, field):
_hc('') _hc('')
_hc('int') _hc('int')
spacing = ' '*(len(field.c_length_name)+2)
add_param_str = additional_params_to_str(spacing)
if switch_obj is not None: if switch_obj is not None:
_hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type) _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
spacing = ' '*(len(field.c_length_name)+2) _h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
_h('%sconst %s *S /**< */);', spacing, S_obj.c_type) _c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
_c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
length = _c_accessor_get_expr(field.type.expr, fields)
else: else:
_h('%s (const %s *R /**< */);', field.c_length_name, c_type) _h('%s (const %s *R /**< */%s);', field.c_length_name, c_type, add_param_str)
_c('%s (const %s *R /**< */)', field.c_length_name, c_type) _c('%s (const %s *R /**< */%s)', field.c_length_name, c_type, add_param_str)
length = _c_accessor_get_expr(field.type.expr, fields)
_c('{') _c('{')
length = _c_accessor_get_expr(field.type.expr, fields)
_c(' return %s;', length) _c(' return %s;', length)
_c('}') _c('}')
if field.type.member.is_simple: if field.type.member.is_simple:
_hc('') _hc('')
_hc('xcb_generic_iterator_t') _hc('xcb_generic_iterator_t')
spacing = ' '*(len(field.c_end_name)+2)
add_param_str = additional_params_to_str(spacing)
if switch_obj is not None: if switch_obj is not None:
_hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type) _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
spacing = ' '*(len(field.c_end_name)+2) _h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
_h('%sconst %s *S /**< */);', spacing, S_obj.c_type) _c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
_c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
else: else:
_h('%s (const %s *R /**< */);', field.c_end_name, c_type) _h('%s (const %s *R /**< */%s);', field.c_end_name, c_type, add_param_str)
_c('%s (const %s *R /**< */)', field.c_end_name, c_type) _c('%s (const %s *R /**< */%s)', field.c_end_name, c_type, add_param_str)
_c('{') _c('{')
_c(' xcb_generic_iterator_t i;') _c(' xcb_generic_iterator_t i;')
@ -1688,21 +1974,27 @@ def _c_accessors_list(self, field):
else: else:
_hc('') _hc('')
_hc('%s', field.c_iterator_type) _hc('%s', field.c_iterator_type)
spacing = ' '*(len(field.c_iterator_name)+2)
add_param_str = additional_params_to_str(spacing)
if switch_obj is not None: if switch_obj is not None:
_hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type) _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
spacing = ' '*(len(field.c_iterator_name)+2) _h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
_h('%sconst %s *S /**< */);', spacing, S_obj.c_type) _c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
_c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
else: else:
_h('%s (const %s *R /**< */);', field.c_iterator_name, c_type) _h('%s (const %s *R /**< */%s);', field.c_iterator_name, c_type, add_param_str)
_c('%s (const %s *R /**< */)', field.c_iterator_name, c_type) _c('%s (const %s *R /**< */%s)', field.c_iterator_name, c_type, add_param_str)
_c('{') _c('{')
_c(' %s i;', field.c_iterator_type) _c(' %s i;', field.c_iterator_type)
_c_pre.start()
length_expr_str = _c_accessor_get_expr(field.type.expr, fields)
if switch_obj is not None: if switch_obj is not None:
_c_pre.end()
_c(' i.data = %s;', fields[field.c_field_name][0]) _c(' i.data = %s;', fields[field.c_field_name][0])
_c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields)) _c(' i.rem = %s;', length_expr_str)
elif field.prev_varsized_field == None: elif field.prev_varsized_field == None:
_c_pre.end()
_c(' i.data = (%s *) (R + 1);', field.c_field_type) _c(' i.data = (%s *) (R + 1);', field.c_field_type)
else: else:
(prev_varsized_field, align_pad) = get_align_pad(field) (prev_varsized_field, align_pad) = get_align_pad(field)
@ -1713,12 +2005,20 @@ def _c_accessors_list(self, field):
_c(' xcb_generic_iterator_t prev = %s;', _c(' xcb_generic_iterator_t prev = %s;',
_c_iterator_get_end(prev_varsized_field, 'R')) _c_iterator_get_end(prev_varsized_field, 'R'))
_c_pre.end()
_c(' i.data = (%s *) ((char *) prev.data + %s);', _c(' i.data = (%s *) ((char *) prev.data + %s);',
field.c_field_type, align_pad) field.c_field_type, align_pad)
if switch_obj is None: if switch_obj is None:
_c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields)) _c(' i.rem = %s;', length_expr_str)
_c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' ) _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
# initialize additional iterator fields which are derived from
# additional type parameters for the list member type.
additional_iter_fields = _c_get_additional_type_params(field.type.member)
for iter_field in additional_iter_fields:
_c(' i.%s = %s;', iter_field[2], fields[iter_field[2]][0])
_c(' return i;') _c(' return i;')
_c('}') _c('}')
@ -1734,9 +2034,9 @@ def _c_accessors(self, name, base):
if True: if True:
for field in self.fields: for field in self.fields:
if not field.type.is_pad: if not field.type.is_pad:
if field.type.is_list and not field.type.fixed_size(): if _c_field_needs_list_accessor(field):
_c_accessors_list(self, field) _c_accessors_list(self, field)
elif field.prev_varsized_field is not None or not field.type.fixed_size(): elif _c_field_needs_field_accessor(field):
_c_accessors_field(self, field) _c_accessors_field(self, field)
def c_simple(self, name): def c_simple(self, name):
@ -2870,7 +3170,18 @@ def c_event(self, name):
force_packed = any(f.type.size == 8 and f.type.is_simple for f in self.fields[(idx+1):]) force_packed = any(f.type.size == 8 and f.type.is_simple for f in self.fields[(idx+1):])
break break
_c_type_setup(self, name, ('event',)) if self.name == name:
_c_type_setup(self, name, ('event',))
# generate accessors
# (needed for fields after var-sized fields, for lists with var-sized elements,
# switches, ...)
_c_accessors(self, name, name)
else:
# no type-setup needed for eventcopies
# (the type-setup of an eventcopy would overwrite members of the original
# event, and it would create sizeof-etc funtions which
# called undefined accessor functions)
pass
# Opcode define # Opcode define
_c_opcode(name, self.opcodes[name]) _c_opcode(name, self.opcodes[name])
@ -2883,6 +3194,22 @@ def c_event(self, name):
_h('') _h('')
_h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',))) _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
# Create sizeof-function for eventcopies for compatibility reasons
if self.c_need_sizeof:
_h_setlevel(1)
_c_setlevel(1)
_h('')
_h('int')
_h('%s (const void *_buffer /**< */);', _n(name + ('sizeof',)))
_c('')
_c('int')
_c('%s (const void *_buffer /**< */)', _n(name + ('sizeof',)))
_c('{');
_c(' return %s(_buffer);', _n(self.name + ('sizeof',)))
_c('}');
_h_setlevel(0)
_c_setlevel(0)
_man_event(self, name) _man_event(self, name)
def c_error(self, name): def c_error(self, name):