generator: support parametrized structs
[free-sw/xcb/libxcb] / src / c_client.py
index 99fd307..cce620f 100644 (file)
@@ -28,7 +28,7 @@ _clines = []
 _clevel = 0
 _ns = None
 
 _clevel = 0
 _ns = None
 
-# global variable to keep track of serializers and 
+# global variable to keep track of serializers and
 # switch data types due to weird dependencies
 finished_serializers = []
 finished_sizeof = []
 # switch data types due to weird dependencies
 finished_serializers = []
 finished_sizeof = []
@@ -44,13 +44,13 @@ def _h(fmt, *args):
     Writes the given line to the header file.
     '''
     _hlines[_hlevel].append(fmt % args)
     Writes the given line to the header file.
     '''
     _hlines[_hlevel].append(fmt % args)
-    
+
 def _c(fmt, *args):
     '''
     Writes the given line to the source file.
     '''
     _clines[_clevel].append(fmt % args)
 def _c(fmt, *args):
     '''
     Writes the given line to the source file.
     '''
     _clines[_clevel].append(fmt % args)
-    
+
 def _hc(fmt, *args):
     '''
     Writes the given line to both the header and source files.
 def _hc(fmt, *args):
     '''
     Writes the given line to both the header and source files.
@@ -58,6 +58,107 @@ def _hc(fmt, *args):
     _h(fmt, *args)
     _c(fmt, *args)
 
     _h(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.
 def _h_setlevel(idx):
     '''
 # XXX See if this level thing is really necessary.
 def _h_setlevel(idx):
     '''
@@ -68,7 +169,7 @@ def _h_setlevel(idx):
     while len(_hlines) <= idx:
         _hlines.append([])
     _hlevel = idx
     while len(_hlines) <= idx:
         _hlines.append([])
     _hlevel = idx
-    
+
 def _c_setlevel(idx):
     '''
     Changes the array that source lines are written to.
 def _c_setlevel(idx):
     '''
     Changes the array that source lines are written to.
@@ -78,7 +179,7 @@ def _c_setlevel(idx):
     while len(_clines) <= idx:
         _clines.append([])
     _clevel = idx
     while len(_clines) <= idx:
         _clines.append([])
     _clevel = idx
-    
+
 def _n_item(str):
     '''
     Does C-name conversion on a single string fragment.
 def _n_item(str):
     '''
     Does C-name conversion on a single string fragment.
@@ -90,7 +191,7 @@ def _n_item(str):
         split = _cname_re.finditer(str)
         name_parts = [match.group(0) for match in split]
         return '_'.join(name_parts)
         split = _cname_re.finditer(str)
         name_parts = [match.group(0) for match in split]
         return '_'.join(name_parts)
-    
+
 def _cpp(str):
     '''
     Checks for certain C++ reserved words and fixes them.
 def _cpp(str):
     '''
     Checks for certain C++ reserved words and fixes them.
@@ -111,7 +212,7 @@ def _ext(str):
         return _n_item(str).lower()
     else:
         return str.lower()
         return _n_item(str).lower()
     else:
         return str.lower()
-    
+
 def _n(list):
     '''
     Does C-name conversion on a tuple of strings.
 def _n(list):
     '''
     Does C-name conversion on a tuple of strings.
@@ -142,7 +243,7 @@ def _t(list):
     else:
         parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
     return '_'.join(parts).lower()
     else:
         parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
     return '_'.join(parts).lower()
-        
+
 
 def c_open(self):
     '''
 
 def c_open(self):
     '''
@@ -185,12 +286,12 @@ def c_open(self):
     _c('#include <stddef.h>  /* for offsetof() */')
     _c('#include "xcbext.h"')
     _c('#include "%s.h"', _ns.header)
     _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:
     _c('')
     _c('#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)')
 
     if _ns.is_ext:
-        for (n, h) in self.imports:
+        for (n, h) in self.direct_imports:
             _hc('#include "%s.h"', h)
 
     _h('')
             _hc('#include "%s.h"', h)
 
     _h('')
@@ -202,7 +303,7 @@ def c_open(self):
         _h('')
         _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
         _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
         _h('')
         _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
         _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
-        _h('  ') #XXX
+        _h('') #XXX
         _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
 
         _c('')
         _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
 
         _c('')
@@ -305,9 +406,9 @@ def _c_type_setup(self, name, postfix):
     self.c_cookie_type = _t(name + ('cookie',))
     self.c_reply_fds_name = _n(name + ('reply_fds',))
 
     self.c_cookie_type = _t(name + ('cookie',))
     self.c_reply_fds_name = _n(name + ('reply_fds',))
 
-    self.need_aux = False
-    self.need_serialize = False
-    self.need_sizeof = False
+    self.c_need_aux = False
+    self.c_need_serialize = False
+    self.c_need_sizeof = False
 
     self.c_aux_name = _n(name + ('aux',))
     self.c_aux_checked_name = _n(name + ('aux', 'checked'))
 
     self.c_aux_name = _n(name + ('aux',))
     self.c_aux_checked_name = _n(name + ('aux', 'checked'))
@@ -318,10 +419,10 @@ def _c_type_setup(self, name, postfix):
     self.c_sizeof_name = _n(name + ('sizeof',))
 
     # special case: structs where variable size fields are followed by fixed size fields
     self.c_sizeof_name = _n(name + ('sizeof',))
 
     # special case: structs where variable size fields are followed by fixed size fields
-    self.var_followed_by_fixed_fields = False
+    self.c_var_followed_by_fixed_fields = False
 
     if self.is_switch:
 
     if self.is_switch:
-        self.need_serialize = True
+        self.c_need_serialize = True
         self.c_container = 'struct'
         for bitcase in self.bitcases:
             bitcase.c_field_name = _cpp(bitcase.field_name)
         self.c_container = 'struct'
         for bitcase in self.bitcases:
             bitcase.c_field_name = _cpp(bitcase.field_name)
@@ -336,12 +437,6 @@ def _c_type_setup(self, name, postfix):
         first_field_after_varsized = None
 
         for field in self.fields:
         first_field_after_varsized = None
 
         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.need_sizeof = True
-
             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_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)
@@ -357,9 +452,10 @@ def _c_type_setup(self, name, postfix):
             if field.type.is_switch:
                 field.c_pointer = '*'
                 field.c_field_const_type = 'const ' + field.c_field_type
             if field.type.is_switch:
                 field.c_pointer = '*'
                 field.c_field_const_type = 'const ' + field.c_field_type
-                self.need_aux = True
-            elif not field.type.fixed_size() and not field.type.is_bitcase:
-                self.need_sizeof = True
+                self.c_need_aux = True
+
+            if not field.type.fixed_size() and not field.type.is_case_or_bitcase:
+                self.c_need_sizeof = True
 
             field.c_iterator_type = _t(field.field_type + ('iterator',))      # xcb_fieldtype_iterator_t
             field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
 
             field.c_iterator_type = _t(field.field_type + ('iterator',))      # xcb_fieldtype_iterator_t
             field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
@@ -379,22 +475,31 @@ def _c_type_setup(self, name, postfix):
                 # special case: intermixed fixed and variable size fields
                 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
                     if not self.is_union:
                 # special case: intermixed fixed and variable size fields
                 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
                     if not self.is_union:
-                        self.need_serialize = True
-                        self.var_followed_by_fixed_fields = True
+                        self.c_need_serialize = True
+                        self.c_var_followed_by_fixed_fields = True
             else:
                 self.last_varsized_field = field
                 prev_varsized_field = field
             else:
                 self.last_varsized_field = field
                 prev_varsized_field = field
-                prev_varsized_offset = 0                    
+                prev_varsized_offset = 0
 
 
-            if self.var_followed_by_fixed_fields:
+            if self.c_var_followed_by_fixed_fields:
                 if field.type.fixed_size():
                     field.prev_varsized_field = None
                 if field.type.fixed_size():
                     field.prev_varsized_field = None
-                            
-    if self.need_serialize:
-        # when _unserialize() is wanted, create _sizeof() as well for consistency reasons 
-        self.need_sizeof = True
 
 
-    # as switch does never appear at toplevel, 
+            # 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:
+        # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
+        self.c_need_sizeof = True
+
+    # as switch does never appear at toplevel,
     # continue here with type construction
     if self.is_switch:
         if self.c_type not in finished_switch:
     # continue here with type construction
     if self.is_switch:
         if self.c_type not in finished_switch:
@@ -404,11 +509,11 @@ def _c_type_setup(self, name, postfix):
             for bitcase in self.bitcases:
                 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
                 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
             for bitcase in self.bitcases:
                 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
                 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
-                # no list with switch as element, so no call to 
+                # no list with switch as element, so no call to
                 # _c_iterator(field.type, field_name) necessary
 
                 # _c_iterator(field.type, field_name) necessary
 
-    if not self.is_bitcase:
-        if self.need_serialize:
+    if not self.is_case_or_bitcase:
+        if self.c_need_serialize:
             if self.c_serialize_name not in finished_serializers:
                 finished_serializers.append(self.c_serialize_name)
                 _c_serialize('serialize', self)
             if self.c_serialize_name not in finished_serializers:
                 finished_serializers.append(self.c_serialize_name)
                 _c_serialize('serialize', self)
@@ -416,36 +521,77 @@ def _c_type_setup(self, name, postfix):
                 # _unpack() and _unserialize() are only needed for special cases:
                 #   switch -> unpack
                 #   special cases -> unserialize
                 # _unpack() and _unserialize() are only needed for special cases:
                 #   switch -> unpack
                 #   special cases -> unserialize
-                if self.is_switch or self.var_followed_by_fixed_fields:
+                if self.is_switch or self.c_var_followed_by_fixed_fields:
                     _c_serialize('unserialize', self)
                     _c_serialize('unserialize', self)
-                    
-        if self.need_sizeof:
+
+        if self.c_need_sizeof:
             if self.c_sizeof_name not in finished_sizeof:
                 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()
 
             if self.c_sizeof_name not in finished_sizeof:
                 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):
+# 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)
-    if field is not None, append the field name as well
+    representing a valid field-access-expression in C (based on the context)
+    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
-        if '' == sep:
-            sep = '->'
-            if ((obj.is_bitcase and obj.has_name) or     # named bitcase
-                (obj.is_switch and len(obj.parents)>1)):
-                sep = '.'
-        prefix_str += sep
-    if field is not None:
-        prefix_str += _cpp(field.field_name)
+        prefix_str += last_sep + name
+        last_sep = sep
+
+    if field is None:
+        # add separator for access to a yet unknown field
+        prefix_str += last_sep
+    else:
+        if _c_field_needs_accessor(field):
+            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
 # _c_absolute_name
     return prefix_str
 # _c_absolute_name
-    
+
 def _c_helper_field_mapping(complex_type, prefix, flat=False):
     """
     generate absolute names, based on prefix, for all fields starting from complex_type
 def _c_helper_field_mapping(complex_type, prefix, flat=False):
     """
     generate absolute names, based on prefix, for all fields starting from complex_type
@@ -458,19 +604,19 @@ def _c_helper_field_mapping(complex_type, prefix, flat=False):
                 switch_name, switch_sep, switch_type = prefix[-1]
                 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
             else:
                 switch_name, switch_sep, switch_type = prefix[-1]
                 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
             else:
-                bitcase_prefix = prefix 
+                bitcase_prefix = prefix
 
             if (True==flat and not b.type.has_name) or False==flat:
                 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
     else:
         for f in complex_type.fields:
 
             if (True==flat and not b.type.has_name) or False==flat:
                 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
     else:
         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:
                 raise Exception("field name %s has been registered before" % f.field_name)
 
             all_fields[f.field_name] = (fname, f)
             if f.type.is_container and flat==False:
             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)
             if f.type.is_container and flat==False:
-                if f.type.is_bitcase and not f.type.has_name:
+                if f.type.is_case_or_bitcase and not f.type.has_name:
                     new_prefix = prefix
                 elif f.type.is_switch and len(f.type.parents)>1:
                     # nested switch gets another separator
                     new_prefix = prefix
                 elif f.type.is_switch and len(f.type.parents)>1:
                     # nested switch gets another separator
@@ -493,10 +639,10 @@ def _c_helper_resolve_field_names (prefix):
         name, sep, obj = p
         if ''==sep:
             # sep can be preset in prefix, if not, make a sensible guess
         name, sep, obj = p
         if ''==sep:
             # sep can be preset in prefix, if not, make a sensible guess
-            sep = '.' if (obj.is_switch or obj.is_bitcase) else '->'
+            sep = '.' if (obj.is_switch or obj.is_case_or_bitcase) else '->'
             # exception: 'toplevel' object (switch as well!) always have sep '->'
             sep = '->' if idx<1 else sep
             # exception: 'toplevel' object (switch as well!) always have sep '->'
             sep = '->' if idx<1 else sep
-        if not obj.is_bitcase or (obj.is_bitcase and obj.has_name):
+        if not obj.is_case_or_bitcase or (obj.is_case_or_bitcase and obj.has_name):
             tmp_prefix.append((name, sep, obj))
         all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
 
             tmp_prefix.append((name, sep, obj))
         all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
 
@@ -505,7 +651,7 @@ def _c_helper_resolve_field_names (prefix):
 
 def get_expr_fields(self):
     """
 
 def get_expr_fields(self):
     """
-    get the Fields referenced by switch or list expression 
+    get the Fields referenced by switch or list expression
     """
     def get_expr_field_names(expr):
         if expr.op is None:
     """
     def get_expr_field_names(expr):
         if expr.op is None:
@@ -520,7 +666,7 @@ def get_expr_fields(self):
             elif expr.op == 'popcount':
                 return get_expr_field_names(expr.rhs)
             elif expr.op == 'sumof':
             elif expr.op == 'popcount':
                 return get_expr_field_names(expr.rhs)
             elif expr.op == 'sumof':
-                # sumof expr references another list, 
+                # sumof expr references another list,
                 # we need that list's length field here
                 field = None
                 for f in expr.lenfield_parent.fields:
                 # we need that list's length field here
                 field = None
                 for f in expr.lenfield_parent.fields:
@@ -536,7 +682,7 @@ def get_expr_fields(self):
             else:
                 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
     # get_expr_field_names()
             else:
                 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
     # get_expr_field_names()
-    
+
     # resolve the field names with the parent structure(s)
     unresolved_fields_names = get_expr_field_names(self.expr)
 
     # resolve the field names with the parent structure(s)
     unresolved_fields_names = get_expr_field_names(self.expr)
 
@@ -549,7 +695,7 @@ def get_expr_fields(self):
     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)
     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)
-    
+
     resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
     return resolved_fields
 # get_expr_fields()
     resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
     return resolved_fields
 # get_expr_fields()
@@ -576,13 +722,38 @@ def resolve_expr_fields(complex_obj):
             unresolved.append(e)
     return unresolved
 # resolve_expr_fields()
             unresolved.append(e)
     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:
 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
     """
     functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
-    E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch 
-    expression. This function tries to resolve all fields within a structure, and returns the 
-    unresolved fields as the list of external parameters. 
+    E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch
+    expression. This function tries to resolve all fields within a structure, and returns the
+    unresolved fields as the list of external parameters.
     """
     def add_param(params, param):
         if param not in params:
     """
     def add_param(params, param):
         if param not in params:
@@ -601,9 +772,9 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
                 # field in the xcb_out structure
                 wire_fields.append(field)
         # fields like 'pad0' are skipped!
                 # field in the xcb_out structure
                 wire_fields.append(field)
         # fields like 'pad0' are skipped!
-               
+
     # in case of switch, parameters always contain any fields referenced in the switch expr
     # in case of switch, parameters always contain any fields referenced in the switch expr
-    # we do not need any variable size fields here, as the switch data type contains both 
+    # we do not need any variable size fields here, as the switch data type contains both
     # fixed and variable size fields
     if self.is_switch:
         param_fields = get_expr_fields(self)
     # fixed and variable size fields
     if self.is_switch:
         param_fields = get_expr_fields(self)
@@ -611,7 +782,7 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
     # _serialize()/_unserialize()/_unpack() function parameters
     # note: don't use set() for params, it is unsorted
     params = []
     # _serialize()/_unserialize()/_unpack() function parameters
     # note: don't use set() for params, it is unsorted
     params = []
-    
+
     # 1. the parameter for the void * buffer
     if  'serialize' == context:
         params.append(('void', '**', buffer_var))
     # 1. the parameter for the void * buffer
     if  'serialize' == context:
         params.append(('void', '**', buffer_var))
@@ -628,25 +799,25 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
     for p in param_fields:
         if self.is_switch:
             typespec = p.c_field_const_type
     for p in param_fields:
         if self.is_switch:
             typespec = p.c_field_const_type
-            pointerspec = p.c_pointer 
+            pointerspec = p.c_pointer
             add_param(params, (typespec, pointerspec, p.c_field_name))
         else:
             if p.visible and not p.wire and not p.auto:
                 typespec = p.c_field_type
                 pointerspec = ''
                 add_param(params, (typespec, pointerspec, p.c_field_name))
             add_param(params, (typespec, pointerspec, p.c_field_name))
         else:
             if p.visible and not p.wire and not p.auto:
                 typespec = p.c_field_type
                 pointerspec = ''
                 add_param(params, (typespec, pointerspec, p.c_field_name))
-  
+
     # 4. aux argument
     if 'serialize' == context:
         add_param(params, ('const %s' % self.c_type, '*', aux_var))
     # 4. aux argument
     if 'serialize' == context:
         add_param(params, ('const %s' % self.c_type, '*', aux_var))
-    elif 'unserialize' == context: 
+    elif 'unserialize' == context:
         add_param(params, ('%s' % self.c_type, '**', aux_var))
     elif 'unpack' == context:
         add_param(params, ('%s' % self.c_type, '*', aux_var))
 
     # 5. switch contains all variable size fields as struct members
     #    for other data types though, these have to be supplied separately
         add_param(params, ('%s' % self.c_type, '**', aux_var))
     elif 'unpack' == context:
         add_param(params, ('%s' % self.c_type, '*', aux_var))
 
     # 5. switch contains all variable size fields as struct members
     #    for other data types though, these have to be supplied separately
-    #    this is important for the special case of intermixed fixed and 
+    #    this is important for the special case of intermixed fixed and
     #    variable size fields
     if not self.is_switch and 'serialize' == context:
         for p in param_fields:
     #    variable size fields
     if not self.is_switch and 'serialize' == context:
         for p in param_fields:
@@ -656,9 +827,15 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
     return (param_fields, wire_fields, params)
 # get_serialize_params()
 
     return (param_fields, wire_fields, params)
 # get_serialize_params()
 
-def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
+def _c_serialize_helper_insert_padding(context, code_lines, space, postpone, is_case_or_bitcase):
     code_lines.append('%s    /* insert padding */' % space)
     code_lines.append('%s    /* insert padding */' % space)
-    code_lines.append('%s    xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
+    if is_case_or_bitcase:
+        code_lines.append(
+            '%s    xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);'
+            % space)
+    else:
+        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)
 
 #    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)
 
@@ -674,43 +851,56 @@ def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
 
         code_lines.append('%s        xcb_pad = 0;' % space)
         code_lines.append('%s    }' % space)
 
         code_lines.append('%s        xcb_pad = 0;' % space)
         code_lines.append('%s    }' % space)
-        
+
     code_lines.append('%s    xcb_block_len = 0;' % space)
     code_lines.append('%s    xcb_block_len = 0;' % space)
+    if is_case_or_bitcase:
+        code_lines.append('%s    xcb_padding_offset = 0;' % space)
 
     # keep tracking of xcb_parts entries for serialize
     return 1
 # _c_serialize_helper_insert_padding()
 
 
     # keep tracking of xcb_parts entries for serialize
     return 1
 # _c_serialize_helper_insert_padding()
 
-def _c_serialize_helper_switch(context, self, complex_name, 
-                               code_lines, temp_vars, 
+def _c_serialize_helper_switch(context, self, complex_name,
+                               code_lines, temp_vars,
                                space, prefix):
     count = 0
     switch_expr = _c_accessor_get_expr(self.expr, None)
 
                                space, prefix):
     count = 0
     switch_expr = _c_accessor_get_expr(self.expr, None)
 
-    for b in self.bitcases:            
+    for b in self.bitcases:
         len_expr = len(b.type.expr)
         len_expr = len(b.type.expr)
+
+        compare_operator = '&'
+        if b.type.is_case:
+            compare_operator = '=='
+        else:
+            compare_operator = '&'
+
         for n, expr in enumerate(b.type.expr):
             bitcase_expr = _c_accessor_get_expr(expr, None)
             # only one <enumref> in the <bitcase>
             if len_expr == 1:
         for n, expr in enumerate(b.type.expr):
             bitcase_expr = _c_accessor_get_expr(expr, None)
             # only one <enumref> in the <bitcase>
             if len_expr == 1:
-                code_lines.append('    if(%s & %s) {' % (switch_expr, bitcase_expr))
+                code_lines.append(
+                    '    if(%s %s %s) {' % (switch_expr, compare_operator, bitcase_expr))
             # multiple <enumref> in the <bitcase>
             elif n == 0: # first
             # multiple <enumref> in the <bitcase>
             elif n == 0: # first
-                code_lines.append('    if((%s & %s) ||' % (switch_expr, bitcase_expr))
+                code_lines.append(
+                    '    if((%s %s %s) ||' % (switch_expr, compare_operator, bitcase_expr))
             elif len_expr == (n + 1): # last
             elif len_expr == (n + 1): # last
-                code_lines.append('       (%s & %s)) {' % (switch_expr, bitcase_expr))
+                code_lines.append(
+                    '       (%s %s %s)) {' % (switch_expr, compare_operator, bitcase_expr))
             else: # between first and last
             else: # between first and last
-                code_lines.append('       (%s & %s) ||' % (switch_expr, bitcase_expr))
+                code_lines.append(
+                    '       (%s %s %s) ||' % (switch_expr, compare_operator, bitcase_expr))
 
         b_prefix = prefix
         if b.type.has_name:
             b_prefix = prefix + [(b.c_field_name, '.', b.type)]
 
         b_prefix = prefix
         if b.type.has_name:
             b_prefix = prefix + [(b.c_field_name, '.', b.type)]
-            
-        count += _c_serialize_helper_fields(context, b.type, 
-                                            code_lines, temp_vars, 
-                                            "%s    " % space, 
-                                            b_prefix, 
-                                            is_bitcase = True)
+
+        count += _c_serialize_helper_fields(context, b.type,
+                                            code_lines, temp_vars,
+                                            "%s    " % space,
+                                            b_prefix,
+                                            is_case_or_bitcase = True)
         code_lines.append('    }')
 
 #    if 'serialize' == context:
         code_lines.append('    }')
 
 #    if 'serialize' == context:
@@ -719,7 +909,7 @@ def _c_serialize_helper_switch(context, self, complex_name,
 #        # padding
 #        code_lines.append('%s    xcb_pad = -xcb_block_len & 3;' % space)
 #        code_lines.append('%s    xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
 #        # padding
 #        code_lines.append('%s    xcb_pad = -xcb_block_len & 3;' % space)
 #        code_lines.append('%s    xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
-   
+
     return count
 # _c_serialize_helper_switch
 
     return count
 # _c_serialize_helper_switch
 
@@ -730,12 +920,12 @@ def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, pr
     # switch is handled by this function as a special case
     param_fields, wire_fields, params = get_serialize_params(context, self)
     field_mapping = _c_helper_field_mapping(self, prefix)
     # switch is handled by this function as a special case
     param_fields, wire_fields, params = get_serialize_params(context, self)
     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():
     # all switch expr fields must be given as parameters
     args = get_expr_fields(field.type)
 
     # find the parameters that need to be passed to _serialize()/_unpack():
     # all switch expr fields must be given as parameters
     args = get_expr_fields(field.type)
-    # length fields for variable size types in switch, normally only some of need 
+    # length fields for variable size types in switch, normally only some of need
     # need to be passed as parameters
     switch_len_fields = resolve_expr_fields(field.type)
 
     # need to be passed as parameters
     switch_len_fields = resolve_expr_fields(field.type)
 
@@ -745,7 +935,7 @@ def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, pr
     if len(bitcase_unresolved) != 0:
         raise Exception('unresolved fields within bitcase is not supported at this point')
 
     if len(bitcase_unresolved) != 0:
         raise Exception('unresolved fields within bitcase is not supported at this point')
 
-    # get the C names for the parameters  
+    # get the C names for the parameters
     c_field_names = ''
     for a in switch_len_fields:
         c_field_names += "%s, " % field_mapping[a.c_field_name][0]
     c_field_names = ''
     for a in switch_len_fields:
         c_field_names += "%s, " % field_mapping[a.c_field_name][0]
@@ -755,39 +945,53 @@ def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, pr
     # call _serialize()/_unpack() to determine the actual size
     if 'serialize' == context:
         length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
     # call _serialize()/_unpack() to determine the actual size
     if 'serialize' == context:
         length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
-                                       c_field_names, prefix_str, field.c_field_name) 
+                                       c_field_names, prefix_str, field.c_field_name)
     elif context in ('unserialize', 'unpack'):
     elif context in ('unserialize', 'unpack'):
-        length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name, 
+        length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
                                            c_field_names, prefix_str, field.c_field_name)
                                            c_field_names, prefix_str, field.c_field_name)
+    elif 'sizeof' == context:
+        # remove trailing ", " from c_field_names because it will be used at end of arglist
+        my_c_field_names = c_field_names[:-2]
+        length = "%s(xcb_tmp, %s)" % (field.type.c_sizeof_name, my_c_field_names)
 
     return length
 # _c_serialize_helper_switch_field()
 
 
     return length
 # _c_serialize_helper_switch_field()
 
-def _c_serialize_helper_list_field(context, self, field, 
-                                   code_lines, temp_vars, 
+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):
     """
     helper function to cope with lists of variable length
     """
     expr = field.type.expr
                                    space, prefix):
     """
     helper function to cope with lists of variable length
     """
     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_names = [p[2] for p in params]
     param_fields, wire_fields, params = get_serialize_params('sizeof', self)
     param_names = [p[2] for p in params]
-    
+
     expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
     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))
     expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
     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_mapping[r] = (r, None)
     field_mapping = {}
     for r in resolved:
         field_mapping[r] = (r, None)
-    
+
     if len(unresolved)>0:
         tmp_prefix = prefix
         if len(tmp_prefix)==0:
     if len(unresolved)>0:
         tmp_prefix = prefix
         if len(tmp_prefix)==0:
-            raise Exception("found an empty prefix while resolving expr field names for list %s", 
-                            field.c_field_name)        
-        
+            raise Exception("found an empty prefix while resolving expr field names for list %s",
+                            field.c_field_name)
+
         field_mapping.update(_c_helper_resolve_field_names(prefix))
         resolved += list(filter(lambda x: x in field_mapping, unresolved))
         unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
         field_mapping.update(_c_helper_resolve_field_names(prefix))
         resolved += list(filter(lambda x: x in field_mapping, unresolved))
         unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
@@ -799,8 +1003,16 @@ def _c_serialize_helper_list_field(context, self, field,
     # default: list with fixed size elements
     length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
 
     # default: list with fixed size elements
     length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
 
-    # 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 = ''
         if context in ('unserialize', 'sizeof', 'unpack'):
             int_i = '    unsigned int i;'
         length = ''
         if context in ('unserialize', 'sizeof', 'unpack'):
             int_i = '    unsigned int i;'
@@ -812,66 +1024,70 @@ 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))
             # 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        xcb_block_len += xcb_tmp_len;" % space)
             code_lines.append("%s        xcb_tmp += xcb_tmp_len;" % space)
-            code_lines.append("%s    }" % space)                  
-      
+            code_lines.append("%s    }" % space)
+
         elif 'serialize' == context:
             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))
         elif 'serialize' == context:
             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)
             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)
-            
+
     return length
 # _c_serialize_helper_list_field()
 
     return length
 # _c_serialize_helper_list_field()
 
-def _c_serialize_helper_fields_fixed_size(context, self, field, 
-                                          code_lines, temp_vars, 
+def _c_serialize_helper_fields_fixed_size(context, self, field,
+                                          code_lines, temp_vars,
                                           space, prefix):
     # keep the C code a bit more readable by giving the field name
                                           space, prefix):
     # keep the C code a bit more readable by giving the field name
-    if not self.is_bitcase:
+    if not self.is_case_or_bitcase:
         code_lines.append('%s    /* %s.%s */' % (space, self.c_type, field.c_field_name))
     else:
         scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
         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, self.c_type, field.c_field_name))
     else:
         scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
         typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_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()
     length = "sizeof(%s)" % field.c_field_type
 
     if context in ('unserialize', 'unpack', 'sizeof'):
         # default: simple cast
     # default for simple cases: call sizeof()
     length = "sizeof(%s)" % field.c_field_type
 
     if context in ('unserialize', 'unpack', 'sizeof'):
         # default: simple cast
-        value = '    %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type) 
-        
+        value = '    %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
+
         # padding - we could probably just ignore it
         if field.type.is_pad and field.type.nmemb > 1:
             value = ''
             for i in range(field.type.nmemb):
         # padding - we could probably just ignore it
         if field.type.is_pad and field.type.nmemb > 1:
             value = ''
             for i in range(field.type.nmemb):
-                code_lines.append('%s    %s[%d] = *(%s *)xcb_tmp;' % 
-                                  (space, abs_field_name, i, field.c_field_type)) 
+                code_lines.append('%s    %s[%d] = *(%s *)xcb_tmp;' %
+                                  (space, abs_field_name, i, field.c_field_type))
             # total padding = sizeof(pad0) * nmemb
             length += " * %d" % field.type.nmemb
 
             # total padding = sizeof(pad0) * nmemb
             length += " * %d" % field.type.nmemb
 
-        if field.type.is_list:
-            # no such case in the protocol, cannot be tested and therefore ignored for now
-            raise Exception('list with fixed number of elemens unhandled in _unserialize()')
+        elif field.type.is_list:
+            # list with fixed number of elements
+            # length of array = sizeof(arrayElementType) * nmemb
+            length += " * %d" % field.type.nmemb
+            # use memcpy because C cannot assign whole arrays with operator=
+            value = '    memcpy(%s, xcb_tmp, %s);' % (abs_field_name, length)
+
 
     elif 'serialize' == context:
 
     elif 'serialize' == context:
-        value = '    xcb_parts[xcb_parts_idx].iov_base = (char *) ' 
+        value = '    xcb_parts[xcb_parts_idx].iov_base = (char *) '
 
         if field.type.is_expr:
             # need to register a temporary variable for the expression in case we know its type
             if field.type.c_type is None:
 
         if field.type.is_expr:
             # need to register a temporary variable for the expression in case we know its type
             if field.type.c_type is None:
-                raise Exception("type for field '%s' (expression '%s') unkown" % 
+                raise Exception("type for field '%s' (expression '%s') unkown" %
                                 (field.field_name, _c_accessor_get_expr(field.type.expr)))
                                 (field.field_name, _c_accessor_get_expr(field.type.expr)))
-            
-            temp_vars.append('    %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name), 
+
+            temp_vars.append('    %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
                                                            _c_accessor_get_expr(field.type.expr, prefix)))
             value += "&xcb_expr_%s;" % _cpp(field.field_name)
 
                                                            _c_accessor_get_expr(field.type.expr, prefix)))
             value += "&xcb_expr_%s;" % _cpp(field.field_name)
 
@@ -896,25 +1112,25 @@ def _c_serialize_helper_fields_fixed_size(context, self, field,
     return (value, length)
 # _c_serialize_helper_fields_fixed_size()
 
     return (value, length)
 # _c_serialize_helper_fields_fixed_size()
 
-def _c_serialize_helper_fields_variable_size(context, self, field, 
-                                             code_lines, temp_vars, 
+def _c_serialize_helper_fields_variable_size(context, self, field,
+                                             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'):
         value = ''
         var_field_name = 'xcb_tmp'
 
     if context in ('unserialize', 'unpack', 'sizeof'):
         value = ''
         var_field_name = 'xcb_tmp'
-        
+
         # special case: intermixed fixed and variable size fields
         # special case: intermixed fixed and variable size fields
-        if self.var_followed_by_fixed_fields and 'unserialize' == context:
+        if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
             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:
             value = '    %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
             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:
             value = '    %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
-            
+
     elif 'serialize' == context:
     elif 'serialize' == context:
-        # variable size fields appear as parameters to _serialize() if the 
+        # variable size fields appear as parameters to _serialize() if the
         # 'toplevel' container is not a switch
         prefix_string = prefix_str if prefix[0][2].is_switch else ''
         var_field_name = "%s%s" % (prefix_string, field.c_field_name)
         # 'toplevel' container is not a switch
         prefix_string = prefix_str if prefix[0][2].is_switch else ''
         var_field_name = "%s%s" % (prefix_string, field.c_field_name)
@@ -929,19 +1145,19 @@ def _c_serialize_helper_fields_variable_size(context, self, field,
             # in any context, list is already a pointer, so the default assignment is ok
             code_lines.append("%s%s" % (space, value))
             value = ''
             # in any context, list is already a pointer, so the default assignment is ok
             code_lines.append("%s%s" % (space, value))
             value = ''
-        length = _c_serialize_helper_list_field(context, self, field, 
-                                                code_lines, temp_vars, 
+        length = _c_serialize_helper_list_field(context, self, field,
+                                                code_lines, temp_vars,
                                                 space, prefix)
                                                 space, prefix)
-        
+
     elif field.type.is_switch:
         value = ''
         if context == 'serialize':
             # the _serialize() function allocates the correct amount memory if given a NULL pointer
             value = '    xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
     elif field.type.is_switch:
         value = ''
         if context == 'serialize':
             # the _serialize() function allocates the correct amount memory if given a NULL pointer
             value = '    xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
-        length = _c_serialize_helper_switch_field(context, self, field, 
-                                                  'xcb_parts[xcb_parts_idx].iov_base', 
+        length = _c_serialize_helper_switch_field(context, self, field,
+                                                  'xcb_parts[xcb_parts_idx].iov_base',
                                                   prefix)
                                                   prefix)
-        
+
     else:
         # in all remaining special cases - call _sizeof()
         length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
     else:
         # in all remaining special cases - call _sizeof()
         length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
@@ -949,65 +1165,76 @@ def _c_serialize_helper_fields_variable_size(context, self, field,
     return (value, length)
 # _c_serialize_helper_fields_variable_size
 
     return (value, length)
 # _c_serialize_helper_fields_variable_size
 
-def _c_serialize_helper_fields(context, self, 
-                               code_lines, temp_vars, 
-                               space, prefix, is_bitcase):
+def _c_serialize_helper_fields(context, self,
+                               code_lines, temp_vars,
+                               space, prefix, is_case_or_bitcase):
     count = 0
     need_padding = False
     prev_field_was_variable = False
 
     count = 0
     need_padding = False
     prev_field_was_variable = False
 
+    _c_pre.push_indent(space + '    ')
+
     for field in self.fields:
         if not field.visible:
             if not ((field.wire and not field.auto) or 'unserialize' == context):
                 continue
 
     for field in self.fields:
         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 
+        # switch/bitcase: fixed size fields must be considered explicitly
         if field.type.fixed_size():
         if field.type.fixed_size():
-            if self.is_bitcase or self.var_followed_by_fixed_fields:
+            if self.is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
                 if prev_field_was_variable and need_padding:
                     # insert padding
                 if prev_field_was_variable and need_padding:
                     # insert padding
-#                    count += _c_serialize_helper_insert_padding(context, code_lines, space, 
-#                                                                self.var_followed_by_fixed_fields)
+#                    count += _c_serialize_helper_insert_padding(context, code_lines, space,
+#                                                                self.c_var_followed_by_fixed_fields)
                     prev_field_was_variable = False
 
                 # prefix for fixed size fields
                 fixed_prefix = prefix
 
                     prev_field_was_variable = False
 
                 # prefix for fixed size fields
                 fixed_prefix = prefix
 
-                value, length = _c_serialize_helper_fields_fixed_size(context, self, field, 
-                                                                      code_lines, temp_vars, 
+                value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
+                                                                      code_lines, temp_vars,
                                                                       space, fixed_prefix)
             else:
                 continue
 
         # fields with variable size
         else:
                                                                       space, fixed_prefix)
             else:
                 continue
 
         # fields with variable size
         else:
-            # switch/bitcase: always calculate padding before and after variable sized fields
-            if need_padding or is_bitcase:
-                count += _c_serialize_helper_insert_padding(context, code_lines, space, 
-                                                            self.var_followed_by_fixed_fields)
-
-            value, length = _c_serialize_helper_fields_variable_size(context, self, field, 
-                                                                     code_lines, temp_vars, 
-                                                                     space, prefix)
-            prev_field_was_variable = True
-        
+            if field.type.is_pad:
+                # Variable length pad is <pad align= />
+                code_lines.append('%s    xcb_align_to = %d;' % (space, field.type.align))
+                count += _c_serialize_helper_insert_padding(context, code_lines, space,
+                                                            self.c_var_followed_by_fixed_fields,
+                                                            is_case_or_bitcase)
+                continue
+            else:
+                # switch/bitcase: always calculate padding before and after variable sized fields
+                if need_padding or is_case_or_bitcase:
+                    count += _c_serialize_helper_insert_padding(context, code_lines, space,
+                                                                self.c_var_followed_by_fixed_fields,
+                                                                is_case_or_bitcase)
+
+                value, length = _c_serialize_helper_fields_variable_size(context, self, field,
+                                                                         code_lines, temp_vars,
+                                                                         space, prefix)
+                prev_field_was_variable = True
+
         # save (un)serialization C code
         if '' != value:
         # save (un)serialization C code
         if '' != value:
-            code_lines.append('%s%s' % (space, value))    
-        
+            code_lines.append('%s%s' % (space, value))
+
         if field.type.fixed_size():
         if field.type.fixed_size():
-            if is_bitcase or self.var_followed_by_fixed_fields:
+            if is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
                 # keep track of (un)serialized object's size
                 code_lines.append('%s    xcb_block_len += %s;' % (space, length))
                 if context in ('unserialize', 'unpack', 'sizeof'):
                     code_lines.append('%s    xcb_tmp += %s;' % (space, length))
                 # keep track of (un)serialized object's size
                 code_lines.append('%s    xcb_block_len += %s;' % (space, length))
                 if context in ('unserialize', 'unpack', 'sizeof'):
                     code_lines.append('%s    xcb_tmp += %s;' % (space, length))
-        else: 
+        else:
             # variable size objects or bitcase:
             #   value & length might have been inserted earlier for special cases
             if '' != length:
                 # special case: intermixed fixed and variable size fields
             # variable size objects or bitcase:
             #   value & length might have been inserted earlier for special cases
             if '' != length:
                 # special case: intermixed fixed and variable size fields
-                if (not field.type.fixed_size() and 
-                    self.var_followed_by_fixed_fields and 'unserialize' == context):
+                if (not field.type.fixed_size() and
+                    self.c_var_followed_by_fixed_fields and 'unserialize' == context):
                     temp_vars.append('    int %s_len;' % field.c_field_name)
                     code_lines.append('%s    %s_len = %s;' % (space, field.c_field_name, length))
                     code_lines.append('%s    xcb_block_len += %s_len;' % (space, field.c_field_name))
                     temp_vars.append('    int %s_len;' % field.c_field_name)
                     code_lines.append('%s    %s_len = %s;' % (space, field.c_field_name, length))
                     code_lines.append('%s    xcb_block_len += %s_len;' % (space, field.c_field_name))
@@ -1017,24 +1244,31 @@ def _c_serialize_helper_fields(context, self,
                     # increase pointer into the byte stream accordingly
                     if context in ('unserialize', 'sizeof', 'unpack'):
                         code_lines.append('%s    xcb_tmp += xcb_block_len;' % space)
                     # increase pointer into the byte stream accordingly
                     if context in ('unserialize', 'sizeof', 'unpack'):
                         code_lines.append('%s    xcb_tmp += xcb_block_len;' % space)
-                        
+
         if 'serialize' == context:
             if '' != length:
                 code_lines.append('%s    xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
             code_lines.append('%s    xcb_parts_idx++;' % space)
             count += 1
 
         if 'serialize' == context:
             if '' != length:
                 code_lines.append('%s    xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
             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))
+        code_lines.append(
+            '%s    xcb_align_to = ALIGNOF(%s);'
+             % (space,
+                 'char'
+                  if field.c_field_type == 'void' or field.type.is_switch
+                  else field.c_field_type))
 
         need_padding = True
 
         need_padding = True
-        if self.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()
 
 
-def _c_serialize_helper(context, complex_type, 
-                        code_lines, temp_vars, 
+def _c_serialize_helper(context, complex_type,
+                        code_lines, temp_vars,
                         space='', prefix=[]):
     # count tracks the number of fields to serialize
     count = 0
                         space='', prefix=[]):
     # count tracks the number of fields to serialize
     count = 0
@@ -1044,38 +1278,38 @@ def _c_serialize_helper(context, complex_type,
         complex_name = complex_type.name
     else:
         self = complex_type
         complex_name = complex_type.name
     else:
         self = complex_type
-        if self.var_followed_by_fixed_fields and 'unserialize' == context:
+        if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
             complex_name = 'xcb_out'
         else:
             complex_name = '_aux'
             complex_name = 'xcb_out'
         else:
             complex_name = '_aux'
-    
+
     # special case: switch is serialized by evaluating each bitcase separately
     if self.is_switch:
     # special case: switch is serialized by evaluating each bitcase separately
     if self.is_switch:
-        count += _c_serialize_helper_switch(context, self, complex_name, 
-                                            code_lines, temp_vars, 
+        count += _c_serialize_helper_switch(context, self, complex_name,
+                                            code_lines, temp_vars,
                                             space, prefix)
 
     # all other data types can be evaluated one field a time
                                             space, prefix)
 
     # all other data types can be evaluated one field a time
-    else: 
+    else:
         # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
         # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
-        if context in ('unserialize', 'unpack', 'sizeof') and not self.var_followed_by_fixed_fields:
+        if context in ('unserialize', 'unpack', 'sizeof') and not self.c_var_followed_by_fixed_fields:
             code_lines.append('%s    xcb_block_len += sizeof(%s);' % (space, self.c_type))
             code_lines.append('%s    xcb_tmp += xcb_block_len;' % space)
             code_lines.append('%s    xcb_buffer_len += xcb_block_len;' % space)
             code_lines.append('%s    xcb_block_len = 0;' % space)
 
             code_lines.append('%s    xcb_block_len += sizeof(%s);' % (space, self.c_type))
             code_lines.append('%s    xcb_tmp += xcb_block_len;' % space)
             code_lines.append('%s    xcb_buffer_len += xcb_block_len;' % space)
             code_lines.append('%s    xcb_block_len = 0;' % space)
 
-        count += _c_serialize_helper_fields(context, self, 
-                                            code_lines, temp_vars, 
+        count += _c_serialize_helper_fields(context, self,
+                                            code_lines, temp_vars,
                                             space, prefix, False)
     # "final padding"
                                             space, prefix, False)
     # "final padding"
-    count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
+    count += _c_serialize_helper_insert_padding(context, code_lines, space, False, self.is_switch)
 
 
-    return count    
+    return count
 # _c_serialize_helper()
 
 def _c_serialize(context, self):
     """
 # _c_serialize_helper()
 
 def _c_serialize(context, self):
     """
-    depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof() 
+    depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
     for the ComplexType variable self
     """
     _h_setlevel(1)
     for the ComplexType variable self
     """
     _h_setlevel(1)
@@ -1088,25 +1322,25 @@ def _c_serialize(context, self):
     if self.is_switch and 'unserialize' == context:
         context = 'unpack'
 
     if self.is_switch and 'unserialize' == context:
         context = 'unpack'
 
-    cases = { 'serialize'   : self.c_serialize_name, 
-              'unserialize' : self.c_unserialize_name, 
-              'unpack'      : self.c_unpack_name, 
+    cases = { 'serialize'   : self.c_serialize_name,
+              'unserialize' : self.c_unserialize_name,
+              'unpack'      : self.c_unpack_name,
               'sizeof'      : self.c_sizeof_name }
     func_name = cases[context]
               'sizeof'      : self.c_sizeof_name }
     func_name = cases[context]
-            
+
     param_fields, wire_fields, params = get_serialize_params(context, self)
     variable_size_fields = 0
     # maximum space required for type definition of function arguments
     maxtypelen = 0
 
     param_fields, wire_fields, params = get_serialize_params(context, self)
     variable_size_fields = 0
     # maximum space required for type definition of function arguments
     maxtypelen = 0
 
-    # determine N(variable_fields) 
+    # determine N(variable_fields)
     for field in param_fields:
         # if self.is_switch, treat all fields as if they are variable sized
         if not field.type.fixed_size() or self.is_switch:
             variable_size_fields += 1
     # determine maxtypelen
     for p in params:
     for field in param_fields:
         # if self.is_switch, treat all fields as if they are variable sized
         if not field.type.fixed_size() or self.is_switch:
             variable_size_fields += 1
     # determine maxtypelen
     for p in params:
-        maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))    
+        maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
 
     # write to .c/.h
     indent = ' '*(len(func_name)+2)
 
     # write to .c/.h
     indent = ' '*(len(func_name)+2)
@@ -1128,8 +1362,10 @@ def _c_serialize(context, self):
     temp_vars = []
     prefix = []
 
     temp_vars = []
     prefix = []
 
+    _c_pre.redirect_start(code_lines, temp_vars)
+
     if 'serialize' == context:
     if 'serialize' == context:
-        if not self.is_switch and not self.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('    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('    %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)
@@ -1138,13 +1374,15 @@ def _c_serialize(context, self):
             _c('    char *xcb_out = *_buffer;')
             _c('    unsigned int xcb_buffer_len = 0;')
             _c('    unsigned int xcb_align_to = 0;')
             _c('    char *xcb_out = *_buffer;')
             _c('    unsigned int xcb_buffer_len = 0;')
             _c('    unsigned int xcb_align_to = 0;')
+        if self.is_switch:
+            _c('    unsigned int xcb_padding_offset = ((size_t)xcb_out) & 7;')
         prefix = [('_aux', '->', self)]
         aux_ptr = 'xcb_out'
 
     elif context in ('unserialize', 'unpack'):
         _c('    char *xcb_tmp = (char *)_buffer;')
         if not self.is_switch:
         prefix = [('_aux', '->', self)]
         aux_ptr = 'xcb_out'
 
     elif context in ('unserialize', 'unpack'):
         _c('    char *xcb_tmp = (char *)_buffer;')
         if not self.is_switch:
-            if not self.var_followed_by_fixed_fields:
+            if not self.c_var_followed_by_fixed_fields:
                 _c('    const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
                 prefix = [('_aux', '->', self)]
             else:
                 _c('    const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
                 prefix = [('_aux', '->', self)]
             else:
@@ -1161,6 +1399,8 @@ def _c_serialize(context, self):
         _c('    unsigned int xcb_block_len = 0;')
         _c('    unsigned int xcb_pad = 0;')
         _c('    unsigned int xcb_align_to = 0;')
         _c('    unsigned int xcb_block_len = 0;')
         _c('    unsigned int xcb_pad = 0;')
         _c('    unsigned int xcb_align_to = 0;')
+        if self.is_switch:
+            _c('    unsigned int xcb_padding_offset = ((size_t)_buffer) & 7;')
 
     elif 'sizeof' == context:
         param_names = [p[2] for p in params]
 
     elif 'sizeof' == context:
         param_names = [p[2] for p in params]
@@ -1169,22 +1409,26 @@ def _c_serialize(context, self):
             _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('}')
             _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('}')
+            _c_pre.redirect_end()
             return
             return
-        elif self.var_followed_by_fixed_fields:
+        elif self.c_var_followed_by_fixed_fields:
             # special case: call _unserialize()
             _c('    return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
             _c('}')
             # special case: call _unserialize()
             _c('    return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
             _c('}')
+            _c_pre.redirect_end()
             return
         else:
             _c('    char *xcb_tmp = (char *)_buffer;')
             prefix = [('_aux', '->', self)]
             return
         else:
             _c('    char *xcb_tmp = (char *)_buffer;')
             prefix = [('_aux', '->', self)]
+            if self.is_switch:
+                _c('    unsigned int xcb_padding_offset = 0;')
 
     count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
     # update variable size fields (only important for context=='serialize'
     variable_size_fields = count
     if 'serialize' == context:
         temp_vars.append('    unsigned int xcb_pad = 0;')
 
     count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
     # update variable size fields (only important for context=='serialize'
     variable_size_fields = count
     if 'serialize' == context:
         temp_vars.append('    unsigned int xcb_pad = 0;')
-        temp_vars.append('    char xcb_pad0[3] = {0, 0, 0};') 
+        temp_vars.append('    char xcb_pad0[3] = {0, 0, 0};')
         temp_vars.append('    struct iovec xcb_parts[%d];' % count)
         temp_vars.append('    unsigned int xcb_parts_idx = 0;')
         temp_vars.append('    unsigned int xcb_block_len = 0;')
         temp_vars.append('    struct iovec xcb_parts[%d];' % count)
         temp_vars.append('    unsigned int xcb_parts_idx = 0;')
         temp_vars.append('    unsigned int xcb_block_len = 0;')
@@ -1193,20 +1437,22 @@ def _c_serialize(context, self):
     elif 'sizeof' == context:
         # neither switch nor intermixed fixed and variable size fields:
         # evaluate parameters directly
     elif 'sizeof' == context:
         # neither switch nor intermixed fixed and variable size fields:
         # evaluate parameters directly
-        if not (self.is_switch or self.var_followed_by_fixed_fields):
+        if not (self.is_switch or self.c_var_followed_by_fixed_fields):
 
             # look if we have to declare an '_aux' variable at all
             if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
 
             # look if we have to declare an '_aux' variable at all
             if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
-                if not self.var_followed_by_fixed_fields:
+                if not self.c_var_followed_by_fixed_fields:
                     _c('    const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
                 else:
                     _c('    %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
 
             _c('    unsigned int xcb_buffer_len = 0;')
             _c('    unsigned int xcb_block_len = 0;')
                     _c('    const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
                 else:
                     _c('    %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
 
             _c('    unsigned int xcb_buffer_len = 0;')
             _c('    unsigned int xcb_block_len = 0;')
-            _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('')
     for t in temp_vars:
         _c(t)
     _c('')
     for t in temp_vars:
         _c(t)
@@ -1215,7 +1461,7 @@ def _c_serialize(context, self):
         _c(l)
 
     # variable sized fields have been collected, now
         _c(l)
 
     # variable sized fields have been collected, now
-    # allocate memory and copy everything into a continuous memory area 
+    # 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
     # note: this is not necessary in case of unpack
     if context in ('serialize', 'unserialize'):
         # unserialize: check for sizeof-only invocation
@@ -1235,13 +1481,13 @@ def _c_serialize(context, self):
 
         # serialize: handle variable size fields in a loop
         if 'serialize' == context:
 
         # serialize: handle variable size fields in a loop
         if 'serialize' == context:
-            if not self.is_switch and not self.var_followed_by_fixed_fields:
+            if not self.is_switch and not self.c_var_followed_by_fixed_fields:
                 if len(wire_fields)>0:
                     _c('    *xcb_out = *_aux;')
             # copy variable size fields into the buffer
             if variable_size_fields > 0:
                 # xcb_out padding
                 if len(wire_fields)>0:
                     _c('    *xcb_out = *_aux;')
             # copy variable size fields into the buffer
             if variable_size_fields > 0:
                 # xcb_out padding
-                if not self.is_switch and not self.var_followed_by_fixed_fields:
+                if not self.is_switch and not self.c_var_followed_by_fixed_fields:
                     _c('    xcb_tmp = (char*)++xcb_out;')
                     _c('    xcb_tmp += xcb_out_pad;')
                 else:
                     _c('    xcb_tmp = (char*)++xcb_out;')
                     _c('    xcb_tmp += xcb_out_pad;')
                 else:
@@ -1254,7 +1500,7 @@ def _c_serialize(context, self):
                 _c('        if (0 != xcb_parts[i].iov_len)')
                 _c('            xcb_tmp += xcb_parts[i].iov_len;')
                 _c('    }')
                 _c('        if (0 != xcb_parts[i].iov_len)')
                 _c('            xcb_tmp += xcb_parts[i].iov_len;')
                 _c('    }')
-            
+
         # unserialize: assign variable size fields individually
         if 'unserialize' == context:
             _c('    xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
         # unserialize: assign variable size fields individually
         if 'unserialize' == context:
             _c('    xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
@@ -1264,7 +1510,7 @@ def _c_serialize(context, self):
                     _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('    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('}')
     _c('')
     _c('    return xcb_buffer_len;')
     _c('}')
@@ -1299,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))
     _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)
     _h('} %s;', self.c_iterator_type)
 
     _h_setlevel(1)
@@ -1313,16 +1567,6 @@ def _c_iterator(self, name):
     _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
     _h(' */')
     _c('')
     _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
     _h(' */')
     _c('')
-    _hc('')
-    _hc('/*****************************************************************************')
-    _hc(' **')
-    _hc(' ** void %s', self.c_next_name)
-    _hc(' ** ')
-    _hc(' ** @param %s *i', self.c_iterator_type)
-    _hc(' ** @returns void')
-    _hc(' **')
-    _hc(' *****************************************************************************/')
-    _hc(' ')
     _hc('void')
     _h('%s (%s *i  /**< */);', self.c_next_name, self.c_iterator_type)
     _c('%s (%s *i  /**< */)', self.c_next_name, self.c_iterator_type)
     _hc('void')
     _h('%s (%s *i  /**< */);', self.c_next_name, self.c_iterator_type)
     _c('%s (%s *i  /**< */)', self.c_next_name, self.c_iterator_type)
@@ -1333,12 +1577,17 @@ def _c_iterator(self, name):
 
         if self.is_union:
             # FIXME - how to determine the size of a variable size union??
 
         if self.is_union:
             # FIXME - how to determine the size of a variable size union??
-            _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.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));', 
-                   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'))
                 _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'))
@@ -1364,16 +1613,6 @@ def _c_iterator(self, name):
     _h(' * last element.')
     _h(' */')
     _c('')
     _h(' * last element.')
     _h(' */')
     _c('')
-    _hc('')
-    _hc('/*****************************************************************************')
-    _hc(' **')
-    _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
-    _hc(' ** ')
-    _hc(' ** @param %s i', self.c_iterator_type)
-    _hc(' ** @returns xcb_generic_iterator_t')
-    _hc(' **')
-    _hc(' *****************************************************************************/')
-    _hc(' ')
     _hc('xcb_generic_iterator_t')
     _h('%s (%s i  /**< */);', self.c_end_name, self.c_iterator_type)
     _c('%s (%s i  /**< */)', self.c_end_name, self.c_iterator_type)
     _hc('xcb_generic_iterator_t')
     _h('%s (%s i  /**< */);', self.c_end_name, self.c_iterator_type)
     _c('%s (%s i  /**< */)', self.c_end_name, self.c_iterator_type)
@@ -1397,7 +1636,7 @@ def _c_iterator(self, name):
 def _c_accessor_get_length(expr, field_mapping=None):
     '''
     Figures out what C code is needed to get a length field.
 def _c_accessor_get_length(expr, field_mapping=None):
     '''
     Figures out what C code is needed to get a length field.
-    The field_mapping parameter can be used to change the absolute name of a length field. 
+    The field_mapping parameter can be used to change the absolute name of a length field.
     For fields that follow a variable-length field, use the accessor.
     Otherwise, just reference the structure field directly.
     '''
     For fields that follow a variable-length field, use the accessor.
     Otherwise, just reference the structure field directly.
     '''
@@ -1406,13 +1645,8 @@ def _c_accessor_get_length(expr, field_mapping=None):
     if lenfield_name is not None:
         if field_mapping is not None:
             lenfield_name = field_mapping[lenfield_name][0]
     if lenfield_name is not 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 <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
-        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)
         return lenfield_name
     else:
         return str(expr.nmemb)
@@ -1420,7 +1654,7 @@ def _c_accessor_get_length(expr, field_mapping=None):
 def _c_accessor_get_expr(expr, field_mapping):
     '''
     Figures out what C code is needed to get the length of a list field.
 def _c_accessor_get_expr(expr, field_mapping):
     '''
     Figures out what C code is needed to get the length of a list field.
-    The field_mapping parameter can be used to change the absolute name of a length field. 
+    The field_mapping parameter can be used to change the absolute name of a length field.
     Recurses for math operations.
     Returns bitcount for value-mask fields.
     Otherwise, uses the value of the length field.
     Recurses for math operations.
     Returns bitcount for value-mask fields.
     Otherwise, uses the value of the length field.
@@ -1449,12 +1683,68 @@ def _c_accessor_get_expr(expr, field_mapping):
             raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
         list_name = field_mapping[field.c_field_name][0]
         c_length_func = "%s(%s)" % (field.c_length_name, list_name)
             raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
         list_name = field_mapping[field.c_field_name][0]
         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) + 
-                ' ' + expr.op + ' ' + 
+        return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
+                ' ' + expr.op + ' ' +
                 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
     elif expr.bitfield:
         return 'xcb_popcount(' + lenexp + ')'
                 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
     elif expr.bitfield:
         return 'xcb_popcount(' + lenexp + ')'
@@ -1474,23 +1764,13 @@ def _c_accessors_field(self, field):
 
     # special case: switch
     switch_obj = self if self.is_switch else None
 
     # special case: switch
     switch_obj = self if self.is_switch else None
-    if self.is_bitcase:
+    if self.is_case_or_bitcase:
         switch_obj = self.parents[-1]
     if switch_obj is not None:
         c_type = switch_obj.c_type
 
     if field.type.is_simple:
         _hc('')
         switch_obj = self.parents[-1]
     if switch_obj is not None:
         c_type = switch_obj.c_type
 
     if field.type.is_simple:
         _hc('')
-        _hc('')
-        _hc('/*****************************************************************************')
-        _hc(' ** ')
-        _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
-        _hc(' ** ')
-        _hc(' ** @param const %s *R', c_type)
-        _hc(' ** @returns %s', field.c_field_type)
-        _hc(' **')
-        _hc(' *****************************************************************************/')
-        _hc(' ')
         _hc('%s', field.c_field_type)
         _h('%s (const %s *R  /**< */);', field.c_accessor_name, c_type)
         _c('%s (const %s *R  /**< */)', field.c_accessor_name, c_type)
         _hc('%s', field.c_field_type)
         _h('%s (const %s *R  /**< */);', field.c_accessor_name, c_type)
         _c('%s (const %s *R  /**< */)', field.c_accessor_name, c_type)
@@ -1499,21 +1779,11 @@ def _c_accessors_field(self, field):
             _c('    return (%s *) (R + 1);', field.c_field_type)
         else:
             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
             _c('    return (%s *) (R + 1);', field.c_field_type)
         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);', 
+            _c('    return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
                field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
         _c('}')
     else:
         _hc('')
                field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
         _c('}')
     else:
         _hc('')
-        _hc('')
-        _hc('/*****************************************************************************')
-        _hc(' **')
-        _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
-        _hc(' ** ')
-        _hc(' ** @param const %s *R', c_type)
-        _hc(' ** @returns %s *', field.c_field_type)
-        _hc(' **')
-        _hc(' *****************************************************************************/')
-        _hc(' ')
         if field.type.is_switch and switch_obj is None:
             return_type = 'void *'
         else:
         if field.type.is_switch and switch_obj is None:
             return_type = 'void *'
         else:
@@ -1526,21 +1796,32 @@ def _c_accessors_field(self, field):
         if field.prev_varsized_field is None:
             _c('    return (%s) (R + 1);', return_type)
             # note: the special case 'variable fields followed by fixed size fields'
         if field.prev_varsized_field is None:
             _c('    return (%s) (R + 1);', return_type)
             # note: the special case 'variable fields followed by fixed size fields'
-            #       is not of any consequence here, since the ordering gets 
+            #       is not of any consequence here, since the ordering gets
             #       'corrected' in the reply function
         else:
             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
             #       'corrected' in the reply function
         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);', 
+            _c('    return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
                return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
         _c('}')
 
                return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
         _c('}')
 
-    
+
 def _c_accessors_list(self, field):
     '''
     Declares the accessor functions for a list field.
     Declares a direct-accessor function only if the list members are fixed size.
     Declares length and get-iterator functions always.
     '''
 def _c_accessors_list(self, field):
     '''
     Declares the accessor functions for a list field.
     Declares a direct-accessor function only if the list members are fixed size.
     Declares length and get-iterator functions always.
     '''
+
+    def get_align_pad(field):
+            prev = field.prev_varsized_field
+            prev_prev = field.prev_varsized_field.prev_varsized_field
+
+            if (prev.type.is_pad and prev.type.align > 0 and prev_prev is not None):
+                return (prev_prev, '((-prev.index) & (%d - 1))' % prev.type.align)
+            else:
+                return (prev, None)
+
+
     list = field.type
     c_type = self.c_type
 
     list = field.type
     c_type = self.c_type
 
@@ -1548,10 +1829,10 @@ def _c_accessors_list(self, field):
     # in case of switch, 2 params have to be supplied to certain accessor functions:
     #   1. the anchestor object (request or reply)
     #   2. the (anchestor) switch object
     # in case of switch, 2 params have to be supplied to certain accessor functions:
     #   1. the anchestor object (request or reply)
     #   2. the (anchestor) switch object
-    # the reason is that switch is either a child of a request/reply or nested in another switch, 
+    # the reason is that switch is either a child of a request/reply or nested in another switch,
     # so whenever we need to access a length field, we might need to refer to some anchestor type
     switch_obj = self if self.is_switch else None
     # so whenever we need to access a length field, we might need to refer to some anchestor type
     switch_obj = self if self.is_switch else None
-    if self.is_bitcase:
+    if self.is_case_or_bitcase:
         switch_obj = self.parents[-1]
     if switch_obj is not None:
         c_type = switch_obj.c_type
         switch_obj = self.parents[-1]
     if switch_obj is not None:
         c_type = switch_obj.c_type
@@ -1559,14 +1840,14 @@ def _c_accessors_list(self, field):
     params = []
     fields = {}
     parents = self.parents if hasattr(self, 'parents') else [self]
     params = []
     fields = {}
     parents = self.parents if hasattr(self, 'parents') else [self]
-    # 'R': parents[0] is always the 'toplevel' container type 
+    # 'R': parents[0] is always the 'toplevel' container type
     params.append(('const %s *R' % parents[0].c_type, parents[0]))
     fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
     # auxiliary object for 'R' parameters
     R_obj = parents[0]
 
     if switch_obj is not None:
     params.append(('const %s *R' % parents[0].c_type, parents[0]))
     fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
     # auxiliary object for 'R' parameters
     R_obj = parents[0]
 
     if switch_obj is not None:
-        # now look where the fields are defined that are needed to evaluate 
+        # now look where the fields are defined that are needed to evaluate
         # the switch expr, and store the parent objects in accessor_params and
         # the fields in switch_fields
 
         # the switch expr, and store the parent objects in accessor_params and
         # the fields in switch_fields
 
@@ -1581,30 +1862,43 @@ def _c_accessors_list(self, field):
 
         # look for fields in the remaining containers
         for p in parents[2:] + [self]:
 
         # look for fields in the remaining containers
         for p in parents[2:] + [self]:
-            # the separator between parent and child is always '.' here, 
+            # the separator between parent and child is always '.' here,
             # because of nested switch statements
             # because of nested switch statements
-            if not p.is_bitcase or (p.is_bitcase and p.has_name):
+            if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
                 prefix.append((p.name[-1], '.', p))
             fields.update(_c_helper_field_mapping(p, prefix, flat=True))
 
         # auxiliary object for 'S' parameter
         S_obj = parents[1]
 
                 prefix.append((p.name[-1], '.', p))
             fields.update(_c_helper_field_mapping(p, prefix, flat=True))
 
         # 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():
         idx = 1 if switch_obj is not None else 0
         _hc('')
     _h_setlevel(1)
     _c_setlevel(1)
     if list.member.fixed_size():
         idx = 1 if switch_obj is not None else 0
         _hc('')
-        _hc('')
-        _hc('/*****************************************************************************')
-        _hc(' **')
-        _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
-        _hc(' ** ')
-        _hc(' ** @param %s', params[idx][0])
-        _hc(' ** @returns %s *', field.c_field_type)
-        _hc(' **')
-        _hc(' *****************************************************************************/')
-        _hc(' ')
         _hc('%s *', field.c_field_type)
 
         _h('%s (%s  /**< */);', field.c_accessor_name, params[idx][0])
         _hc('%s *', field.c_field_type)
 
         _h('%s (%s  /**< */);', field.c_accessor_name, params[idx][0])
@@ -1616,72 +1910,60 @@ def _c_accessors_list(self, field):
         elif field.prev_varsized_field is None:
             _c('    return (%s *) (R + 1);', field.c_field_type)
         else:
         elif field.prev_varsized_field is None:
             _c('    return (%s *) (R + 1);', field.c_field_type)
         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, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
+            (prev_varsized_field, align_pad) = get_align_pad(field)
+
+            if align_pad is None:
+                align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
+                    type_pad_type(field.first_field_after_varsized.type.c_type))
+
+            _c('    xcb_generic_iterator_t prev = %s;',
+                _c_iterator_get_end(prev_varsized_field, 'R'))
+            _c('    return (%s *) ((char *) prev.data + %s + %d);',
+               field.c_field_type, align_pad, field.prev_varsized_offset)
         _c('}')
 
     _hc('')
         _c('}')
 
     _hc('')
-    _hc('')
-    _hc('/*****************************************************************************')
-    _hc(' **')
-    _hc(' ** int %s', field.c_length_name)
-    _hc(' ** ')
-    _hc(' ** @param const %s *R', c_type)
-    _hc(' ** @returns int')
-    _hc(' **')
-    _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:
         _hc('%s (const %s *R  /**< */,', field.c_length_name, R_obj.c_type)
     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)
-        length = _c_accessor_get_expr(field.type.expr, fields)
+        _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:
     else:
-        _h('%s (const %s *R  /**< */);', field.c_length_name, c_type)
-        _c('%s (const %s *R  /**< */)', field.c_length_name, c_type)
-        length = _c_accessor_get_expr(field.type.expr, fields)
+        _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('{')
     _c('{')
+    length = _c_accessor_get_expr(field.type.expr, fields)
     _c('    return %s;', length)
     _c('}')
 
     if field.type.member.is_simple:
         _hc('')
     _c('    return %s;', length)
     _c('}')
 
     if field.type.member.is_simple:
         _hc('')
-        _hc('')
-        _hc('/*****************************************************************************')
-        _hc(' **')
-        _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
-        _hc(' ** ')
-        _hc(' ** @param const %s *R', c_type)
-        _hc(' ** @returns xcb_generic_iterator_t')
-        _hc(' **')
-        _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:
             _hc('%s (const %s *R  /**< */,', field.c_end_name, R_obj.c_type)
         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:
         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;')
         _c('{')
         _c('    xcb_generic_iterator_t i;')
-        
+
         param = 'R' if switch_obj is None else 'S'
         if switch_obj is not None:
         param = 'R' if switch_obj is None else 'S'
         if switch_obj is not None:
-            _c('    i.data = %s + %s;', fields[field.c_field_name][0], 
+            _c('    i.data = %s + %s;', fields[field.c_field_name][0],
                _c_accessor_get_expr(field.type.expr, fields))
         elif field.prev_varsized_field == None:
                _c_accessor_get_expr(field.type.expr, fields))
         elif field.prev_varsized_field == None:
-            _c('    i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, 
+            _c('    i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
                _c_accessor_get_expr(field.type.expr, fields))
         else:
                _c_accessor_get_expr(field.type.expr, fields))
         else:
-            _c('    xcb_generic_iterator_t child = %s;', 
+            _c('    xcb_generic_iterator_t child = %s;',
                _c_iterator_get_end(field.prev_varsized_field, 'R'))
                _c_iterator_get_end(field.prev_varsized_field, 'R'))
-            _c('    i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, 
+            _c('    i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
                _c_accessor_get_expr(field.type.expr, fields))
 
         _c('    i.rem = 0;')
                _c_accessor_get_expr(field.type.expr, fields))
 
         _c('    i.rem = 0;')
@@ -1691,41 +1973,52 @@ def _c_accessors_list(self, field):
 
     else:
         _hc('')
 
     else:
         _hc('')
-        _hc('')
-        _hc('/*****************************************************************************')
-        _hc(' **')
-        _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
-        _hc(' ** ')
-        _hc(' ** @param const %s *R', c_type)
-        _hc(' ** @returns %s', field.c_iterator_type)
-        _hc(' **')
-        _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:
             _hc('%s (const %s *R  /**< */,', field.c_iterator_name, R_obj.c_type)
         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:
         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)
 
         _c('{')
         _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)
         else:
             _c('    i.data = (%s *) (R + 1);', field.c_field_type)
         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, type_pad_type(field.c_field_type))
+            (prev_varsized_field, align_pad) = get_align_pad(field)
+
+            if align_pad is None:
+                align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
+                    type_pad_type(field.c_field_type))
+
+            _c('    xcb_generic_iterator_t prev = %s;',
+                _c_iterator_get_end(prev_varsized_field, 'R'))
+            _c_pre.end()
+            _c('    i.data = (%s *) ((char *) prev.data + %s);',
+                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('}')
 
         _c('    return i;')
         _c('}')
 
@@ -1733,17 +2026,18 @@ def _c_accessors(self, name, base):
     '''
     Declares the accessor functions for the fields of a structure.
     '''
     '''
     Declares the accessor functions for the fields of a structure.
     '''
-    # no accessors for switch itself - 
+    # no accessors for switch itself -
     # switch always needs to be unpacked explicitly
 #    if self.is_switch:
 #        pass
 #    else:
     if True:
         for field in self.fields:
     # switch always needs to be unpacked explicitly
 #    if self.is_switch:
 #        pass
 #    else:
     if True:
         for field in self.fields:
-            if field.type.is_list and not field.type.fixed_size():
-                _c_accessors_list(self, field)
-            elif field.prev_varsized_field is not None or not field.type.fixed_size():
-                _c_accessors_field(self, field)
+            if not field.type.is_pad:
+                if _c_field_needs_list_accessor(field):
+                    _c_accessors_list(self, field)
+                elif _c_field_needs_field_accessor(field):
+                    _c_accessors_field(self, field)
 
 def c_simple(self, name):
     '''
 
 def c_simple(self, name):
     '''
@@ -1762,7 +2056,7 @@ def c_simple(self, name):
         # Iterator
         _c_iterator(self, name)
 
         # Iterator
         _c_iterator(self, name)
 
-def _c_complex(self):
+def _c_complex(self, force_packed = False):
     '''
     Helper function for handling all structure types.
     Called for all structs, requests, replies, events, errors.
     '''
     Helper function for handling all structure types.
     Called for all structs, requests, replies, events, errors.
@@ -1784,7 +2078,7 @@ def _c_complex(self):
             continue
         if field.wire:
             struct_fields.append(field)
             continue
         if field.wire:
             struct_fields.append(field)
-    
+
     for field in struct_fields:
         length = len(field.c_field_type)
         # account for '*' pointer_spec
     for field in struct_fields:
         length = len(field.c_field_type)
         # account for '*' pointer_spec
@@ -1810,14 +2104,14 @@ def _c_complex(self):
         for b in self.bitcases:
             space = ''
             if b.type.has_name:
         for b in self.bitcases:
             space = ''
             if b.type.has_name:
-                _h('    struct _%s {', b.c_field_name)
+                _h('    struct {')
                 space = '    '
             for field in b.type.fields:
                 _c_complex_field(self, field, space)
             if b.type.has_name:
                 _h('    } %s;', b.c_field_name)
 
                 space = '    '
             for field in b.type.fields:
                 _c_complex_field(self, field, space)
             if b.type.has_name:
                 _h('    } %s;', b.c_field_name)
 
-    _h('} %s;', self.c_type)
+    _h('} %s%s;', 'XCB_PACKED ' if force_packed else '', self.c_type)
 
 def c_struct(self, name):
     '''
 
 def c_struct(self, name):
     '''
@@ -1895,12 +2189,12 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_f
         if field.wire and not field.auto:
             # We need to set the field up in the structure
             wire_fields.append(field)
         if field.wire and not field.auto:
             # We need to set the field up in the structure
             wire_fields.append(field)
-        if field.type.need_serialize or field.type.need_sizeof:
+        if field.type.c_need_serialize or field.type.c_need_sizeof:
             serial_fields.append(field)
             serial_fields.append(field)
-        
+
     for field in param_fields:
     for field in param_fields:
-        c_field_const_type = field.c_field_const_type 
-        if field.type.need_serialize and not aux:
+        c_field_const_type = field.c_field_const_type
+        if field.type.c_need_serialize and not aux:
             c_field_const_type = "const void"
         if len(c_field_const_type) > maxtypelen:
             maxtypelen = len(c_field_const_type)
             c_field_const_type = "const void"
         if len(c_field_const_type) > maxtypelen:
             maxtypelen = len(c_field_const_type)
@@ -1963,7 +2257,7 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_f
             _h(' * No description yet')
     else:
         _h(' * Delivers a request to the X server.')
             _h(' * No description yet')
     else:
         _h(' * Delivers a request to the X server.')
-    _h(' * ')
+    _h(' *')
     if checked:
         _h(' * This form can be used only if the request will not cause')
         _h(' * a reply to be generated. Any returned error will be')
     if checked:
         _h(' * This form can be used only if the request will not cause')
         _h(' * a reply to be generated. Any returned error will be')
@@ -1974,26 +2268,6 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_f
         _h(' * placed in the event queue.')
     _h(' */')
     _c('')
         _h(' * placed in the event queue.')
     _h(' */')
     _c('')
-    _hc('')
-    _hc('/*****************************************************************************')
-    _hc(' **')
-    _hc(' ** %s %s', cookie_type, func_name)
-    _hc(' ** ')
-
-    spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
-    _hc(' ** @param xcb_connection_t%s *c', spacing)
-
-    for field in param_fields:
-        c_field_const_type = field.c_field_const_type 
-        if field.type.need_serialize and not aux:
-            c_field_const_type = "const void"
-        spacing = ' ' * (maxtypelen - len(c_field_const_type))
-        _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
-
-    _hc(' ** @returns %s', cookie_type)
-    _hc(' **')
-    _hc(' *****************************************************************************/')
-    _hc(' ')
     _hc('%s', cookie_type)
 
     spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
     _hc('%s', cookie_type)
 
     spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
@@ -2006,25 +2280,25 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_f
     count = len(param_fields)
     for field in param_fields:
         count = count - 1
     count = len(param_fields)
     for field in param_fields:
         count = count - 1
-        c_field_const_type = field.c_field_const_type 
+        c_field_const_type = field.c_field_const_type
         c_pointer = field.c_pointer
         c_pointer = field.c_pointer
-        if field.type.need_serialize and not aux:
+        if field.type.c_need_serialize and not aux:
             c_field_const_type = "const void"
             c_pointer = '*'
         spacing = ' ' * (maxtypelen - len(c_field_const_type))
         comma = ',' if count else ');'
             c_field_const_type = "const void"
             c_pointer = '*'
         spacing = ' ' * (maxtypelen - len(c_field_const_type))
         comma = ',' if count else ');'
-        _h('%s%s%s %s%s  /**< */%s', func_spacing, c_field_const_type, 
+        _h('%s%s%s %s%s  /**< */%s', func_spacing, c_field_const_type,
            spacing, c_pointer, field.c_field_name, comma)
         comma = ',' if count else ')'
            spacing, c_pointer, field.c_field_name, comma)
         comma = ',' if count else ')'
-        _c('%s%s%s %s%s  /**< */%s', func_spacing, c_field_const_type, 
+        _c('%s%s%s %s%s  /**< */%s', func_spacing, c_field_const_type,
            spacing, c_pointer, field.c_field_name, comma)
 
     count = 2
            spacing, c_pointer, field.c_field_name, comma)
 
     count = 2
-    if not self.var_followed_by_fixed_fields:
+    if not self.c_var_followed_by_fixed_fields:
         for field in param_fields:
             if not field.type.fixed_size():
                 count = count + 2
         for field in param_fields:
             if not field.type.fixed_size():
                 count = count + 2
-                if field.type.need_serialize:
+                if field.type.c_need_serialize:
                     # _serialize() keeps track of padding automatically
                     count -= 1
     dimension = count + 2
                     # _serialize() keeps track of padding automatically
                     count -= 1
     dimension = count + 2
@@ -2036,15 +2310,15 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_f
     _c('        /* opcode */ %s,', self.c_request_name.upper())
     _c('        /* isvoid */ %d', 1 if void else 0)
     _c('    };')
     _c('        /* opcode */ %s,', self.c_request_name.upper())
     _c('        /* isvoid */ %d', 1 if void else 0)
     _c('    };')
-    _c('    ')
+    _c('')
 
     _c('    struct iovec xcb_parts[%d];', dimension)
     _c('    %s xcb_ret;', func_cookie)
     _c('    %s xcb_out;', self.c_type)
 
     _c('    struct iovec xcb_parts[%d];', dimension)
     _c('    %s xcb_ret;', func_cookie)
     _c('    %s xcb_out;', self.c_type)
-    if self.var_followed_by_fixed_fields:
+    if self.c_var_followed_by_fixed_fields:
         _c('    /* in the protocol description, variable size fields are followed by fixed size fields */')
         _c('    void *xcb_aux = 0;')
         _c('    /* in the protocol description, variable size fields are followed by fixed size fields */')
         _c('    void *xcb_aux = 0;')
-        
+
 
     for idx, f in enumerate(serial_fields):
         if aux:
 
     for idx, f in enumerate(serial_fields):
         if aux:
@@ -2053,10 +2327,10 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_f
         _c('    unsigned int i;')
         _c('    unsigned int xcb_tmp_len;')
         _c('    char *xcb_tmp;')
         _c('    unsigned int i;')
         _c('    unsigned int xcb_tmp_len;')
         _c('    char *xcb_tmp;')
-    _c('    ')
+    _c('')
     # simple request call tracing
     # simple request call tracing
-#    _c('    printf("in function %s\\n");' % func_name)     
+#    _c('    printf("in function %s\\n");' % func_name)
+
     # fixed size fields
     for field in wire_fields:
         if field.type.fixed_size():
     # fixed size fields
     for field in wire_fields:
         if field.type.fixed_size():
@@ -2074,16 +2348,16 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_f
                     _c('    memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
 
     def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
                     _c('    memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
 
     def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
-        serialize_args = get_serialize_params(context, type_obj, 
-                                              c_field_name, 
+        serialize_args = get_serialize_params(context, type_obj,
+                                              c_field_name,
                                               aux_var)[2]
         return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
 
     # calls in order to free dyn. all. memory
     free_calls = []
 
                                               aux_var)[2]
         return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
 
     # calls in order to free dyn. all. memory
     free_calls = []
 
-    _c('    ')
-    if not self.var_followed_by_fixed_fields:
+    _c('')
+    if not self.c_var_followed_by_fixed_fields:
         _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
         _c('    xcb_parts[2].iov_len = sizeof(xcb_out);')
         _c('    xcb_parts[3].iov_base = 0;')
         _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
         _c('    xcb_parts[2].iov_len = sizeof(xcb_out);')
         _c('    xcb_parts[3].iov_base = 0;')
@@ -2095,25 +2369,25 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_f
             if not field.type.fixed_size():
                 _c('    /* %s %s */', field.type.c_type, field.c_field_name)
                 # default: simple cast to char *
             if not field.type.fixed_size():
                 _c('    /* %s %s */', field.type.c_type, field.c_field_name)
                 # default: simple cast to char *
-                if not field.type.need_serialize and not field.type.need_sizeof:
+                if not field.type.c_need_serialize and not field.type.c_need_sizeof:
                     _c('    xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
                     if field.type.is_list:
                         if field.type.member.fixed_size():
                     _c('    xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
                     if field.type.is_list:
                         if field.type.member.fixed_size():
-                            _c('    xcb_parts[%d].iov_len = %s * sizeof(%s);', count, 
-                               _c_accessor_get_expr(field.type.expr, None), 
+                            _c('    xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
+                               _c_accessor_get_expr(field.type.expr, None),
                                field.type.member.c_wiretype)
                         else:
                             list_length = _c_accessor_get_expr(field.type.expr, None)
                                field.type.member.c_wiretype)
                         else:
                             list_length = _c_accessor_get_expr(field.type.expr, None)
-    
+
                             length = ''
                             _c("    xcb_parts[%d].iov_len = 0;" % count)
                             _c("    xcb_tmp = (char *)%s;", field.c_field_name)
                             _c("    for(i=0; i<%s; i++) {" % list_length)
                             length = ''
                             _c("    xcb_parts[%d].iov_len = 0;" % count)
                             _c("    xcb_tmp = (char *)%s;", field.c_field_name)
                             _c("    for(i=0; i<%s; i++) {" % list_length)
-                            _c("        xcb_tmp_len = %s(xcb_tmp);" % 
+                            _c("        xcb_tmp_len = %s(xcb_tmp);" %
                                               (field.type.c_sizeof_name))
                             _c("        xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
                             _c("        xcb_tmp += xcb_tmp_len;")
                                               (field.type.c_sizeof_name))
                             _c("        xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
                             _c("        xcb_tmp += xcb_tmp_len;")
-                            _c("    }")                        
+                            _c("    }")
                     else:
                         # not supposed to happen
                         raise Exception("unhandled variable size field %s" % field.c_field_name)
                     else:
                         # not supposed to happen
                         raise Exception("unhandled variable size field %s" % field.c_field_name)
@@ -2123,7 +2397,7 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_f
                     idx = serial_fields.index(field)
                     aux_var = '&xcb_aux%d' % idx
                     context = 'serialize' if aux else 'sizeof'
                     idx = serial_fields.index(field)
                     aux_var = '&xcb_aux%d' % idx
                     context = 'serialize' if aux else 'sizeof'
-                    _c('    xcb_parts[%d].iov_len = ', count)
+                    _c('    xcb_parts[%d].iov_len =', count)
                     if aux:
                         serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
                         _c('      %s (%s);', field.type.c_serialize_name, serialize_args)
                     if aux:
                         serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
                         _c('      %s (%s);', field.type.c_serialize_name, serialize_args)
@@ -2135,17 +2409,17 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_f
                         _c('      %s (%s);', func_name, serialize_args)
 
                 count += 1
                         _c('      %s (%s);', func_name, serialize_args)
 
                 count += 1
-                if not (field.type.need_serialize or field.type.need_sizeof):
+                if not (field.type.c_need_serialize or field.type.c_need_sizeof):
                     # the _serialize() function keeps track of padding automatically
                     _c('    xcb_parts[%d].iov_base = 0;', count)
                     _c('    xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
                     count += 1
 
                     # the _serialize() function keeps track of padding automatically
                     _c('    xcb_parts[%d].iov_base = 0;', count)
                     _c('    xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
                     count += 1
 
-    # elif self.var_followed_by_fixed_fields:
+    # elif self.c_var_followed_by_fixed_fields:
     else:
         _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
         # request header: opcodes + length
     else:
         _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
         # request header: opcodes + length
-        _c('    xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);') 
+        _c('    xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
         count += 1
         # call _serialize()
         buffer_var = '&xcb_aux'
         count += 1
         # call _serialize()
         buffer_var = '&xcb_aux'
@@ -2155,13 +2429,13 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_f
         free_calls.append('    free(xcb_aux);')
         # no padding necessary - _serialize() keeps track of padding automatically
 
         free_calls.append('    free(xcb_aux);')
         # no padding necessary - _serialize() keeps track of padding automatically
 
-    _c('    ')
+    _c('')
     for field in param_fields:
         if field.isfd:
             _c('    xcb_send_fd(c, %s);', field.c_field_name)
     for field in param_fields:
         if field.isfd:
             _c('    xcb_send_fd(c, %s);', field.c_field_name)
-    
+
     _c('    xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
     _c('    xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
-    
+
     # free dyn. all. data, if any
     for f in free_calls:
         _c(f)
     # free dyn. all. data, if any
     for f in free_calls:
         _c(f)
@@ -2175,7 +2449,7 @@ def _c_reply(self, name):
     spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
     spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
     spacing3 = ' ' * (len(self.c_reply_name) + 2)
     spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
     spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
     spacing3 = ' ' * (len(self.c_reply_name) + 2)
-    
+
     # check if _unserialize() has to be called for any field
     def look_for_special_cases(complex_obj):
         unserialize_fields = []
     # check if _unserialize() has to be called for any field
     def look_for_special_cases(complex_obj):
         unserialize_fields = []
@@ -2185,19 +2459,19 @@ def _c_reply(self, name):
                 # three cases: 1. field with special case
                 #              2. container that contains special case field
                 #              3. list with special case elements
                 # three cases: 1. field with special case
                 #              2. container that contains special case field
                 #              3. list with special case elements
-                if field.type.var_followed_by_fixed_fields:
+                if field.type.c_var_followed_by_fixed_fields:
                     unserialize_fields.append(field)
                 elif field.type.is_container:
                     unserialize_fields += look_for_special_cases(field.type)
                 elif field.type.is_list:
                     unserialize_fields.append(field)
                 elif field.type.is_container:
                     unserialize_fields += look_for_special_cases(field.type)
                 elif field.type.is_list:
-                    if field.type.member.var_followed_by_fixed_fields:
+                    if field.type.member.c_var_followed_by_fixed_fields:
                         unserialize_fields.append(field)
                     if field.type.member.is_container:
                         unserialize_fields += look_for_special_cases(field.type.member)
         return unserialize_fields
                         unserialize_fields.append(field)
                     if field.type.member.is_container:
                         unserialize_fields += look_for_special_cases(field.type.member)
         return unserialize_fields
-    
+
     unserialize_fields = look_for_special_cases(self.reply)
     unserialize_fields = look_for_special_cases(self.reply)
-    
+
     _h('')
     _h('/**')
     _h(' * Return the reply')
     _h('')
     _h('/**')
     _h(' * Return the reply')
@@ -2206,7 +2480,7 @@ def _c_reply(self, name):
     _h(' * @param e      The xcb_generic_error_t supplied')
     _h(' *')
     _h(' * Returns the reply of the request asked by')
     _h(' * @param e      The xcb_generic_error_t supplied')
     _h(' *')
     _h(' * Returns the reply of the request asked by')
-    _h(' * ')
+    _h(' *')
     _h(' * The parameter @p e supplied to this function must be NULL if')
     _h(' * %s(). is used.', self.c_unchecked_name)
     _h(' * Otherwise, it stores the error if any.')
     _h(' * The parameter @p e supplied to this function must be NULL if')
     _h(' * %s(). is used.', self.c_unchecked_name)
     _h(' * Otherwise, it stores the error if any.')
@@ -2214,28 +2488,16 @@ def _c_reply(self, name):
     _h(' * The returned value must be freed by the caller using free().')
     _h(' */')
     _c('')
     _h(' * The returned value must be freed by the caller using free().')
     _h(' */')
     _c('')
-    _hc('')
-    _hc('/*****************************************************************************')
-    _hc(' **')
-    _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
-    _hc(' ** ')
-    _hc(' ** @param xcb_connection_t%s  *c', spacing1)
-    _hc(' ** @param %s   cookie', self.c_cookie_type)
-    _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
-    _hc(' ** @returns %s *', self.c_reply_type)
-    _hc(' **')
-    _hc(' *****************************************************************************/')
-    _hc(' ')
     _hc('%s *', self.c_reply_type)
     _hc('%s (xcb_connection_t%s  *c  /**< */,', self.c_reply_name, spacing1)
     _hc('%s%s   cookie  /**< */,', spacing3, self.c_cookie_type)
     _h('%sxcb_generic_error_t%s **e  /**< */);', spacing3, spacing2)
     _c('%sxcb_generic_error_t%s **e  /**< */)', spacing3, spacing2)
     _c('{')
     _hc('%s *', self.c_reply_type)
     _hc('%s (xcb_connection_t%s  *c  /**< */,', self.c_reply_name, spacing1)
     _hc('%s%s   cookie  /**< */,', spacing3, self.c_cookie_type)
     _h('%sxcb_generic_error_t%s **e  /**< */);', spacing3, spacing2)
     _c('%sxcb_generic_error_t%s **e  /**< */)', spacing3, spacing2)
     _c('{')
-    
+
     if len(unserialize_fields)>0:
         # certain variable size fields need to be unserialized explicitly
     if len(unserialize_fields)>0:
         # certain variable size fields need to be unserialized explicitly
-        _c('    %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', 
+        _c('    %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
            self.c_reply_type, self.c_reply_type)
         _c('    int i;')
         for field in unserialize_fields:
            self.c_reply_type, self.c_reply_type)
         _c('    int i;')
         for field in unserialize_fields:
@@ -2251,13 +2513,13 @@ def _c_reply(self, name):
             if field.type.is_list:
                 _c('    for(i=0; i<%s_len; i++) {', field.c_field_name)
                 _c('        %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
             if field.type.is_list:
                 _c('    for(i=0; i<%s_len; i++) {', field.c_field_name)
                 _c('        %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
-                _c('        %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name, 
+                _c('        %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
                    field.c_field_name, field.c_field_name)
                 _c('        %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
                 _c('    }')
         # return the transformed reply
         _c('    return reply;')
                    field.c_field_name, field.c_field_name)
                 _c('        %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
                 _c('    }')
         # return the transformed reply
         _c('    return reply;')
-    
+
     else:
         _c('    return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
 
     else:
         _c('    return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
 
@@ -2282,31 +2544,20 @@ def _c_reply_fds(self, name):
     _h(' * @param reply  The reply')
     _h(' *')
     _h(' * Returns the array of reply fds of the request asked by')
     _h(' * @param reply  The reply')
     _h(' *')
     _h(' * Returns the array of reply fds of the request asked by')
-    _h(' * ')
+    _h(' *')
     _h(' * The returned value must be freed by the caller using free().')
     _h(' */')
     _c('')
     _h(' * The returned value must be freed by the caller using free().')
     _h(' */')
     _c('')
-    _hc('')
-    _hc('/*****************************************************************************')
-    _hc(' **')
-    _hc(' ** int * %s', self.c_reply_fds_name)
-    _hc(' ** ')
-    _hc(' ** @param xcb_connection_t%s  *c', spacing1)
-    _hc(' ** @param %s  *reply', self.c_reply_type)
-    _hc(' ** @returns int *')
-    _hc(' **')
-    _hc(' *****************************************************************************/')
-    _hc(' ')
     _hc('int *')
     _hc('%s (xcb_connection_t%s  *c  /**< */,', self.c_reply_fds_name, spacing1)
     _h('%s%s  *reply  /**< */);', spacing3, self.c_reply_type)
     _c('%s%s  *reply  /**< */)', spacing3, self.c_reply_type)
     _c('{')
     _hc('int *')
     _hc('%s (xcb_connection_t%s  *c  /**< */,', self.c_reply_fds_name, spacing1)
     _h('%s%s  *reply  /**< */);', spacing3, self.c_reply_type)
     _c('%s%s  *reply  /**< */)', spacing3, self.c_reply_type)
     _c('{')
-    
+
     _c('    return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
 
     _c('}')
     _c('    return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
 
     _c('}')
-    
+
 
 def _c_opcode(name, opcode):
     '''
 
 def _c_opcode(name, opcode):
     '''
@@ -2316,7 +2567,7 @@ def _c_opcode(name, opcode):
     _h('')
     _h('/** Opcode for %s. */', _n(name))
     _h('#define %s %s', _n(name).upper(), opcode)
     _h('')
     _h('/** Opcode for %s. */', _n(name))
     _h('#define %s %s', _n(name).upper(), opcode)
-    
+
 def _c_cookie(self, name):
     '''
     Declares the cookie type for a non-void request.
 def _c_cookie(self, name):
     '''
     Declares the cookie type for a non-void request.
@@ -2336,18 +2587,18 @@ def _man_request(self, name, cookie_type, void, aux):
     func_name = self.c_request_name if not aux else self.c_aux_name
 
     def create_link(linkname):
     func_name = self.c_request_name if not aux else self.c_aux_name
 
     def create_link(linkname):
-        name = 'man/%s.3' % linkname
+        name = 'man/%s.%s' % (linkname, section)
         if manpaths:
             sys.stdout.write(name)
         f = open(name, 'w')
         if manpaths:
             sys.stdout.write(name)
         f = open(name, 'w')
-        f.write('.so man3/%s.3' % func_name)
+        f.write('.so man%s/%s.%s' % (section, func_name, section))
         f.close()
 
     if manpaths:
         f.close()
 
     if manpaths:
-        sys.stdout.write('man/%s.3 ' % func_name)
+        sys.stdout.write('man/%s.%s ' % (func_name, section))
     # Our CWD is src/, so this will end up in src/man/
     # Our CWD is src/, so this will end up in src/man/
-    f = open('man/%s.3' % func_name, 'w')
-    f.write('.TH %s 3  %s "XCB" "XCB Requests"\n' % (func_name, today))
+    f = open('man/%s.%s' % (func_name, section), 'w')
+    f.write('.TH %s %s  "%s" "%s" "XCB Requests"\n' % (func_name, section, center_footer, left_footer))
     # Left-adjust instead of adjusting to both sides
     f.write('.ad l\n')
     f.write('.SH NAME\n')
     # Left-adjust instead of adjusting to both sides
     f.write('.ad l\n')
     f.write('.SH NAME\n')
@@ -2367,7 +2618,7 @@ def _man_request(self, name, cookie_type, void, aux):
         c_pointer = field.c_pointer
         if c_pointer == ' ':
             c_pointer = ''
         c_pointer = field.c_pointer
         if c_pointer == ' ':
             c_pointer = ''
-        if field.type.need_serialize and not aux:
+        if field.type.c_need_serialize and not aux:
             c_field_const_type = "const void"
             c_pointer = '*'
         comma = ', ' if count else ');'
             c_field_const_type = "const void"
             c_pointer = '*'
         comma = ', ' if count else ');'
@@ -2454,7 +2705,7 @@ def _man_request(self, name, cookie_type, void, aux):
 
             # special case: switch
             switch_obj = self if self.is_switch else None
 
             # special case: switch
             switch_obj = self if self.is_switch else None
-            if self.is_bitcase:
+            if self.is_case_or_bitcase:
                 switch_obj = self.parents[-1]
             if switch_obj is not None:
                 c_type = switch_obj.c_type
                 switch_obj = self.parents[-1]
             if switch_obj is not None:
                 c_type = switch_obj.c_type
@@ -2482,7 +2733,7 @@ def _man_request(self, name, cookie_type, void, aux):
             # the reason is that switch is either a child of a request/reply or nested in another switch,
             # so whenever we need to access a length field, we might need to refer to some anchestor type
             switch_obj = self if self.is_switch else None
             # the reason is that switch is either a child of a request/reply or nested in another switch,
             # so whenever we need to access a length field, we might need to refer to some anchestor type
             switch_obj = self if self.is_switch else None
-            if self.is_bitcase:
+            if self.is_case_or_bitcase:
                 switch_obj = self.parents[-1]
             if switch_obj is not None:
                 c_type = switch_obj.c_type
                 switch_obj = self.parents[-1]
             if switch_obj is not None:
                 c_type = switch_obj.c_type
@@ -2514,7 +2765,7 @@ def _man_request(self, name, cookie_type, void, aux):
                 for p in parents[2:] + [self]:
                     # the separator between parent and child is always '.' here,
                     # because of nested switch statements
                 for p in parents[2:] + [self]:
                     # the separator between parent and child is always '.' here,
                     # because of nested switch statements
-                    if not p.is_bitcase or (p.is_bitcase and p.has_name):
+                    if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
                         prefix.append((p.name[-1], '.', p))
                     fields.update(_c_helper_field_mapping(p, prefix, flat=True))
 
                         prefix.append((p.name[-1], '.', p))
                     fields.update(_c_helper_field_mapping(p, prefix, flat=True))
 
@@ -2672,17 +2923,17 @@ def _man_request(self, name, cookie_type, void, aux):
                  'have to be handled in the event loop.\n\nIf you want to '
                  'handle errors directly with \\fIxcb_request_check\\fP '
                  'instead, use \\fI%s_checked\\fP. See '
                  'have to be handled in the event loop.\n\nIf you want to '
                  'handle errors directly with \\fIxcb_request_check\\fP '
                  'instead, use \\fI%s_checked\\fP. See '
-                 '\\fBxcb-requests(3)\\fP for details.\n') % (base_func_name))
+                 '\\fBxcb-requests(%s)\\fP for details.\n') % (base_func_name, section))
     else:
         f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
                  'calling the reply function \\fI%s\\fP.\n\nIf you want to '
                  'handle errors in the event loop instead, use '
     else:
         f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
                  'calling the reply function \\fI%s\\fP.\n\nIf you want to '
                  'handle errors in the event loop instead, use '
-                 '\\fI%s_unchecked\\fP. See \\fBxcb-requests(3)\\fP for '
+                 '\\fI%s_unchecked\\fP. See \\fBxcb-requests(%s)\\fP for '
                  'details.\n') %
                  'details.\n') %
-                (cookie_type, self.c_reply_name, base_func_name))
+                (cookie_type, self.c_reply_name, base_func_name, section))
     f.write('.SH ERRORS\n')
     if hasattr(self, "doc") and self.doc:
     f.write('.SH ERRORS\n')
     if hasattr(self, "doc") and self.doc:
-        for errtype, errtext in self.doc.errors.items():
+        for errtype, errtext in sorted(self.doc.errors.items()):
             f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
             errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
             f.write('%s\n' % (errtext))
             f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
             errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
             f.write('%s\n' % (errtext))
@@ -2697,18 +2948,18 @@ def _man_request(self, name, cookie_type, void, aux):
         f.write('.fi\n')
     f.write('.SH SEE ALSO\n')
     if hasattr(self, "doc") and self.doc:
         f.write('.fi\n')
     f.write('.SH SEE ALSO\n')
     if hasattr(self, "doc") and self.doc:
-        see = ['.BR %s (3)' % 'xcb-requests']
+        see = ['.BR %s (%s)' % ('xcb-requests', section)]
         if self.doc.example:
         if self.doc.example:
-            see.append('.BR %s (3)' % 'xcb-examples')
-        for seename, seetype in self.doc.see.items():
+            see.append('.BR %s (%s)' % ('xcb-examples', section))
+        for seename, seetype in sorted(self.doc.see.items()):
             if seetype == 'program':
                 see.append('.BR %s (1)' % seename)
             elif seetype == 'event':
             if seetype == 'program':
                 see.append('.BR %s (1)' % seename)
             elif seetype == 'event':
-                see.append('.BR %s (3)' % _t(('xcb', seename, 'event')))
+                see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
             elif seetype == 'request':
             elif seetype == 'request':
-                see.append('.BR %s (3)' % _n(('xcb', seename)))
+                see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
             elif seetype == 'function':
             elif seetype == 'function':
-                see.append('.BR %s (3)' % seename)
+                see.append('.BR %s (%s)' % (seename, section))
             else:
                 see.append('TODO: %s (type %s)' % (seename, seetype))
         f.write(',\n'.join(see) + '\n')
             else:
                 see.append('TODO: %s (type %s)' % (seename, seetype))
         f.write(',\n'.join(see) + '\n')
@@ -2718,10 +2969,10 @@ def _man_request(self, name, cookie_type, void, aux):
 
 def _man_event(self, name):
     if manpaths:
 
 def _man_event(self, name):
     if manpaths:
-        sys.stdout.write('man/%s.3 ' % self.c_type)
+        sys.stdout.write('man/%s.%s ' % (self.c_type, section))
     # Our CWD is src/, so this will end up in src/man/
     # Our CWD is src/, so this will end up in src/man/
-    f = open('man/%s.3' % self.c_type, 'w')
-    f.write('.TH %s 3  %s "XCB" "XCB Events"\n' % (self.c_type, today))
+    f = open('man/%s.%s' % (self.c_type, section), 'w')
+    f.write('.TH %s %s  "%s" "%s" "XCB Events"\n' % (self.c_type, section, center_footer, left_footer))
     # Left-adjust instead of adjusting to both sides
     f.write('.ad l\n')
     f.write('.SH NAME\n')
     # Left-adjust instead of adjusting to both sides
     f.write('.ad l\n')
     f.write('.SH NAME\n')
@@ -2827,18 +3078,18 @@ def _man_event(self, name):
         f.write('.fi\n')
     f.write('.SH SEE ALSO\n')
     if hasattr(self, "doc") and self.doc:
         f.write('.fi\n')
     f.write('.SH SEE ALSO\n')
     if hasattr(self, "doc") and self.doc:
-        see = ['.BR %s (3)' % 'xcb_generic_event_t']
+        see = ['.BR %s (%s)' % ('xcb_generic_event_t', section)]
         if self.doc.example:
         if self.doc.example:
-            see.append('.BR %s (3)' % 'xcb-examples')
-        for seename, seetype in self.doc.see.items():
+            see.append('.BR %s (%s)' % ('xcb-examples', section))
+        for seename, seetype in sorted(self.doc.see.items()):
             if seetype == 'program':
                 see.append('.BR %s (1)' % seename)
             elif seetype == 'event':
             if seetype == 'program':
                 see.append('.BR %s (1)' % seename)
             elif seetype == 'event':
-                see.append('.BR %s (3)' % _t(('xcb', seename, 'event')))
+                see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
             elif seetype == 'request':
             elif seetype == 'request':
-                see.append('.BR %s (3)' % _n(('xcb', seename)))
+                see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
             elif seetype == 'function':
             elif seetype == 'function':
-                see.append('.BR %s (3)' % seename)
+                see.append('.BR %s (%s)' % (seename, section))
             else:
                 see.append('TODO: %s (type %s)' % (seename, seetype))
         f.write(',\n'.join(see) + '\n')
             else:
                 see.append('TODO: %s (type %s)' % (seename, seetype))
         f.write(',\n'.join(see) + '\n')
@@ -2871,7 +3122,7 @@ def c_request(self, name):
         has_fds = _c_reply_has_fds(self.reply)
         _c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds)
         _c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds)
         has_fds = _c_reply_has_fds(self.reply)
         _c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds)
         _c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds)
-        if self.need_aux:
+        if self.c_need_aux:
             _c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds)
             _c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds)
         # Reply accessors
             _c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds)
             _c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds)
         # Reply accessors
@@ -2883,7 +3134,7 @@ def c_request(self, name):
         # Request prototypes
         _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
         _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
         # Request prototypes
         _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
         _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
-        if self.need_aux:
+        if self.c_need_aux:
             _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
             _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
 
             _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
             _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
 
@@ -2902,6 +3153,7 @@ def c_event(self, name):
     # events while generating the structure for them. Otherwise we would read
     # garbage (the internal full_sequence) when accessing normal event fields
     # there.
     # events while generating the structure for them. Otherwise we would read
     # garbage (the internal full_sequence) when accessing normal event fields
     # there.
+    force_packed = False
     if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
         event_size = 0
         for field in self.fields:
     if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
         event_size = 0
         for field in self.fields:
@@ -2911,21 +3163,53 @@ def c_event(self, name):
                 full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
                 idx = self.fields.index(field)
                 self.fields.insert(idx + 1, full_sequence)
                 full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
                 idx = self.fields.index(field)
                 self.fields.insert(idx + 1, full_sequence)
+
+                # If the event contains any 64-bit extended fields, they need
+                # to remain aligned on a 64-bit boundary.  Adding full_sequence
+                # would normally break that; force the struct to be packed.
+                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
     _c_opcode(name, self.opcodes[name])
 
     if self.name == name:
         # Structure definition
 
     # Opcode define
     _c_opcode(name, self.opcodes[name])
 
     if self.name == name:
         # Structure definition
-        _c_complex(self)
+        _c_complex(self, force_packed)
     else:
         # Typedef
         _h('')
         _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
 
     else:
         # Typedef
         _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):
     _man_event(self, name)
 
 def c_error(self, name):
@@ -2957,20 +3241,26 @@ output = {'open'    : c_open,
           'union'   : c_union,
           'request' : c_request,
           'event'   : c_event,
           'union'   : c_union,
           'request' : c_request,
           'event'   : c_event,
-          'error'   : c_error, 
+          'error'   : c_error,
           }
 
 # Boilerplate below this point
 
 # Check for the argument that specifies path to the xcbgen python package.
 try:
           }
 
 # Boilerplate below this point
 
 # Check for the argument that specifies path to the xcbgen python package.
 try:
-    opts, args = getopt.getopt(sys.argv[1:], 'p:m')
+    opts, args = getopt.getopt(sys.argv[1:], 'c:l:s:p:m')
 except getopt.GetoptError as err:
     print(err)
 except getopt.GetoptError as err:
     print(err)
-    print('Usage: c_client.py [-p path] file.xml')
+    print('Usage: c_client.py -c center_footer -l left_footer -s section [-p path] file.xml')
     sys.exit(1)
 
 for (opt, arg) in opts:
     sys.exit(1)
 
 for (opt, arg) in opts:
+    if opt == '-c':
+        center_footer=arg
+    if opt == '-l':
+        left_footer=arg
+    if opt == '-s':
+        section=arg
     if opt == '-p':
         sys.path.insert(1, arg)
     elif opt == '-m':
     if opt == '-p':
         sys.path.insert(1, arg)
     elif opt == '-m':
@@ -2998,8 +3288,6 @@ except OSError as e:
     if e.errno != errno.EEXIST:
         raise
 
     if e.errno != errno.EEXIST:
         raise
 
-today = time.strftime('%Y-%m-%d', time.gmtime(os.path.getmtime(args[0])))
-
 # Parse the xml header
 module = Module(args[0], output)
 
 # Parse the xml header
 module = Module(args[0], output)