X-Git-Url: http://git.demorecorder.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fc_client.py;h=cce620ff4f8f8dd32a7b79d9ae638e26e51239ee;hb=c6f3fb2529a6211221e8254f58c85fd67c1d8844;hp=5a41f9ae71f74b5925a87a9a189ab5e638d1b8c2;hpb=d905b886185fd8e0d9d7f70e0d112cb58ab86f98;p=free-sw%2Fxcb%2Flibxcb diff --git a/src/c_client.py b/src/c_client.py index 5a41f9a..cce620f 100644 --- a/src/c_client.py +++ b/src/c_client.py @@ -568,11 +568,6 @@ def _c_helper_fieldaccess_expr(prefix, field=None): last_sep ='' for name, sep, obj in prefix: prefix_str += last_sep + 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 = '.' last_sep = sep if field is None: @@ -728,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: @@ -937,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): @@ -975,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;' @@ -986,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) @@ -996,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) @@ -1507,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) @@ -1534,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')) @@ -1595,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 - 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) @@ -1656,6 +1702,14 @@ def _c_accessor_get_expr(expr, field_mapping): _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: @@ -1665,10 +1719,11 @@ def _c_accessor_get_expr(expr, field_mapping): # field mapping for the subexpression needs to include # the fields of the list-member type scoped_field_mapping = field_mapping.copy() - scoped_field_mapping.update( - _c_helper_field_mapping( - field.type.member, - [(listvar, '->', field.type.member)])) + 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() @@ -1685,6 +1740,8 @@ def _c_accessor_get_expr(expr, field_mapping): _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 + ' ' + @@ -1814,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(): @@ -1844,14 +1924,15 @@ 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) + _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) + _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) @@ -1860,14 +1941,15 @@ def _c_accessors_list(self, field): 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;') @@ -1892,14 +1974,15 @@ 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) @@ -1929,6 +2012,13 @@ def _c_accessors_list(self, field): if switch_obj is None: _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('}') @@ -3080,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]) @@ -3093,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):