Keep ALIGNOF definition out of the public namespace.
[free-sw/xcb/libxcb] / src / c_client.py
index a66c7e3..ad3ea22 100644 (file)
@@ -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,9 +171,13 @@ def c_open(self):
     _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)
@@ -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
@@ -443,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)
@@ -524,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)
     
@@ -636,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)
 
@@ -743,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:
@@ -757,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)
 
@@ -875,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:
@@ -925,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():
@@ -991,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
@@ -1082,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(','))
@@ -1098,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'
 
@@ -1123,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]
@@ -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:
@@ -1422,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.
@@ -1456,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('')
@@ -1487,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('}')
 
     
@@ -1574,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('')
@@ -1678,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' )
@@ -2276,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