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)
|
_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):
|
||||||
|
|
Loading…
Reference in New Issue