#!/usr/bin/env python
from xml.etree.cElementTree import *
from os.path import basename
+from functools import reduce
import getopt
import sys
import re
_c('#include <stdlib.h>')
_c('#include <string.h>')
_c('#include <assert.h>')
+ _c('#include <stddef.h> /* for offsetof() */')
_c('#include "xcbext.h"')
_c('#include "%s.h"', _ns.header)
+ _c('')
+ _c('#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)')
+
if _ns.is_ext:
for (n, h) in self.imports:
_hc('#include "%s.h"', h)
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
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):
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)
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)
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)
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:
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)
# 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:
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():
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
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(','))
_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'
_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]
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:
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:
_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:
# 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 */')
# 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;')
_c(' xcb_generic_iterator_t child;')
_c(' child.data = (%s *)(((char *)R) + %s(R));',
self.c_type, self.c_sizeof_name)
+ _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'))
+ _c(' i->index = child.index;')
_c(' --i->rem;')
_c(' i->data = (%s *) child.data;', self.c_type)
- _c(' i->index = child.index;')
+
else:
_c(' --i->rem;')
_c(' ++i->data;')
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.
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('')
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('}')
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('')
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' )
_c(' %s xcb_out;', self.c_type)
if self.var_followed_by_fixed_fields:
_c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
- _c(' char *xcb_aux = 0;')
+ _c(' void *xcb_aux = 0;')
for idx, f in enumerate(serial_fields):
# 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