c_client.py: remove useless 'today' variable
[free-sw/xcb/libxcb] / src / c_client.py
index 31ed3b5..4f66b48 100644 (file)
@@ -176,6 +176,9 @@ def c_open(self):
     _h('')
     _h('#include "xcb.h"')
 
     _h('')
     _h('#include "xcb.h"')
 
+    _c('#ifdef HAVE_CONFIG_H')
+    _c('#include "config.h"')
+    _c('#endif')
     _c('#include <stdlib.h>')
     _c('#include <string.h>')
     _c('#include <assert.h>')
     _c('#include <stdlib.h>')
     _c('#include <string.h>')
     _c('#include <assert.h>')
@@ -187,7 +190,7 @@ def c_open(self):
     _c('#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)')
 
     if _ns.is_ext:
     _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('')
@@ -300,6 +303,7 @@ def _c_type_setup(self, name, postfix):
     self.c_reply_name = _n(name + ('reply',))
     self.c_reply_type = _t(name + ('reply',))
     self.c_cookie_type = _t(name + ('cookie',))
     self.c_reply_name = _n(name + ('reply',))
     self.c_reply_type = _t(name + ('reply',))
     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_aux = False
     self.need_serialize = False
@@ -684,10 +688,20 @@ def _c_serialize_helper_switch(context, self, complex_name,
     switch_expr = _c_accessor_get_expr(self.expr, None)
 
     for b in self.bitcases:            
     switch_expr = _c_accessor_get_expr(self.expr, None)
 
     for b in self.bitcases:            
-        bitcase_expr = _c_accessor_get_expr(b.type.expr, None)
-        code_lines.append('    if(%s & %s) {' % (switch_expr, bitcase_expr))
-#        code_lines.append('        printf("switch %s: entering bitcase section %s (mask=%%%%d)...\\n", %s);' % 
-#                          (self.name[-1], b.type.name[-1], bitcase_expr))
+        len_expr = len(b.type.expr)
+        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))
+            # multiple <enumref> in the <bitcase>
+            elif n == 0: # first
+                code_lines.append('    if((%s & %s) ||' % (switch_expr, bitcase_expr))
+            elif len_expr == (n + 1): # last
+                code_lines.append('       (%s & %s)) {' % (switch_expr, bitcase_expr))
+            else: # between first and last
+                code_lines.append('       (%s & %s) ||' % (switch_expr, 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)]
@@ -967,15 +981,22 @@ def _c_serialize_helper_fields(context, self,
 
         # fields with variable size
         else:
 
         # fields with variable size
         else:
-            # switch/bitcase: always calculate padding before and after variable sized fields
-            if need_padding or is_bitcase:
+            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, 
                 count += _c_serialize_helper_insert_padding(context, code_lines, space, 
+                                                        self.var_followed_by_fixed_fields)
+                continue
+            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)
 
                                                             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
+                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:
@@ -1047,8 +1068,8 @@ def _c_serialize_helper(context, complex_type,
         if context in ('unserialize', 'unpack', 'sizeof') and not self.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)
         if context in ('unserialize', 'unpack', 'sizeof') and not self.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)
-            # probably not needed
-            #_c_serialize_helper_insert_padding(context, code_lines, space, False)
+            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, 
@@ -1119,11 +1140,11 @@ def _c_serialize(context, self):
             _c('    %s *xcb_out = *_buffer;', self.c_type)
             _c('    unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
             _c('    unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
             _c('    %s *xcb_out = *_buffer;', self.c_type)
             _c('    unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
             _c('    unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
-            _c('    unsigned int xcb_align_to;')
+            _c('    unsigned int xcb_align_to = 0;')
         else:
             _c('    char *xcb_out = *_buffer;')
             _c('    unsigned int xcb_buffer_len = 0;')
         else:
             _c('    char *xcb_out = *_buffer;')
             _c('    unsigned int xcb_buffer_len = 0;')
-            _c('    unsigned int xcb_align_to;')
+            _c('    unsigned int xcb_align_to = 0;')
         prefix = [('_aux', '->', self)]
         aux_ptr = 'xcb_out'
 
         prefix = [('_aux', '->', self)]
         aux_ptr = 'xcb_out'
 
@@ -1146,7 +1167,7 @@ def _c_serialize(context, self):
         _c('    unsigned int xcb_buffer_len = 0;')
         _c('    unsigned int xcb_block_len = 0;')
         _c('    unsigned int xcb_pad = 0;')
         _c('    unsigned int xcb_buffer_len = 0;')
         _c('    unsigned int xcb_block_len = 0;')
         _c('    unsigned int xcb_pad = 0;')
-        _c('    unsigned int xcb_align_to;')
+        _c('    unsigned int xcb_align_to = 0;')
 
     elif 'sizeof' == context:
         param_names = [p[2] for p in params]
 
     elif 'sizeof' == context:
         param_names = [p[2] for p in params]
@@ -1191,7 +1212,7 @@ def _c_serialize(context, self):
             _c('    unsigned int xcb_buffer_len = 0;')
             _c('    unsigned int xcb_block_len = 0;')
             _c('    unsigned int xcb_pad = 0;')        
             _c('    unsigned int xcb_buffer_len = 0;')
             _c('    unsigned int xcb_block_len = 0;')
             _c('    unsigned int xcb_pad = 0;')        
-            _c('    unsigned int xcb_align_to;')
+            _c('    unsigned int xcb_align_to = 0;')
 
     _c('')
     for t in temp_vars:
 
     _c('')
     for t in temp_vars:
@@ -1527,6 +1548,17 @@ def _c_accessors_list(self, field):
     Declares a direct-accessor function only if the list members are fixed size.
     Declares length and get-iterator functions always.
     '''
     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
 
@@ -1602,9 +1634,16 @@ 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('')
@@ -1706,9 +1745,17 @@ def _c_accessors_list(self, field):
         elif field.prev_varsized_field == None:
             _c('    i.data = (%s *) (R + 1);', field.c_field_type)
         else:
         elif field.prev_varsized_field == None:
             _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('    i.data = (%s *) ((char *) prev.data + %s);',
+                field.c_field_type, align_pad)
+
         if switch_obj is None:
             _c('    i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
         _c('    i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
         if switch_obj is None:
             _c('    i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
         _c('    i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
@@ -1726,10 +1773,11 @@ def _c_accessors(self, name, base):
 #    else:
     if True:
         for field in self.fields:
 #    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 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)
 
 def c_simple(self, name):
     '''
 
 def c_simple(self, name):
     '''
@@ -1748,7 +1796,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.
@@ -1774,12 +1822,12 @@ def _c_complex(self):
     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
-        if not field.type.fixed_size():
+        if not field.type.fixed_size() and not self.is_union:
             length += 1
         maxtypelen = max(maxtypelen, length)
 
     def _c_complex_field(self, field, space=''):
             length += 1
         maxtypelen = max(maxtypelen, length)
 
     def _c_complex_field(self, field, space=''):
-        if (field.type.fixed_size() or 
+        if (field.type.fixed_size() or self.is_union or
             # in case of switch with switch children, don't make the field a pointer
             # necessary for unserialize to work
             (self.is_switch and field.type.is_switch)):
             # in case of switch with switch children, don't make the field a pointer
             # necessary for unserialize to work
             (self.is_switch and field.type.is_switch)):
@@ -1803,7 +1851,7 @@ def _c_complex(self):
             if b.type.has_name:
                 _h('    } %s;', b.c_field_name)
 
             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):
     '''
@@ -1822,7 +1870,7 @@ def c_union(self, name):
     _c_complex(self)
     _c_iterator(self, name)
 
     _c_complex(self)
     _c_iterator(self, name)
 
-def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
+def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_fds=False):
     '''
     Declares a request function.
     '''
     '''
     Declares a request function.
     '''
@@ -1851,6 +1899,12 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
     # What flag is passed to xcb_request
     func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
 
     # What flag is passed to xcb_request
     func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
 
+    if reply_fds:
+        if func_flags == '0':
+            func_flags = 'XCB_REQUEST_REPLY_FDS'
+        else:
+            func_flags = func_flags + '|XCB_REQUEST_REPLY_FDS'
+
     # Global extension id variable or NULL for xproto
     func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
 
     # Global extension id variable or NULL for xproto
     func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
 
@@ -2136,6 +2190,10 @@ def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
         # no padding necessary - _serialize() keeps track of padding automatically
 
     _c('    ')
         # no padding necessary - _serialize() keeps track of padding automatically
 
     _c('    ')
+    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)
     
     # free dyn. all. data, if any
     _c('    xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
     
     # free dyn. all. data, if any
@@ -2239,6 +2297,51 @@ def _c_reply(self, name):
 
     _c('}')
 
 
     _c('}')
 
+def _c_reply_has_fds(self):
+    for field in self.fields:
+        if field.isfd:
+            return True
+    return False
+
+def _c_reply_fds(self, name):
+    '''
+    Declares the function that returns fds related to the reply.
+    '''
+    spacing1 = ' ' * (len(self.c_reply_type) - len('xcb_connection_t'))
+    spacing3 = ' ' * (len(self.c_reply_fds_name) + 2)
+    _h('')
+    _h('/**')
+    _h(' * Return the reply fds')
+    _h(' * @param c      The connection')
+    _h(' * @param reply  The reply')
+    _h(' *')
+    _h(' * Returns the array of reply fds of the request asked by')
+    _h(' * ')
+    _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('{')
+    
+    _c('    return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
+
+    _c('}')
+    
+
 def _c_opcode(name, opcode):
     '''
     Declares the opcode define for requests, events, and errors.
 def _c_opcode(name, opcode):
     '''
     Declares the opcode define for requests, events, and errors.
@@ -2267,18 +2370,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')
@@ -2603,17 +2706,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.iteritems():
+        for errtype, errtext in 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))
@@ -2628,18 +2731,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.iteritems():
+            see.append('.BR %s (%s)' % ('xcb-examples', section))
+        for seename, seetype in 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')
@@ -2649,10 +2752,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')
@@ -2758,18 +2861,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.iteritems():
+            see.append('.BR %s (%s)' % ('xcb-examples', section))
+        for seename, seetype in 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')
@@ -2799,14 +2902,17 @@ def c_request(self, name):
         # Reply structure definition
         _c_complex(self.reply)
         # Request prototypes
         # Reply structure definition
         _c_complex(self.reply)
         # Request prototypes
-        _c_request_helper(self, name, self.c_cookie_type, False, True)
-        _c_request_helper(self, name, self.c_cookie_type, False, False)
+        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.need_aux:
-            _c_request_helper(self, name, self.c_cookie_type, False, True, True)
-            _c_request_helper(self, name, self.c_cookie_type, False, False, True)
+            _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_accessors(self.reply, name + ('reply',), name)
         _c_reply(self, name)
         # Reply accessors
         _c_accessors(self.reply, name + ('reply',), name)
         _c_reply(self, name)
+        if has_fds:
+            _c_reply_fds(self, name)
     else:
         # Request prototypes
         _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
     else:
         # Request prototypes
         _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
@@ -2824,6 +2930,29 @@ def c_event(self, name):
     '''
     Exported function that handles event declarations.
     '''
     '''
     Exported function that handles event declarations.
     '''
+
+    # The generic event structure xcb_ge_event_t has the full_sequence field
+    # at the 32byte boundary. That's why we've to inject this field into GE
+    # 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 field.type.size != None and field.type.nmemb != None:
+                event_size += field.type.size * field.type.nmemb
+            if event_size == 32:
+                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
+
     _c_type_setup(self, name, ('event',))
 
     # Opcode define
     _c_type_setup(self, name, ('event',))
 
     # Opcode define
@@ -2831,7 +2960,7 @@ def c_event(self, name):
 
     if self.name == name:
         # Structure definition
 
     if self.name == name:
         # Structure definition
-        _c_complex(self)
+        _c_complex(self, force_packed)
     else:
         # Typedef
         _h('')
     else:
         # Typedef
         _h('')
@@ -2875,13 +3004,19 @@ output = {'open'    : c_open,
 
 # Check for the argument that specifies path to the xcbgen python package.
 try:
 
 # 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':
@@ -2905,12 +3040,10 @@ Refer to the README file in xcb/proto for more info.
 # Ensure the man subdirectory exists
 try:
     os.mkdir('man')
 # Ensure the man subdirectory exists
 try:
     os.mkdir('man')
-except OSError, e:
+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)