X-Git-Url: http://git.demorecorder.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fc_client.py;h=7a27c1f095d93c4fdd8194e3b1f22416fe0baa8d;hb=aa02096b8e7f94ad3c998a8d5af54963ee860b13;hp=26826e42fc400407377a102d69ce2f9794e5ccfa;hpb=5e8a7ade2dc8aeeeb8013785ca3f24c6057ae443;p=free-sw%2Fxcb%2Flibxcb diff --git a/src/c_client.py b/src/c_client.py index 26826e4..7a27c1f 100644 --- a/src/c_client.py +++ b/src/c_client.py @@ -1,6 +1,7 @@ #!/usr/bin/env python from xml.etree.cElementTree import * from os.path import basename +from functools import reduce import getopt import sys import re @@ -170,6 +171,7 @@ def c_open(self): _c('#include ') _c('#include ') _c('#include ') + _c('#include /* for offsetof() */') _c('#include "xcbext.h"') _c('#include "%s.h"', _ns.header) @@ -182,6 +184,9 @@ def c_open(self): _h('extern "C" {') _h('#endif') + _h('') + _h('#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)') + if _ns.is_ext: _h('') _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version) @@ -323,7 +328,7 @@ def _c_type_setup(self, name, postfix): 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) - field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else '' + field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb and field.type.nmemb > 1) else '' field.c_pointer = ' ' if field.type.nmemb == 1 else '*' # correct the c_pointer field for variable size non-list types @@ -399,8 +404,9 @@ def _c_type_setup(self, name, postfix): if self.need_sizeof: if self.c_sizeof_name not in finished_sizeof: - finished_sizeof.append(self.c_sizeof_name) - _c_serialize('sizeof', self) + if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix: + finished_sizeof.append(self.c_sizeof_name) + _c_serialize('sizeof', self) # _c_type_setup() def _c_helper_absolute_name(prefix, field=None): @@ -442,7 +448,7 @@ def _c_helper_field_mapping(complex_type, prefix, flat=False): else: for f in complex_type.fields: fname = _c_helper_absolute_name(prefix, f) - if all_fields.has_key(f.field_name): + if f.field_name in all_fields: raise Exception("field name %s has been registered before" % f.field_name) all_fields[f.field_name] = (fname, f) @@ -523,7 +529,7 @@ def get_expr_fields(self): prefix.append(('', '', self)) all_fields = _c_helper_resolve_field_names (prefix) - resolved_fields_names = filter(lambda x: x in all_fields.keys(), unresolved_fields_names) + resolved_fields_names = list(filter(lambda x: x in all_fields.keys(), unresolved_fields_names)) if len(unresolved_fields_names) != len(resolved_fields_names): raise Exception("could not resolve all fields for %s" % self.name) @@ -635,7 +641,7 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'): def _c_serialize_helper_insert_padding(context, code_lines, space, postpone): code_lines.append('%s /* insert padding */' % space) - code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space) + code_lines.append('%s xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space) # code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space) code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space) @@ -742,8 +748,8 @@ def _c_serialize_helper_list_field(context, self, field, param_names = [p[2] for p in params] expr_fields_names = [f.field_name for f in get_expr_fields(field.type)] - resolved = filter(lambda x: x in param_names, expr_fields_names) - unresolved = filter(lambda x: x not in param_names, expr_fields_names) + resolved = list(filter(lambda x: x in param_names, expr_fields_names)) + unresolved = list(filter(lambda x: x not in param_names, expr_fields_names)) field_mapping = {} for r in resolved: @@ -756,8 +762,8 @@ def _c_serialize_helper_list_field(context, self, field, field.c_field_name) field_mapping.update(_c_helper_resolve_field_names(prefix)) - resolved += filter(lambda x: x in field_mapping, unresolved) - unresolved = filter(lambda x: x not in field_mapping, unresolved) + resolved += list(filter(lambda x: x in field_mapping, unresolved)) + unresolved = list(filter(lambda x: x not in field_mapping, unresolved)) if len(unresolved)>0: raise Exception('could not resolve the length fields required for list %s' % field.c_field_name) @@ -874,7 +880,7 @@ def _c_serialize_helper_fields_variable_size(context, self, field, # special case: intermixed fixed and variable size fields if self.var_followed_by_fixed_fields and 'unserialize' == context: - value = ' %s = xcb_tmp;' % field.c_field_name + value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type) temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name)) # special case: switch if 'unpack' == context: @@ -924,8 +930,9 @@ def _c_serialize_helper_fields(context, self, prev_field_was_variable = False for field in self.fields: - if not ((field.wire and not field.auto) or field.visible): - continue + if not field.visible: + if not ((field.wire and not field.auto) or 'unserialize' == context): + continue # switch/bitcase: fixed size fields must be considered explicitly if field.type.fixed_size(): @@ -990,6 +997,8 @@ def _c_serialize_helper_fields(context, self, code_lines.append('%s xcb_parts_idx++;' % space) count += 1 + code_lines.append('%s xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type)) + need_padding = True if self.var_followed_by_fixed_fields: need_padding = False @@ -1081,7 +1090,7 @@ def _c_serialize(context, self): param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)) # insert function name param_str[0] = "%s (%s" % (func_name, param_str[0].strip()) - param_str = map(lambda x: "%s," % x, param_str) + param_str = list(map(lambda x: "%s," % x, param_str)) for s in param_str[:-1]: _hc(s) _h("%s);" % param_str[-1].rstrip(',')) @@ -1097,9 +1106,11 @@ def _c_serialize(context, self): _c(' %s *xcb_out = *_buffer;', self.c_type) _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type) _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type) + _c(' unsigned int xcb_align_to;') else: _c(' char *xcb_out = *_buffer;') _c(' unsigned int xcb_buffer_len = 0;') + _c(' unsigned int xcb_align_to;') prefix = [('_aux', '->', self)] aux_ptr = 'xcb_out' @@ -1122,6 +1133,7 @@ def _c_serialize(context, self): _c(' unsigned int xcb_buffer_len = 0;') _c(' unsigned int xcb_block_len = 0;') _c(' unsigned int xcb_pad = 0;') + _c(' unsigned int xcb_align_to;') elif 'sizeof' == context: param_names = [p[2] for p in params] @@ -1133,8 +1145,7 @@ def _c_serialize(context, self): return elif self.var_followed_by_fixed_fields: # special case: call _unserialize() - _c(' %s *_aux = NULL;', self.c_type) - _c(' return %s(%s, &_aux);', 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('}') return else: @@ -1158,7 +1169,7 @@ def _c_serialize(context, self): if not (self.is_switch or self.var_followed_by_fixed_fields): # look if we have to declare an '_aux' variable at all - if len(filter(lambda x: x.find('_aux')!=-1, code_lines))>0: + if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0: if not self.var_followed_by_fixed_fields: _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type) else: @@ -1167,6 +1178,7 @@ def _c_serialize(context, self): _c(' unsigned int xcb_buffer_len = 0;') _c(' unsigned int xcb_block_len = 0;') _c(' unsigned int xcb_pad = 0;') + _c(' unsigned int xcb_align_to;') _c('') for t in temp_vars: @@ -1179,6 +1191,12 @@ def _c_serialize(context, self): # allocate memory and copy everything into a continuous memory area # note: this is not necessary in case of unpack if context in ('serialize', 'unserialize'): + # unserialize: check for sizeof-only invocation + if 'unserialize' == context: + _c('') + _c(' if (NULL == _aux)') + _c(' return xcb_buffer_len;') + _c('') _c(' if (NULL == %s) {', aux_ptr) _c(' /* allocate memory */') @@ -1212,12 +1230,13 @@ def _c_serialize(context, self): # unserialize: assign variable size fields individually if 'unserialize' == context: - _c(' *%s = xcb_out;', aux_ptr) - _c(' xcb_tmp = (char *)(*_aux+1);') + _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;') + param_fields.reverse() for field in param_fields: if not field.type.fixed_size(): - _c(' memcpy(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name) - _c(' xcb_tmp += %s_len;', field.c_field_name) + _c(' xcb_tmp -= %s_len;', field.c_field_name) + _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name) + _c(' *%s = xcb_out;', aux_ptr) _c('') _c(' return xcb_buffer_len;') @@ -1415,6 +1434,11 @@ def _c_accessor_get_expr(expr, field_mapping): else: return lenexp +def type_pad_type(type): + if type == 'void': + return 'char' + return type + def _c_accessors_field(self, field): ''' Declares the accessor functions for a non-list field that follows a variable-length field. @@ -1449,7 +1473,7 @@ def _c_accessors_field(self, field): else: _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R')) _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', - field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset) + field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset) _c('}') else: _hc('') @@ -1480,7 +1504,7 @@ def _c_accessors_field(self, field): else: _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R')) _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', - return_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset) + return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset) _c('}') @@ -1567,7 +1591,7 @@ def _c_accessors_list(self, field): else: _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R')) _c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', - field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset) + field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset) _c('}') _hc('') @@ -1671,7 +1695,7 @@ def _c_accessors_list(self, field): else: _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R')) _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', - field.c_field_type, field.c_field_type) + field.c_field_type, type_pad_type(field.c_field_type)) if switch_obj is None: _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields)) _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' ) @@ -2269,26 +2293,26 @@ output = {'open' : c_open, # Check for the argument that specifies path to the xcbgen python package. try: opts, args = getopt.getopt(sys.argv[1:], 'p:') -except getopt.GetoptError, err: - print str(err) - print 'Usage: c_client.py [-p path] file.xml' +except getopt.GetoptError as err: + print(err) + print('Usage: c_client.py [-p path] file.xml') sys.exit(1) for (opt, arg) in opts: if opt == '-p': - sys.path.append(arg) + sys.path.insert(1, arg) # Import the module class try: from xcbgen.state import Module except ImportError: - print '' - print 'Failed to load the xcbgen Python package!' - print 'Make sure that xcb/proto installed it on your Python path.' - print 'If not, you will need to create a .pth file or define $PYTHONPATH' - print 'to extend the path.' - print 'Refer to the README file in xcb/proto for more info.' - print '' + print(''' +Failed to load the xcbgen Python package! +Make sure that xcb/proto installed it on your Python path. +If not, you will need to create a .pth file or define $PYTHONPATH +to extend the path. +Refer to the README file in xcb/proto for more info. +''') raise # Parse the xml header