branch 'ParametrizedStruct-V7'
This commit is contained in:
commit
5353c0216e
443
src/c_client.py
443
src/c_client.py
|
@ -58,6 +58,107 @@ def _hc(fmt, *args):
|
|||
_h(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.
|
||||
def _h_setlevel(idx):
|
||||
'''
|
||||
|
@ -336,12 +437,6 @@ def _c_type_setup(self, name, postfix):
|
|||
first_field_after_varsized = None
|
||||
|
||||
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_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
|
||||
field.c_field_name = _cpp(field.field_name)
|
||||
|
@ -391,6 +486,15 @@ def _c_type_setup(self, name, postfix):
|
|||
if field.type.fixed_size():
|
||||
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:
|
||||
# when _unserialize() is wanted, create _sizeof() as well for consistency reasons
|
||||
self.c_need_sizeof = True
|
||||
|
@ -427,23 +531,64 @@ def _c_type_setup(self, name, postfix):
|
|||
_c_serialize('sizeof', self)
|
||||
# _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
|
||||
representing a valid name in C (based on the context)
|
||||
if field is not None, append the field name as well
|
||||
representing a valid field-access-expression in C (based on the context)
|
||||
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 = ''
|
||||
last_sep =''
|
||||
for name, sep, obj in prefix:
|
||||
prefix_str += name
|
||||
if '' == sep:
|
||||
sep = '->'
|
||||
if ((obj.is_case_or_bitcase and obj.has_name) or # named bitcase
|
||||
(obj.is_switch and len(obj.parents)>1)):
|
||||
sep = '.'
|
||||
prefix_str += sep
|
||||
if field is not None:
|
||||
prefix_str += _cpp(field.field_name)
|
||||
prefix_str += last_sep + name
|
||||
last_sep = sep
|
||||
|
||||
if field is None:
|
||||
# add separator for access to a yet unknown field
|
||||
prefix_str += last_sep
|
||||
else:
|
||||
if _c_field_needs_accessor(field):
|
||||
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
|
||||
# _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))
|
||||
else:
|
||||
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:
|
||||
raise Exception("field name %s has been registered before" % f.field_name)
|
||||
|
||||
|
@ -578,6 +723,31 @@ def resolve_expr_fields(complex_obj):
|
|||
return unresolved
|
||||
# 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'):
|
||||
"""
|
||||
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
|
||||
param_fields, wire_fields, params = get_serialize_params(context, self)
|
||||
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():
|
||||
# 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
|
||||
# _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,
|
||||
code_lines, temp_vars,
|
||||
space, prefix):
|
||||
|
@ -794,7 +974,7 @@ def _c_serialize_helper_list_field(context, self, field,
|
|||
helper function to cope with lists of variable length
|
||||
"""
|
||||
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_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
|
||||
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 = ''
|
||||
if context in ('unserialize', 'sizeof', 'unpack'):
|
||||
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
|
||||
# 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 xcb_tmp_len = %s(xcb_tmp);" %
|
||||
(space, field.type.c_sizeof_name))
|
||||
code_lines.append("%s xcb_tmp_len = %s(xcb_tmp%s);" %
|
||||
(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_tmp += xcb_tmp_len;" % 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_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 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 }' % 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)
|
||||
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()
|
||||
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,
|
||||
code_lines, temp_vars,
|
||||
space, prefix):
|
||||
prefix_str = _c_helper_absolute_name(prefix)
|
||||
prefix_str = _c_helper_fieldaccess_expr(prefix)
|
||||
|
||||
if context in ('unserialize', 'unpack', 'sizeof'):
|
||||
value = ''
|
||||
|
@ -984,6 +1172,8 @@ def _c_serialize_helper_fields(context, self,
|
|||
need_padding = False
|
||||
prev_field_was_variable = False
|
||||
|
||||
_c_pre.push_indent(space + ' ')
|
||||
|
||||
for field in self.fields:
|
||||
if not field.visible:
|
||||
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:
|
||||
need_padding = False
|
||||
|
||||
_c_pre.pop_indent()
|
||||
|
||||
return count
|
||||
# _c_serialize_helper_fields()
|
||||
|
||||
|
@ -1170,6 +1362,8 @@ def _c_serialize(context, self):
|
|||
temp_vars = []
|
||||
prefix = []
|
||||
|
||||
_c_pre.redirect_start(code_lines, temp_vars)
|
||||
|
||||
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)
|
||||
|
@ -1215,11 +1409,13 @@ def _c_serialize(context, self):
|
|||
_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('}')
|
||||
_c_pre.redirect_end()
|
||||
return
|
||||
elif self.c_var_followed_by_fixed_fields:
|
||||
# special case: call _unserialize()
|
||||
_c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
|
||||
_c('}')
|
||||
_c_pre.redirect_end()
|
||||
return
|
||||
else:
|
||||
_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_align_to = 0;')
|
||||
|
||||
_c_pre.redirect_end()
|
||||
|
||||
_c('')
|
||||
for t in temp_vars:
|
||||
_c(t)
|
||||
|
@ -1347,6 +1545,14 @@ def _c_iterator(self, name):
|
|||
_h(' %s *data; /**< */', self.c_type)
|
||||
_h(' int%s rem; /**< */', ' ' * (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_setlevel(1)
|
||||
|
@ -1374,9 +1580,14 @@ def _c_iterator(self, name):
|
|||
_c(' /* FIXME - determine the size of the union %s */', self.c_type)
|
||||
else:
|
||||
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(' child.data = (%s *)(((char *)R) + %s(R));',
|
||||
self.c_type, self.c_sizeof_name)
|
||||
_c(' child.data = (%s *)(((char *)R) + %s(R%s));',
|
||||
self.c_type, self.c_sizeof_name, additional_args)
|
||||
_c(' i->index = (char *) child.data - (char *) i->data;')
|
||||
else:
|
||||
_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:
|
||||
lenfield_name = field_mapping[lenfield_name][0]
|
||||
|
||||
if expr.lenfield is not None and expr.lenfield.prev_varsized_field 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:
|
||||
if expr.lenfield_name is not None:
|
||||
return lenfield_name
|
||||
else:
|
||||
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)
|
||||
list_name = field_mapping[field.c_field_name][0]
|
||||
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)
|
||||
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:
|
||||
return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
|
||||
' ' + expr.op + ' ' +
|
||||
|
@ -1609,6 +1871,29 @@ def _c_accessors_list(self, field):
|
|||
# auxiliary object for 'S' parameter
|
||||
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)
|
||||
_c_setlevel(1)
|
||||
if list.member.fixed_size():
|
||||
|
@ -1639,31 +1924,32 @@ def _c_accessors_list(self, field):
|
|||
|
||||
_hc('')
|
||||
_hc('int')
|
||||
spacing = ' '*(len(field.c_length_name)+2)
|
||||
add_param_str = additional_params_to_str(spacing)
|
||||
if switch_obj is not None:
|
||||
_hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
|
||||
spacing = ' '*(len(field.c_length_name)+2)
|
||||
_h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
|
||||
_c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
|
||||
length = _c_accessor_get_expr(field.type.expr, fields)
|
||||
_h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
|
||||
_c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
|
||||
else:
|
||||
_h('%s (const %s *R /**< */);', field.c_length_name, c_type)
|
||||
_c('%s (const %s *R /**< */)', field.c_length_name, c_type)
|
||||
length = _c_accessor_get_expr(field.type.expr, fields)
|
||||
_h('%s (const %s *R /**< */%s);', field.c_length_name, c_type, add_param_str)
|
||||
_c('%s (const %s *R /**< */%s)', field.c_length_name, c_type, add_param_str)
|
||||
_c('{')
|
||||
length = _c_accessor_get_expr(field.type.expr, fields)
|
||||
_c(' return %s;', length)
|
||||
_c('}')
|
||||
|
||||
if field.type.member.is_simple:
|
||||
_hc('')
|
||||
_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:
|
||||
_hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
|
||||
spacing = ' '*(len(field.c_end_name)+2)
|
||||
_h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
|
||||
_c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
|
||||
_h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
|
||||
_c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
|
||||
else:
|
||||
_h('%s (const %s *R /**< */);', field.c_end_name, c_type)
|
||||
_c('%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 /**< */%s)', field.c_end_name, c_type, add_param_str)
|
||||
_c('{')
|
||||
_c(' xcb_generic_iterator_t i;')
|
||||
|
||||
|
@ -1688,21 +1974,27 @@ def _c_accessors_list(self, field):
|
|||
else:
|
||||
_hc('')
|
||||
_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:
|
||||
_hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
|
||||
spacing = ' '*(len(field.c_iterator_name)+2)
|
||||
_h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
|
||||
_c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
|
||||
_h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
|
||||
_c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
|
||||
else:
|
||||
_h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
|
||||
_c('%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 /**< */%s)', field.c_iterator_name, c_type, add_param_str)
|
||||
_c('{')
|
||||
_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:
|
||||
_c_pre.end()
|
||||
_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:
|
||||
_c_pre.end()
|
||||
_c(' i.data = (%s *) (R + 1);', field.c_field_type)
|
||||
else:
|
||||
(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_iterator_get_end(prev_varsized_field, 'R'))
|
||||
_c_pre.end()
|
||||
_c(' i.data = (%s *) ((char *) prev.data + %s);',
|
||||
field.c_field_type, align_pad)
|
||||
|
||||
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' )
|
||||
|
||||
# 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('}')
|
||||
|
||||
|
@ -1734,9 +2034,9 @@ def _c_accessors(self, name, base):
|
|||
if True:
|
||||
for field in self.fields:
|
||||
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)
|
||||
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)
|
||||
|
||||
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):])
|
||||
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
|
||||
_c_opcode(name, self.opcodes[name])
|
||||
|
@ -2883,6 +3194,22 @@ def c_event(self, name):
|
|||
_h('')
|
||||
_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)
|
||||
|
||||
def c_error(self, name):
|
||||
|
|
Loading…
Reference in New Issue