Only #include directly referenced module header files
[free-sw/xcb/libxcb] / src / c_client.py
1 #!/usr/bin/env python
2 from xml.etree.cElementTree import *
3 from os.path import basename
4 from functools import reduce
5 import getopt
6 import os
7 import sys
8 import errno
9 import time
10 import re
11
12 # Jump to the bottom of this file for the main routine
13
14 # Some hacks to make the API more readable, and to keep backwards compability
15 _cname_re = re.compile('([A-Z0-9][a-z]+|[A-Z0-9]+(?![a-z])|[a-z]+)')
16 _cname_special_cases = {'DECnet':'decnet'}
17
18 _extension_special_cases = ['XPrint', 'XCMisc', 'BigRequests']
19
20 _cplusplus_annoyances = {'class' : '_class',
21                          'new'   : '_new',
22                          'delete': '_delete'}
23 _c_keywords = {'default' : '_default'}
24
25 _hlines = []
26 _hlevel = 0
27 _clines = []
28 _clevel = 0
29 _ns = None
30
31 # global variable to keep track of serializers and 
32 # switch data types due to weird dependencies
33 finished_serializers = []
34 finished_sizeof = []
35 finished_switch = []
36
37 # keeps enum objects so that we can refer to them when generating manpages.
38 enums = {}
39
40 manpaths = False
41
42 def _h(fmt, *args):
43     '''
44     Writes the given line to the header file.
45     '''
46     _hlines[_hlevel].append(fmt % args)
47     
48 def _c(fmt, *args):
49     '''
50     Writes the given line to the source file.
51     '''
52     _clines[_clevel].append(fmt % args)
53     
54 def _hc(fmt, *args):
55     '''
56     Writes the given line to both the header and source files.
57     '''
58     _h(fmt, *args)
59     _c(fmt, *args)
60
61 # XXX See if this level thing is really necessary.
62 def _h_setlevel(idx):
63     '''
64     Changes the array that header lines are written to.
65     Supports writing different sections of the header file.
66     '''
67     global _hlevel
68     while len(_hlines) <= idx:
69         _hlines.append([])
70     _hlevel = idx
71     
72 def _c_setlevel(idx):
73     '''
74     Changes the array that source lines are written to.
75     Supports writing to different sections of the source file.
76     '''
77     global _clevel
78     while len(_clines) <= idx:
79         _clines.append([])
80     _clevel = idx
81     
82 def _n_item(str):
83     '''
84     Does C-name conversion on a single string fragment.
85     Uses a regexp with some hard-coded special cases.
86     '''
87     if str in _cname_special_cases:
88         return _cname_special_cases[str]
89     else:
90         split = _cname_re.finditer(str)
91         name_parts = [match.group(0) for match in split]
92         return '_'.join(name_parts)
93     
94 def _cpp(str):
95     '''
96     Checks for certain C++ reserved words and fixes them.
97     '''
98     if str in _cplusplus_annoyances:
99         return _cplusplus_annoyances[str]
100     elif str in _c_keywords:
101         return  _c_keywords[str]
102     else:
103         return str
104
105 def _ext(str):
106     '''
107     Does C-name conversion on an extension name.
108     Has some additional special cases on top of _n_item.
109     '''
110     if str in _extension_special_cases:
111         return _n_item(str).lower()
112     else:
113         return str.lower()
114     
115 def _n(list):
116     '''
117     Does C-name conversion on a tuple of strings.
118     Different behavior depending on length of tuple, extension/not extension, etc.
119     Basically C-name converts the individual pieces, then joins with underscores.
120     '''
121     if len(list) == 1:
122         parts = list
123     elif len(list) == 2:
124         parts = [list[0], _n_item(list[1])]
125     elif _ns.is_ext:
126         parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
127     else:
128         parts = [list[0]] + [_n_item(i) for i in list[1:]]
129     return '_'.join(parts).lower()
130
131 def _t(list):
132     '''
133     Does C-name conversion on a tuple of strings representing a type.
134     Same as _n but adds a "_t" on the end.
135     '''
136     if len(list) == 1:
137         parts = list
138     elif len(list) == 2:
139         parts = [list[0], _n_item(list[1]), 't']
140     elif _ns.is_ext:
141         parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
142     else:
143         parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
144     return '_'.join(parts).lower()
145         
146
147 def c_open(self):
148     '''
149     Exported function that handles module open.
150     Opens the files and writes out the auto-generated comment, header file includes, etc.
151     '''
152     global _ns
153     _ns = self.namespace
154     _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
155
156     # Build the type-name collision avoidance table used by c_enum
157     build_collision_table()
158
159     _h_setlevel(0)
160     _c_setlevel(0)
161
162     _hc('/*')
163     _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
164     _hc(' * Edit at your peril.')
165     _hc(' */')
166     _hc('')
167
168     _h('/**')
169     _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
170     _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
171     _h(' * @{')
172     _h(' **/')
173     _h('')
174     _h('#ifndef __%s_H', _ns.header.upper())
175     _h('#define __%s_H', _ns.header.upper())
176     _h('')
177     _h('#include "xcb.h"')
178
179     _c('#ifdef HAVE_CONFIG_H')
180     _c('#include "config.h"')
181     _c('#endif')
182     _c('#include <stdlib.h>')
183     _c('#include <string.h>')
184     _c('#include <assert.h>')
185     _c('#include <stddef.h>  /* for offsetof() */')
186     _c('#include "xcbext.h"')
187     _c('#include "%s.h"', _ns.header)
188         
189     _c('')
190     _c('#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)')
191
192     if _ns.is_ext:
193         for (n, h) in self.direct_imports:
194             _hc('#include "%s.h"', h)
195
196     _h('')
197     _h('#ifdef __cplusplus')
198     _h('extern "C" {')
199     _h('#endif')
200
201     if _ns.is_ext:
202         _h('')
203         _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
204         _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
205         _h('  ') #XXX
206         _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
207
208         _c('')
209         _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
210
211 def c_close(self):
212     '''
213     Exported function that handles module close.
214     Writes out all the stored content lines, then closes the files.
215     '''
216     _h_setlevel(2)
217     _c_setlevel(2)
218     _hc('')
219
220     _h('')
221     _h('#ifdef __cplusplus')
222     _h('}')
223     _h('#endif')
224
225     _h('')
226     _h('#endif')
227     _h('')
228     _h('/**')
229     _h(' * @}')
230     _h(' */')
231
232     # Write header file
233     hfile = open('%s.h' % _ns.header, 'w')
234     for list in _hlines:
235         for line in list:
236             hfile.write(line)
237             hfile.write('\n')
238     hfile.close()
239
240     # Write source file
241     cfile = open('%s.c' % _ns.header, 'w')
242     for list in _clines:
243         for line in list:
244             cfile.write(line)
245             cfile.write('\n')
246     cfile.close()
247
248 def build_collision_table():
249     global namecount
250     namecount = {}
251
252     for v in module.types.values():
253         name = _t(v[0])
254         namecount[name] = (namecount.get(name) or 0) + 1
255
256 def c_enum(self, name):
257     '''
258     Exported function that handles enum declarations.
259     '''
260
261     enums[name] = self
262
263     tname = _t(name)
264     if namecount[tname] > 1:
265         tname = _t(name + ('enum',))
266
267     _h_setlevel(0)
268     _h('')
269     _h('typedef enum %s {', tname)
270
271     count = len(self.values)
272
273     for (enam, eval) in self.values:
274         count = count - 1
275         equals = ' = ' if eval != '' else ''
276         comma = ',' if count > 0 else ''
277         doc = ''
278         if hasattr(self, "doc") and self.doc and enam in self.doc.fields:
279             doc = '\n/**< %s */\n' % self.doc.fields[enam]
280         _h('    %s%s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma, doc)
281
282     _h('} %s;', tname)
283
284 def _c_type_setup(self, name, postfix):
285     '''
286     Sets up all the C-related state by adding additional data fields to
287     all Field and Type objects.  Here is where we figure out most of our
288     variable and function names.
289
290     Recurses into child fields and list member types.
291     '''
292     # Do all the various names in advance
293     self.c_type = _t(name + postfix)
294     self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
295
296     self.c_iterator_type = _t(name + ('iterator',))
297     self.c_next_name = _n(name + ('next',))
298     self.c_end_name = _n(name + ('end',))
299
300     self.c_request_name = _n(name)
301     self.c_checked_name = _n(name + ('checked',))
302     self.c_unchecked_name = _n(name + ('unchecked',))
303     self.c_reply_name = _n(name + ('reply',))
304     self.c_reply_type = _t(name + ('reply',))
305     self.c_cookie_type = _t(name + ('cookie',))
306     self.c_reply_fds_name = _n(name + ('reply_fds',))
307
308     self.need_aux = False
309     self.need_serialize = False
310     self.need_sizeof = False
311
312     self.c_aux_name = _n(name + ('aux',))
313     self.c_aux_checked_name = _n(name + ('aux', 'checked'))
314     self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
315     self.c_serialize_name = _n(name + ('serialize',))
316     self.c_unserialize_name = _n(name + ('unserialize',))
317     self.c_unpack_name = _n(name + ('unpack',))
318     self.c_sizeof_name = _n(name + ('sizeof',))
319
320     # special case: structs where variable size fields are followed by fixed size fields
321     self.var_followed_by_fixed_fields = False
322
323     if self.is_switch:
324         self.need_serialize = True
325         self.c_container = 'struct'
326         for bitcase in self.bitcases:
327             bitcase.c_field_name = _cpp(bitcase.field_name)
328             bitcase_name = bitcase.field_type if bitcase.type.has_name else name
329             _c_type_setup(bitcase.type, bitcase_name, ())
330
331     elif self.is_container:
332
333         self.c_container = 'union' if self.is_union else 'struct'
334         prev_varsized_field = None
335         prev_varsized_offset = 0
336         first_field_after_varsized = None
337
338         for field in self.fields:
339             _c_type_setup(field.type, field.field_type, ())
340             if field.type.is_list:
341                 _c_type_setup(field.type.member, field.field_type, ())
342                 if (field.type.nmemb is None): 
343                     self.need_sizeof = True
344
345             field.c_field_type = _t(field.field_type)
346             field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
347             field.c_field_name = _cpp(field.field_name)
348             field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb and field.type.nmemb > 1) else ''
349             field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
350
351             # correct the c_pointer field for variable size non-list types
352             if not field.type.fixed_size() and field.c_pointer == ' ':
353                 field.c_pointer = '*'
354             if field.type.is_list and not field.type.member.fixed_size():
355                 field.c_pointer = '*'
356
357             if field.type.is_switch:
358                 field.c_pointer = '*'
359                 field.c_field_const_type = 'const ' + field.c_field_type
360                 self.need_aux = True
361             elif not field.type.fixed_size() and not field.type.is_bitcase:
362                 self.need_sizeof = True
363
364             field.c_iterator_type = _t(field.field_type + ('iterator',))      # xcb_fieldtype_iterator_t
365             field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
366             field.c_accessor_name = _n(name + (field.field_name,))            # xcb_container_field
367             field.c_length_name = _n(name + (field.field_name, 'length'))     # xcb_container_field_length
368             field.c_end_name = _n(name + (field.field_name, 'end'))           # xcb_container_field_end
369
370             field.prev_varsized_field = prev_varsized_field
371             field.prev_varsized_offset = prev_varsized_offset
372
373             if prev_varsized_offset == 0:
374                 first_field_after_varsized = field
375             field.first_field_after_varsized = first_field_after_varsized
376
377             if field.type.fixed_size():
378                 prev_varsized_offset += field.type.size
379                 # special case: intermixed fixed and variable size fields
380                 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
381                     if not self.is_union:
382                         self.need_serialize = True
383                         self.var_followed_by_fixed_fields = True
384             else:
385                 self.last_varsized_field = field
386                 prev_varsized_field = field
387                 prev_varsized_offset = 0                    
388
389             if self.var_followed_by_fixed_fields:
390                 if field.type.fixed_size():
391                     field.prev_varsized_field = None
392                             
393     if self.need_serialize:
394         # when _unserialize() is wanted, create _sizeof() as well for consistency reasons 
395         self.need_sizeof = True
396
397     # as switch does never appear at toplevel, 
398     # continue here with type construction
399     if self.is_switch:
400         if self.c_type not in finished_switch:
401             finished_switch.append(self.c_type)
402             # special: switch C structs get pointer fields for variable-sized members
403             _c_complex(self)
404             for bitcase in self.bitcases:
405                 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
406                 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
407                 # no list with switch as element, so no call to 
408                 # _c_iterator(field.type, field_name) necessary
409
410     if not self.is_bitcase:
411         if self.need_serialize:
412             if self.c_serialize_name not in finished_serializers:
413                 finished_serializers.append(self.c_serialize_name)
414                 _c_serialize('serialize', self)
415
416                 # _unpack() and _unserialize() are only needed for special cases:
417                 #   switch -> unpack
418                 #   special cases -> unserialize
419                 if self.is_switch or self.var_followed_by_fixed_fields:
420                     _c_serialize('unserialize', self)
421                     
422         if self.need_sizeof:
423             if self.c_sizeof_name not in finished_sizeof:
424                 if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
425                     finished_sizeof.append(self.c_sizeof_name)
426                     _c_serialize('sizeof', self)
427 # _c_type_setup()
428
429 def _c_helper_absolute_name(prefix, field=None):
430     """
431     turn prefix, which is a list of tuples (name, separator, Type obj) into a string
432     representing a valid name in C (based on the context)
433     if field is not None, append the field name as well
434     """
435     prefix_str = ''
436     for name, sep, obj in prefix:
437         prefix_str += name
438         if '' == sep:
439             sep = '->'
440             if ((obj.is_bitcase and obj.has_name) or     # named bitcase
441                 (obj.is_switch and len(obj.parents)>1)):
442                 sep = '.'
443         prefix_str += sep
444     if field is not None:
445         prefix_str += _cpp(field.field_name)
446     return prefix_str
447 # _c_absolute_name
448     
449 def _c_helper_field_mapping(complex_type, prefix, flat=False):
450     """
451     generate absolute names, based on prefix, for all fields starting from complex_type
452     if flat == True, nested complex types are not taken into account
453     """
454     all_fields = {}
455     if complex_type.is_switch:
456         for b in complex_type.bitcases:
457             if b.type.has_name:
458                 switch_name, switch_sep, switch_type = prefix[-1]
459                 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
460             else:
461                 bitcase_prefix = prefix 
462
463             if (True==flat and not b.type.has_name) or False==flat:
464                 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
465     else:
466         for f in complex_type.fields:
467             fname = _c_helper_absolute_name(prefix, f)
468             if f.field_name in all_fields:
469                 raise Exception("field name %s has been registered before" % f.field_name)
470
471             all_fields[f.field_name] = (fname, f)
472             if f.type.is_container and flat==False:
473                 if f.type.is_bitcase and not f.type.has_name:
474                     new_prefix = prefix
475                 elif f.type.is_switch and len(f.type.parents)>1:
476                     # nested switch gets another separator
477                     new_prefix = prefix+[(f.c_field_name, '.', f.type)]
478                 else:
479                     new_prefix = prefix+[(f.c_field_name, '->', f.type)]
480                 all_fields.update(_c_helper_field_mapping(f.type, new_prefix, flat))
481
482     return all_fields
483 # _c_field_mapping()
484
485 def _c_helper_resolve_field_names (prefix):
486     """
487     get field names for all objects in the prefix array
488     """
489     all_fields = {}
490     tmp_prefix = []
491     # look for fields in the remaining containers
492     for idx, p in enumerate(prefix):
493         name, sep, obj = p
494         if ''==sep:
495             # sep can be preset in prefix, if not, make a sensible guess
496             sep = '.' if (obj.is_switch or obj.is_bitcase) else '->'
497             # exception: 'toplevel' object (switch as well!) always have sep '->'
498             sep = '->' if idx<1 else sep
499         if not obj.is_bitcase or (obj.is_bitcase and obj.has_name):
500             tmp_prefix.append((name, sep, obj))
501         all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
502
503     return all_fields
504 # _c_helper_resolve_field_names
505
506 def get_expr_fields(self):
507     """
508     get the Fields referenced by switch or list expression 
509     """
510     def get_expr_field_names(expr):
511         if expr.op is None:
512             if expr.lenfield_name is not None:
513                 return [expr.lenfield_name]
514             else:
515                 # constant value expr
516                 return []
517         else:
518             if expr.op == '~':
519                 return get_expr_field_names(expr.rhs)
520             elif expr.op == 'popcount':
521                 return get_expr_field_names(expr.rhs)
522             elif expr.op == 'sumof':
523                 # sumof expr references another list, 
524                 # we need that list's length field here
525                 field = None
526                 for f in expr.lenfield_parent.fields:
527                     if f.field_name == expr.lenfield_name:
528                         field = f
529                         break
530                 if field is None:
531                     raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
532                 # referenced list + its length field
533                 return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
534             elif expr.op == 'enumref':
535                 return []
536             else:
537                 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
538     # get_expr_field_names()
539     
540     # resolve the field names with the parent structure(s)
541     unresolved_fields_names = get_expr_field_names(self.expr)
542
543     # construct prefix from self
544     prefix = [('', '', p) for p in self.parents]
545     if self.is_container:
546         prefix.append(('', '', self))
547
548     all_fields = _c_helper_resolve_field_names (prefix)
549     resolved_fields_names = list(filter(lambda x: x in all_fields.keys(), unresolved_fields_names))
550     if len(unresolved_fields_names) != len(resolved_fields_names):
551         raise Exception("could not resolve all fields for %s" % self.name)
552     
553     resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
554     return resolved_fields
555 # get_expr_fields()
556
557 def resolve_expr_fields(complex_obj):
558     """
559     find expr fields appearing in complex_obj and descendents that cannot be resolved within complex_obj
560     these are normally fields that need to be given as function parameters
561     """
562     all_fields = []
563     expr_fields = []
564     unresolved = []
565
566     for field in complex_obj.fields:
567         all_fields.append(field)
568         if field.type.is_switch or field.type.is_list:
569             expr_fields += get_expr_fields(field.type)
570         if field.type.is_container:
571             expr_fields += resolve_expr_fields(field.type)
572
573     # try to resolve expr fields
574     for e in expr_fields:
575         if e not in all_fields and e not in unresolved:
576             unresolved.append(e)
577     return unresolved
578 # resolve_expr_fields()
579             
580 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
581     """
582     functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
583     E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch 
584     expression. This function tries to resolve all fields within a structure, and returns the 
585     unresolved fields as the list of external parameters. 
586     """
587     def add_param(params, param):
588         if param not in params:
589             params.append(param)
590
591     # collect all fields into param_fields
592     param_fields = []
593     wire_fields = []
594
595     for field in self.fields:
596         if field.visible:
597             # the field should appear as a parameter in the function call
598             param_fields.append(field)
599         if field.wire and not field.auto:
600             if field.type.fixed_size() and not self.is_switch:
601                 # field in the xcb_out structure
602                 wire_fields.append(field)
603         # fields like 'pad0' are skipped!
604                
605     # in case of switch, parameters always contain any fields referenced in the switch expr
606     # we do not need any variable size fields here, as the switch data type contains both 
607     # fixed and variable size fields
608     if self.is_switch:
609         param_fields = get_expr_fields(self)
610
611     # _serialize()/_unserialize()/_unpack() function parameters
612     # note: don't use set() for params, it is unsorted
613     params = []
614     
615     # 1. the parameter for the void * buffer
616     if  'serialize' == context:
617         params.append(('void', '**', buffer_var))
618     elif context in ('unserialize', 'unpack', 'sizeof'):
619         params.append(('const void', '*', buffer_var))
620
621     # 2. any expr fields that cannot be resolved within self and descendants
622     unresolved_fields = resolve_expr_fields(self)
623     for f in unresolved_fields:
624         add_param(params, (f.c_field_type, '', f.c_field_name))
625
626     # 3. param_fields contain the fields necessary to evaluate the switch expr or any other fields
627     #    that do not appear in the data type struct
628     for p in param_fields:
629         if self.is_switch:
630             typespec = p.c_field_const_type
631             pointerspec = p.c_pointer 
632             add_param(params, (typespec, pointerspec, p.c_field_name))
633         else:
634             if p.visible and not p.wire and not p.auto:
635                 typespec = p.c_field_type
636                 pointerspec = ''
637                 add_param(params, (typespec, pointerspec, p.c_field_name))
638   
639     # 4. aux argument
640     if 'serialize' == context:
641         add_param(params, ('const %s' % self.c_type, '*', aux_var))
642     elif 'unserialize' == context: 
643         add_param(params, ('%s' % self.c_type, '**', aux_var))
644     elif 'unpack' == context:
645         add_param(params, ('%s' % self.c_type, '*', aux_var))
646
647     # 5. switch contains all variable size fields as struct members
648     #    for other data types though, these have to be supplied separately
649     #    this is important for the special case of intermixed fixed and 
650     #    variable size fields
651     if not self.is_switch and 'serialize' == context:
652         for p in param_fields:
653             if not p.type.fixed_size():
654                 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
655
656     return (param_fields, wire_fields, params)
657 # get_serialize_params()
658
659 def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
660     code_lines.append('%s    /* insert padding */' % space)
661     code_lines.append('%s    xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
662 #    code_lines.append('%s    printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
663     code_lines.append('%s    xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
664
665     if not postpone:
666         code_lines.append('%s    if (0 != xcb_pad) {' % space)
667
668         if 'serialize' == context:
669             code_lines.append('%s        xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
670             code_lines.append('%s        xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
671             code_lines.append('%s        xcb_parts_idx++;' % space)
672         elif context in ('unserialize', 'unpack', 'sizeof'):
673             code_lines.append('%s        xcb_tmp += xcb_pad;' % space)
674
675         code_lines.append('%s        xcb_pad = 0;' % space)
676         code_lines.append('%s    }' % space)
677         
678     code_lines.append('%s    xcb_block_len = 0;' % space)
679
680     # keep tracking of xcb_parts entries for serialize
681     return 1
682 # _c_serialize_helper_insert_padding()
683
684 def _c_serialize_helper_switch(context, self, complex_name, 
685                                code_lines, temp_vars, 
686                                space, prefix):
687     count = 0
688     switch_expr = _c_accessor_get_expr(self.expr, None)
689
690     for b in self.bitcases:            
691         len_expr = len(b.type.expr)
692         for n, expr in enumerate(b.type.expr):
693             bitcase_expr = _c_accessor_get_expr(expr, None)
694             # only one <enumref> in the <bitcase>
695             if len_expr == 1:
696                 code_lines.append('    if(%s & %s) {' % (switch_expr, bitcase_expr))
697             # multiple <enumref> in the <bitcase>
698             elif n == 0: # first
699                 code_lines.append('    if((%s & %s) ||' % (switch_expr, bitcase_expr))
700             elif len_expr == (n + 1): # last
701                 code_lines.append('       (%s & %s)) {' % (switch_expr, bitcase_expr))
702             else: # between first and last
703                 code_lines.append('       (%s & %s) ||' % (switch_expr, bitcase_expr))
704
705         b_prefix = prefix
706         if b.type.has_name:
707             b_prefix = prefix + [(b.c_field_name, '.', b.type)]
708             
709         count += _c_serialize_helper_fields(context, b.type, 
710                                             code_lines, temp_vars, 
711                                             "%s    " % space, 
712                                             b_prefix, 
713                                             is_bitcase = True)
714         code_lines.append('    }')
715
716 #    if 'serialize' == context:
717 #        count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
718 #    elif context in ('unserialize', 'unpack', 'sizeof'):
719 #        # padding
720 #        code_lines.append('%s    xcb_pad = -xcb_block_len & 3;' % space)
721 #        code_lines.append('%s    xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
722    
723     return count
724 # _c_serialize_helper_switch
725
726 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
727     """
728     handle switch by calling _serialize() or _unpack(), depending on context
729     """
730     # switch is handled by this function as a special case
731     param_fields, wire_fields, params = get_serialize_params(context, self)
732     field_mapping = _c_helper_field_mapping(self, prefix)
733     prefix_str = _c_helper_absolute_name(prefix)
734
735     # find the parameters that need to be passed to _serialize()/_unpack():
736     # all switch expr fields must be given as parameters
737     args = get_expr_fields(field.type)
738     # length fields for variable size types in switch, normally only some of need 
739     # need to be passed as parameters
740     switch_len_fields = resolve_expr_fields(field.type)
741
742     # a switch field at this point _must_ be a bitcase field
743     # we require that bitcases are "self-contiguous"
744     bitcase_unresolved = resolve_expr_fields(self)
745     if len(bitcase_unresolved) != 0:
746         raise Exception('unresolved fields within bitcase is not supported at this point')
747
748     # get the C names for the parameters  
749     c_field_names = ''
750     for a in switch_len_fields:
751         c_field_names += "%s, " % field_mapping[a.c_field_name][0]
752     for a in args:
753         c_field_names += "%s, " % field_mapping[a.c_field_name][0]
754
755     # call _serialize()/_unpack() to determine the actual size
756     if 'serialize' == context:
757         length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
758                                        c_field_names, prefix_str, field.c_field_name) 
759     elif context in ('unserialize', 'unpack'):
760         length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name, 
761                                            c_field_names, prefix_str, field.c_field_name)
762
763     return length
764 # _c_serialize_helper_switch_field()
765
766 def _c_serialize_helper_list_field(context, self, field, 
767                                    code_lines, temp_vars, 
768                                    space, prefix):
769     """
770     helper function to cope with lists of variable length
771     """
772     expr = field.type.expr
773     prefix_str = _c_helper_absolute_name(prefix)
774     param_fields, wire_fields, params = get_serialize_params('sizeof', self)
775     param_names = [p[2] for p in params]
776     
777     expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
778     resolved = list(filter(lambda x: x in param_names, expr_fields_names))
779     unresolved = list(filter(lambda x: x not in param_names, expr_fields_names))
780     
781     field_mapping = {}
782     for r in resolved:
783         field_mapping[r] = (r, None)
784     
785     if len(unresolved)>0:
786         tmp_prefix = prefix
787         if len(tmp_prefix)==0:
788             raise Exception("found an empty prefix while resolving expr field names for list %s", 
789                             field.c_field_name)        
790         
791         field_mapping.update(_c_helper_resolve_field_names(prefix))
792         resolved += list(filter(lambda x: x in field_mapping, unresolved))
793         unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
794         if len(unresolved)>0:
795             raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
796
797     list_length = _c_accessor_get_expr(expr, field_mapping)
798
799     # default: list with fixed size elements
800     length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
801
802     # list with variable-sized elements 
803     if not field.type.member.fixed_size():
804         length = ''
805         if context in ('unserialize', 'sizeof', 'unpack'):
806             int_i = '    unsigned int i;'
807             xcb_tmp_len = '    unsigned int xcb_tmp_len;'
808             if int_i not in temp_vars:
809                 temp_vars.append(int_i)
810             if xcb_tmp_len not in temp_vars:
811                 temp_vars.append(xcb_tmp_len)
812             # loop over all list elements and call sizeof repeatedly
813             # this should be a bit faster than using the iterators
814             code_lines.append("%s    for(i=0; i<%s; i++) {" % (space, list_length))
815             code_lines.append("%s        xcb_tmp_len = %s(xcb_tmp);" % 
816                               (space, field.type.c_sizeof_name))
817             code_lines.append("%s        xcb_block_len += xcb_tmp_len;" % space)
818             code_lines.append("%s        xcb_tmp += xcb_tmp_len;" % space)
819             code_lines.append("%s    }" % space)                  
820       
821         elif 'serialize' == context:
822             code_lines.append('%s    xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
823             code_lines.append('%s    xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
824             code_lines.append('%s    for(i=0; i<%s; i++) { ' % (space, list_length))
825             code_lines.append('%s        xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
826             code_lines.append('%s        xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
827             code_lines.append('%s    }' % space)
828             code_lines.append('%s    xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
829             
830     return length
831 # _c_serialize_helper_list_field()
832
833 def _c_serialize_helper_fields_fixed_size(context, self, field, 
834                                           code_lines, temp_vars, 
835                                           space, prefix):
836     # keep the C code a bit more readable by giving the field name
837     if not self.is_bitcase:
838         code_lines.append('%s    /* %s.%s */' % (space, self.c_type, field.c_field_name))
839     else:
840         scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
841         typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
842         code_lines.append('%s    /* %s.%s */' % (space, typename, field.c_field_name))
843
844     abs_field_name = _c_helper_absolute_name(prefix, field)
845     # default for simple cases: call sizeof()
846     length = "sizeof(%s)" % field.c_field_type
847
848     if context in ('unserialize', 'unpack', 'sizeof'):
849         # default: simple cast
850         value = '    %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type) 
851         
852         # padding - we could probably just ignore it
853         if field.type.is_pad and field.type.nmemb > 1:
854             value = ''
855             for i in range(field.type.nmemb):
856                 code_lines.append('%s    %s[%d] = *(%s *)xcb_tmp;' % 
857                                   (space, abs_field_name, i, field.c_field_type)) 
858             # total padding = sizeof(pad0) * nmemb
859             length += " * %d" % field.type.nmemb
860
861         if field.type.is_list:
862             # no such case in the protocol, cannot be tested and therefore ignored for now
863             raise Exception('list with fixed number of elemens unhandled in _unserialize()')
864
865     elif 'serialize' == context:
866         value = '    xcb_parts[xcb_parts_idx].iov_base = (char *) ' 
867
868         if field.type.is_expr:
869             # need to register a temporary variable for the expression in case we know its type
870             if field.type.c_type is None:
871                 raise Exception("type for field '%s' (expression '%s') unkown" % 
872                                 (field.field_name, _c_accessor_get_expr(field.type.expr)))
873             
874             temp_vars.append('    %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name), 
875                                                            _c_accessor_get_expr(field.type.expr, prefix)))
876             value += "&xcb_expr_%s;" % _cpp(field.field_name)
877
878         elif field.type.is_pad:
879             if field.type.nmemb == 1:
880                 value += "&xcb_pad;"
881             else:
882                 # we could also set it to 0, see definition of xcb_send_request()
883                 value = '    xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
884                 length += "*%d" % field.type.nmemb
885
886         else:
887             # non-list type with fixed size
888             if field.type.nmemb == 1:
889                 value += "&%s;" % (abs_field_name)
890
891             # list with nmemb (fixed size) elements
892             else:
893                 value += '%s;' % (abs_field_name)
894                 length = '%d' % field.type.nmemb
895
896     return (value, length)
897 # _c_serialize_helper_fields_fixed_size()
898
899 def _c_serialize_helper_fields_variable_size(context, self, field, 
900                                              code_lines, temp_vars, 
901                                              space, prefix):
902     prefix_str = _c_helper_absolute_name(prefix)
903
904     if context in ('unserialize', 'unpack', 'sizeof'):
905         value = ''
906         var_field_name = 'xcb_tmp'
907         
908         # special case: intermixed fixed and variable size fields
909         if self.var_followed_by_fixed_fields and 'unserialize' == context:
910             value = '    %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
911             temp_vars.append('    %s *%s;' % (field.type.c_type, field.c_field_name))
912         # special case: switch
913         if 'unpack' == context:
914             value = '    %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
915             
916     elif 'serialize' == context:
917         # variable size fields appear as parameters to _serialize() if the 
918         # 'toplevel' container is not a switch
919         prefix_string = prefix_str if prefix[0][2].is_switch else ''
920         var_field_name = "%s%s" % (prefix_string, field.c_field_name)
921         value = '    xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
922
923     length = ''
924
925     code_lines.append('%s    /* %s */' % (space, field.c_field_name))
926
927     if field.type.is_list:
928         if value != '':
929             # in any context, list is already a pointer, so the default assignment is ok
930             code_lines.append("%s%s" % (space, value))
931             value = ''
932         length = _c_serialize_helper_list_field(context, self, field, 
933                                                 code_lines, temp_vars, 
934                                                 space, prefix)
935         
936     elif field.type.is_switch:
937         value = ''
938         if context == 'serialize':
939             # the _serialize() function allocates the correct amount memory if given a NULL pointer
940             value = '    xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
941         length = _c_serialize_helper_switch_field(context, self, field, 
942                                                   'xcb_parts[xcb_parts_idx].iov_base', 
943                                                   prefix)
944         
945     else:
946         # in all remaining special cases - call _sizeof()
947         length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
948
949     return (value, length)
950 # _c_serialize_helper_fields_variable_size
951
952 def _c_serialize_helper_fields(context, self, 
953                                code_lines, temp_vars, 
954                                space, prefix, is_bitcase):
955     count = 0
956     need_padding = False
957     prev_field_was_variable = False
958
959     for field in self.fields:
960         if not field.visible:
961             if not ((field.wire and not field.auto) or 'unserialize' == context):
962                 continue
963
964         # switch/bitcase: fixed size fields must be considered explicitly 
965         if field.type.fixed_size():
966             if self.is_bitcase or self.var_followed_by_fixed_fields:
967                 if prev_field_was_variable and need_padding:
968                     # insert padding
969 #                    count += _c_serialize_helper_insert_padding(context, code_lines, space, 
970 #                                                                self.var_followed_by_fixed_fields)
971                     prev_field_was_variable = False
972
973                 # prefix for fixed size fields
974                 fixed_prefix = prefix
975
976                 value, length = _c_serialize_helper_fields_fixed_size(context, self, field, 
977                                                                       code_lines, temp_vars, 
978                                                                       space, fixed_prefix)
979             else:
980                 continue
981
982         # fields with variable size
983         else:
984             if field.type.is_pad:
985                 # Variable length pad is <pad align= />
986                 code_lines.append('%s    xcb_align_to = %d;' % (space, field.type.align))
987                 count += _c_serialize_helper_insert_padding(context, code_lines, space, 
988                                                         self.var_followed_by_fixed_fields)
989                 continue
990             else:
991                 # switch/bitcase: always calculate padding before and after variable sized fields
992                 if need_padding or is_bitcase:
993                     count += _c_serialize_helper_insert_padding(context, code_lines, space,
994                                                             self.var_followed_by_fixed_fields)
995
996                 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
997                                                                          code_lines, temp_vars,
998                                                                          space, prefix)
999                 prev_field_was_variable = True
1000         
1001         # save (un)serialization C code
1002         if '' != value:
1003             code_lines.append('%s%s' % (space, value))    
1004         
1005         if field.type.fixed_size():
1006             if is_bitcase or self.var_followed_by_fixed_fields:
1007                 # keep track of (un)serialized object's size
1008                 code_lines.append('%s    xcb_block_len += %s;' % (space, length))
1009                 if context in ('unserialize', 'unpack', 'sizeof'):
1010                     code_lines.append('%s    xcb_tmp += %s;' % (space, length))
1011         else: 
1012             # variable size objects or bitcase:
1013             #   value & length might have been inserted earlier for special cases
1014             if '' != length:
1015                 # special case: intermixed fixed and variable size fields
1016                 if (not field.type.fixed_size() and 
1017                     self.var_followed_by_fixed_fields and 'unserialize' == context):
1018                     temp_vars.append('    int %s_len;' % field.c_field_name)
1019                     code_lines.append('%s    %s_len = %s;' % (space, field.c_field_name, length))
1020                     code_lines.append('%s    xcb_block_len += %s_len;' % (space, field.c_field_name))
1021                     code_lines.append('%s    xcb_tmp += %s_len;' % (space, field.c_field_name))
1022                 else:
1023                     code_lines.append('%s    xcb_block_len += %s;' % (space, length))
1024                     # increase pointer into the byte stream accordingly
1025                     if context in ('unserialize', 'sizeof', 'unpack'):
1026                         code_lines.append('%s    xcb_tmp += xcb_block_len;' % space)
1027                         
1028         if 'serialize' == context:
1029             if '' != length:
1030                 code_lines.append('%s    xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
1031             code_lines.append('%s    xcb_parts_idx++;' % space)
1032             count += 1
1033
1034         code_lines.append('%s    xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type))
1035
1036         need_padding = True
1037         if self.var_followed_by_fixed_fields:
1038             need_padding = False
1039         
1040     return count
1041 # _c_serialize_helper_fields()    
1042
1043 def _c_serialize_helper(context, complex_type, 
1044                         code_lines, temp_vars, 
1045                         space='', prefix=[]):
1046     # count tracks the number of fields to serialize
1047     count = 0
1048
1049     if hasattr(complex_type, 'type'):
1050         self = complex_type.type
1051         complex_name = complex_type.name
1052     else:
1053         self = complex_type
1054         if self.var_followed_by_fixed_fields and 'unserialize' == context:
1055             complex_name = 'xcb_out'
1056         else:
1057             complex_name = '_aux'
1058     
1059     # special case: switch is serialized by evaluating each bitcase separately
1060     if self.is_switch:
1061         count += _c_serialize_helper_switch(context, self, complex_name, 
1062                                             code_lines, temp_vars, 
1063                                             space, prefix)
1064
1065     # all other data types can be evaluated one field a time
1066     else: 
1067         # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1068         if context in ('unserialize', 'unpack', 'sizeof') and not self.var_followed_by_fixed_fields:
1069             code_lines.append('%s    xcb_block_len += sizeof(%s);' % (space, self.c_type))
1070             code_lines.append('%s    xcb_tmp += xcb_block_len;' % space)
1071             code_lines.append('%s    xcb_buffer_len += xcb_block_len;' % space)
1072             code_lines.append('%s    xcb_block_len = 0;' % space)
1073
1074         count += _c_serialize_helper_fields(context, self, 
1075                                             code_lines, temp_vars, 
1076                                             space, prefix, False)
1077     # "final padding"
1078     count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
1079
1080     return count    
1081 # _c_serialize_helper()
1082
1083 def _c_serialize(context, self):
1084     """
1085     depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof() 
1086     for the ComplexType variable self
1087     """
1088     _h_setlevel(1)
1089     _c_setlevel(1)
1090
1091     _hc('')
1092     # _serialize() returns the buffer size
1093     _hc('int')
1094
1095     if self.is_switch and 'unserialize' == context:
1096         context = 'unpack'
1097
1098     cases = { 'serialize'   : self.c_serialize_name, 
1099               'unserialize' : self.c_unserialize_name, 
1100               'unpack'      : self.c_unpack_name, 
1101               'sizeof'      : self.c_sizeof_name }
1102     func_name = cases[context]
1103             
1104     param_fields, wire_fields, params = get_serialize_params(context, self)
1105     variable_size_fields = 0
1106     # maximum space required for type definition of function arguments
1107     maxtypelen = 0
1108
1109     # determine N(variable_fields) 
1110     for field in param_fields:
1111         # if self.is_switch, treat all fields as if they are variable sized
1112         if not field.type.fixed_size() or self.is_switch:
1113             variable_size_fields += 1
1114     # determine maxtypelen
1115     for p in params:
1116         maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))    
1117
1118     # write to .c/.h
1119     indent = ' '*(len(func_name)+2)
1120     param_str = []
1121     for p in params:
1122         typespec, pointerspec, field_name = p
1123         spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1124         param_str.append("%s%s%s  %s%s  /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1125     # insert function name
1126     param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1127     param_str = list(map(lambda x: "%s," % x, param_str))
1128     for s in param_str[:-1]:
1129         _hc(s)
1130     _h("%s);" % param_str[-1].rstrip(','))
1131     _c("%s)" % param_str[-1].rstrip(','))
1132     _c('{')
1133
1134     code_lines = []
1135     temp_vars = []
1136     prefix = []
1137
1138     if 'serialize' == context:
1139         if not self.is_switch and not self.var_followed_by_fixed_fields:
1140             _c('    %s *xcb_out = *_buffer;', self.c_type)
1141             _c('    unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1142             _c('    unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1143             _c('    unsigned int xcb_align_to = 0;')
1144         else:
1145             _c('    char *xcb_out = *_buffer;')
1146             _c('    unsigned int xcb_buffer_len = 0;')
1147             _c('    unsigned int xcb_align_to = 0;')
1148         prefix = [('_aux', '->', self)]
1149         aux_ptr = 'xcb_out'
1150
1151     elif context in ('unserialize', 'unpack'):
1152         _c('    char *xcb_tmp = (char *)_buffer;')
1153         if not self.is_switch:
1154             if not self.var_followed_by_fixed_fields:
1155                 _c('    const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1156                 prefix = [('_aux', '->', self)]
1157             else:
1158                 _c('    %s xcb_out;', self.c_type)
1159                 prefix = [('xcb_out', '.', self)]
1160         else:
1161             aux_var = '_aux' # default for unpack: single pointer
1162             # note: unserialize not generated for switch
1163             if 'unserialize' == context:
1164                 aux_var = '(*_aux)' # unserialize: double pointer (!)
1165             prefix = [(aux_var, '->', self)]
1166         aux_ptr = '*_aux'
1167         _c('    unsigned int xcb_buffer_len = 0;')
1168         _c('    unsigned int xcb_block_len = 0;')
1169         _c('    unsigned int xcb_pad = 0;')
1170         _c('    unsigned int xcb_align_to = 0;')
1171
1172     elif 'sizeof' == context:
1173         param_names = [p[2] for p in params]
1174         if self.is_switch:
1175             # switch: call _unpack()
1176             _c('    %s _aux;', self.c_type)
1177             _c('    return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1178             _c('}')
1179             return
1180         elif self.var_followed_by_fixed_fields:
1181             # special case: call _unserialize()
1182             _c('    return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1183             _c('}')
1184             return
1185         else:
1186             _c('    char *xcb_tmp = (char *)_buffer;')
1187             prefix = [('_aux', '->', self)]
1188
1189     count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1190     # update variable size fields (only important for context=='serialize'
1191     variable_size_fields = count
1192     if 'serialize' == context:
1193         temp_vars.append('    unsigned int xcb_pad = 0;')
1194         temp_vars.append('    char xcb_pad0[3] = {0, 0, 0};') 
1195         temp_vars.append('    struct iovec xcb_parts[%d];' % count)
1196         temp_vars.append('    unsigned int xcb_parts_idx = 0;')
1197         temp_vars.append('    unsigned int xcb_block_len = 0;')
1198         temp_vars.append('    unsigned int i;')
1199         temp_vars.append('    char *xcb_tmp;')
1200     elif 'sizeof' == context:
1201         # neither switch nor intermixed fixed and variable size fields:
1202         # evaluate parameters directly
1203         if not (self.is_switch or self.var_followed_by_fixed_fields):
1204
1205             # look if we have to declare an '_aux' variable at all
1206             if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
1207                 if not self.var_followed_by_fixed_fields:
1208                     _c('    const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1209                 else:
1210                     _c('    %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1211
1212             _c('    unsigned int xcb_buffer_len = 0;')
1213             _c('    unsigned int xcb_block_len = 0;')
1214             _c('    unsigned int xcb_pad = 0;')        
1215             _c('    unsigned int xcb_align_to = 0;')
1216
1217     _c('')
1218     for t in temp_vars:
1219         _c(t)
1220     _c('')
1221     for l in code_lines:
1222         _c(l)
1223
1224     # variable sized fields have been collected, now
1225     # allocate memory and copy everything into a continuous memory area 
1226     # note: this is not necessary in case of unpack
1227     if context in ('serialize', 'unserialize'):
1228         # unserialize: check for sizeof-only invocation
1229         if 'unserialize' == context:
1230             _c('')
1231             _c('    if (NULL == _aux)')
1232             _c('        return xcb_buffer_len;')
1233
1234         _c('')
1235         _c('    if (NULL == %s) {', aux_ptr)
1236         _c('        /* allocate memory */')
1237         _c('        %s = malloc(xcb_buffer_len);', aux_ptr)
1238         if 'serialize' == context:
1239             _c('        *_buffer = xcb_out;')
1240         _c('    }')
1241         _c('')
1242
1243         # serialize: handle variable size fields in a loop
1244         if 'serialize' == context:
1245             if not self.is_switch and not self.var_followed_by_fixed_fields:
1246                 if len(wire_fields)>0:
1247                     _c('    *xcb_out = *_aux;')
1248             # copy variable size fields into the buffer
1249             if variable_size_fields > 0:
1250                 # xcb_out padding
1251                 if not self.is_switch and not self.var_followed_by_fixed_fields:
1252                     _c('    xcb_tmp = (char*)++xcb_out;')
1253                     _c('    xcb_tmp += xcb_out_pad;')
1254                 else:
1255                     _c('    xcb_tmp = xcb_out;')
1256
1257                 # variable sized fields
1258                 _c('    for(i=0; i<xcb_parts_idx; i++) {')
1259                 _c('        if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1260                 _c('            memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1261                 _c('        if (0 != xcb_parts[i].iov_len)')
1262                 _c('            xcb_tmp += xcb_parts[i].iov_len;')
1263                 _c('    }')
1264             
1265         # unserialize: assign variable size fields individually
1266         if 'unserialize' == context:
1267             _c('    xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1268             param_fields.reverse()
1269             for field in param_fields:
1270                 if not field.type.fixed_size():
1271                     _c('    xcb_tmp -= %s_len;', field.c_field_name)
1272                     _c('    memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1273             _c('    *%s = xcb_out;', aux_ptr)
1274  
1275     _c('')
1276     _c('    return xcb_buffer_len;')
1277     _c('}')
1278 # _c_serialize()
1279
1280 def _c_iterator_get_end(field, accum):
1281     '''
1282     Figures out what C code is needed to find the end of a variable-length structure field.
1283     For nested structures, recurses into its last variable-sized field.
1284     For lists, calls the end function
1285     '''
1286     if field.type.is_container:
1287         accum = field.c_accessor_name + '(' + accum + ')'
1288         return _c_iterator_get_end(field.type.last_varsized_field, accum)
1289     if field.type.is_list:
1290         # XXX we can always use the first way
1291         if field.type.member.is_simple:
1292             return field.c_end_name + '(' + accum + ')'
1293         else:
1294             return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1295
1296 def _c_iterator(self, name):
1297     '''
1298     Declares the iterator structure and next/end functions for a given type.
1299     '''
1300     _h_setlevel(0)
1301     _h('')
1302     _h('/**')
1303     _h(' * @brief %s', self.c_iterator_type)
1304     _h(' **/')
1305     _h('typedef struct %s {', self.c_iterator_type)
1306     _h('    %s *data; /**<  */', self.c_type)
1307     _h('    int%s rem; /**<  */', ' ' * (len(self.c_type) - 2))
1308     _h('    int%s index; /**<  */', ' ' * (len(self.c_type) - 2))
1309     _h('} %s;', self.c_iterator_type)
1310
1311     _h_setlevel(1)
1312     _c_setlevel(1)
1313     _h('')
1314     _h('/**')
1315     _h(' * Get the next element of the iterator')
1316     _h(' * @param i Pointer to a %s', self.c_iterator_type)
1317     _h(' *')
1318     _h(' * Get the next element in the iterator. The member rem is')
1319     _h(' * decreased by one. The member data points to the next')
1320     _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1321     _h(' */')
1322     _c('')
1323     _hc('')
1324     _hc('/*****************************************************************************')
1325     _hc(' **')
1326     _hc(' ** void %s', self.c_next_name)
1327     _hc(' ** ')
1328     _hc(' ** @param %s *i', self.c_iterator_type)
1329     _hc(' ** @returns void')
1330     _hc(' **')
1331     _hc(' *****************************************************************************/')
1332     _hc(' ')
1333     _hc('void')
1334     _h('%s (%s *i  /**< */);', self.c_next_name, self.c_iterator_type)
1335     _c('%s (%s *i  /**< */)', self.c_next_name, self.c_iterator_type)
1336     _c('{')
1337
1338     if not self.fixed_size():
1339         _c('    %s *R = i->data;', self.c_type)
1340
1341         if self.is_union:
1342             # FIXME - how to determine the size of a variable size union??
1343             _c('    /* FIXME - determine the size of the union %s */', self.c_type)            
1344         else:
1345             if self.need_sizeof:
1346                 _c('    xcb_generic_iterator_t child;')
1347                 _c('    child.data = (%s *)(((char *)R) + %s(R));', 
1348                    self.c_type, self.c_sizeof_name)
1349                 _c('    i->index = (char *) child.data - (char *) i->data;')
1350             else:
1351                 _c('    xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1352                 _c('    i->index = child.index;')
1353             _c('    --i->rem;')
1354             _c('    i->data = (%s *) child.data;', self.c_type)
1355
1356     else:
1357         _c('    --i->rem;')
1358         _c('    ++i->data;')
1359         _c('    i->index += sizeof(%s);', self.c_type)
1360
1361     _c('}')
1362
1363     _h('')
1364     _h('/**')
1365     _h(' * Return the iterator pointing to the last element')
1366     _h(' * @param i An %s', self.c_iterator_type)
1367     _h(' * @return  The iterator pointing to the last element')
1368     _h(' *')
1369     _h(' * Set the current element in the iterator to the last element.')
1370     _h(' * The member rem is set to 0. The member data points to the')
1371     _h(' * last element.')
1372     _h(' */')
1373     _c('')
1374     _hc('')
1375     _hc('/*****************************************************************************')
1376     _hc(' **')
1377     _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1378     _hc(' ** ')
1379     _hc(' ** @param %s i', self.c_iterator_type)
1380     _hc(' ** @returns xcb_generic_iterator_t')
1381     _hc(' **')
1382     _hc(' *****************************************************************************/')
1383     _hc(' ')
1384     _hc('xcb_generic_iterator_t')
1385     _h('%s (%s i  /**< */);', self.c_end_name, self.c_iterator_type)
1386     _c('%s (%s i  /**< */)', self.c_end_name, self.c_iterator_type)
1387     _c('{')
1388     _c('    xcb_generic_iterator_t ret;')
1389
1390     if self.fixed_size():
1391         _c('    ret.data = i.data + i.rem;')
1392         _c('    ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1393         _c('    ret.rem = 0;')
1394     else:
1395         _c('    while(i.rem > 0)')
1396         _c('        %s(&i);', self.c_next_name)
1397         _c('    ret.data = i.data;')
1398         _c('    ret.rem = i.rem;')
1399         _c('    ret.index = i.index;')
1400
1401     _c('    return ret;')
1402     _c('}')
1403
1404 def _c_accessor_get_length(expr, field_mapping=None):
1405     '''
1406     Figures out what C code is needed to get a length field.
1407     The field_mapping parameter can be used to change the absolute name of a length field. 
1408     For fields that follow a variable-length field, use the accessor.
1409     Otherwise, just reference the structure field directly.
1410     '''
1411
1412     lenfield_name = expr.lenfield_name
1413     if lenfield_name is not None:
1414         if field_mapping is not None:
1415             lenfield_name = field_mapping[lenfield_name][0]
1416  
1417     if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1418         # special case: variable and fixed size fields are intermixed
1419         # if the lenfield is among the fixed size fields, there is no need
1420         # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1421         return field_mapping(expr.lenfield_name)
1422     elif expr.lenfield_name is not None:
1423         return lenfield_name
1424     else:
1425         return str(expr.nmemb)
1426
1427 def _c_accessor_get_expr(expr, field_mapping):
1428     '''
1429     Figures out what C code is needed to get the length of a list field.
1430     The field_mapping parameter can be used to change the absolute name of a length field. 
1431     Recurses for math operations.
1432     Returns bitcount for value-mask fields.
1433     Otherwise, uses the value of the length field.
1434     '''
1435     lenexp = _c_accessor_get_length(expr, field_mapping)
1436
1437     if expr.op == '~':
1438         return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1439     elif expr.op == 'popcount':
1440         return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1441     elif expr.op == 'enumref':
1442         enum_name = expr.lenfield_type.name
1443         constant_name = expr.lenfield_name
1444         c_name = _n(enum_name + (constant_name,)).upper()
1445         return c_name
1446     elif expr.op == 'sumof':
1447         # locate the referenced list object
1448         list_obj = expr.lenfield_type
1449         field = None
1450         for f in expr.lenfield_parent.fields:
1451             if f.field_name == expr.lenfield_name:
1452                 field = f
1453                 break
1454
1455         if field is None:
1456             raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1457         list_name = field_mapping[field.c_field_name][0]
1458         c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1459         # note: xcb_sumof() has only been defined for integers
1460         c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1461         return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1462     elif expr.op != None:
1463         return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) + 
1464                 ' ' + expr.op + ' ' + 
1465                 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1466     elif expr.bitfield:
1467         return 'xcb_popcount(' + lenexp + ')'
1468     else:
1469         return lenexp
1470
1471 def type_pad_type(type):
1472     if type == 'void':
1473         return 'char'
1474     return type
1475
1476 def _c_accessors_field(self, field):
1477     '''
1478     Declares the accessor functions for a non-list field that follows a variable-length field.
1479     '''
1480     c_type = self.c_type
1481
1482     # special case: switch
1483     switch_obj = self if self.is_switch else None
1484     if self.is_bitcase:
1485         switch_obj = self.parents[-1]
1486     if switch_obj is not None:
1487         c_type = switch_obj.c_type
1488
1489     if field.type.is_simple:
1490         _hc('')
1491         _hc('')
1492         _hc('/*****************************************************************************')
1493         _hc(' ** ')
1494         _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1495         _hc(' ** ')
1496         _hc(' ** @param const %s *R', c_type)
1497         _hc(' ** @returns %s', field.c_field_type)
1498         _hc(' **')
1499         _hc(' *****************************************************************************/')
1500         _hc(' ')
1501         _hc('%s', field.c_field_type)
1502         _h('%s (const %s *R  /**< */);', field.c_accessor_name, c_type)
1503         _c('%s (const %s *R  /**< */)', field.c_accessor_name, c_type)
1504         _c('{')
1505         if field.prev_varsized_field is None:
1506             _c('    return (%s *) (R + 1);', field.c_field_type)
1507         else:
1508             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1509             _c('    return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', 
1510                field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1511         _c('}')
1512     else:
1513         _hc('')
1514         _hc('')
1515         _hc('/*****************************************************************************')
1516         _hc(' **')
1517         _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1518         _hc(' ** ')
1519         _hc(' ** @param const %s *R', c_type)
1520         _hc(' ** @returns %s *', field.c_field_type)
1521         _hc(' **')
1522         _hc(' *****************************************************************************/')
1523         _hc(' ')
1524         if field.type.is_switch and switch_obj is None:
1525             return_type = 'void *'
1526         else:
1527             return_type = '%s *' % field.c_field_type
1528
1529         _hc(return_type)
1530         _h('%s (const %s *R  /**< */);', field.c_accessor_name, c_type)
1531         _c('%s (const %s *R  /**< */)', field.c_accessor_name, c_type)
1532         _c('{')
1533         if field.prev_varsized_field is None:
1534             _c('    return (%s) (R + 1);', return_type)
1535             # note: the special case 'variable fields followed by fixed size fields'
1536             #       is not of any consequence here, since the ordering gets 
1537             #       'corrected' in the reply function
1538         else:
1539             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1540             _c('    return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', 
1541                return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1542         _c('}')
1543
1544     
1545 def _c_accessors_list(self, field):
1546     '''
1547     Declares the accessor functions for a list field.
1548     Declares a direct-accessor function only if the list members are fixed size.
1549     Declares length and get-iterator functions always.
1550     '''
1551     list = field.type
1552     c_type = self.c_type
1553
1554     # special case: switch
1555     # in case of switch, 2 params have to be supplied to certain accessor functions:
1556     #   1. the anchestor object (request or reply)
1557     #   2. the (anchestor) switch object
1558     # the reason is that switch is either a child of a request/reply or nested in another switch, 
1559     # so whenever we need to access a length field, we might need to refer to some anchestor type
1560     switch_obj = self if self.is_switch else None
1561     if self.is_bitcase:
1562         switch_obj = self.parents[-1]
1563     if switch_obj is not None:
1564         c_type = switch_obj.c_type
1565
1566     params = []
1567     fields = {}
1568     parents = self.parents if hasattr(self, 'parents') else [self]
1569     # 'R': parents[0] is always the 'toplevel' container type 
1570     params.append(('const %s *R' % parents[0].c_type, parents[0]))
1571     fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1572     # auxiliary object for 'R' parameters
1573     R_obj = parents[0]
1574
1575     if switch_obj is not None:
1576         # now look where the fields are defined that are needed to evaluate 
1577         # the switch expr, and store the parent objects in accessor_params and
1578         # the fields in switch_fields
1579
1580         # 'S': name for the 'toplevel' switch
1581         toplevel_switch = parents[1]
1582         params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1583         fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1584
1585         # initialize prefix for everything "below" S
1586         prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1587         prefix = [(prefix_str, '->', toplevel_switch)]
1588
1589         # look for fields in the remaining containers
1590         for p in parents[2:] + [self]:
1591             # the separator between parent and child is always '.' here, 
1592             # because of nested switch statements
1593             if not p.is_bitcase or (p.is_bitcase and p.has_name):
1594                 prefix.append((p.name[-1], '.', p))
1595             fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1596
1597         # auxiliary object for 'S' parameter
1598         S_obj = parents[1]
1599
1600     _h_setlevel(1)
1601     _c_setlevel(1)
1602     if list.member.fixed_size():
1603         idx = 1 if switch_obj is not None else 0
1604         _hc('')
1605         _hc('')
1606         _hc('/*****************************************************************************')
1607         _hc(' **')
1608         _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1609         _hc(' ** ')
1610         _hc(' ** @param %s', params[idx][0])
1611         _hc(' ** @returns %s *', field.c_field_type)
1612         _hc(' **')
1613         _hc(' *****************************************************************************/')
1614         _hc(' ')
1615         _hc('%s *', field.c_field_type)
1616
1617         _h('%s (%s  /**< */);', field.c_accessor_name, params[idx][0])
1618         _c('%s (%s  /**< */)', field.c_accessor_name, params[idx][0])
1619
1620         _c('{')
1621         if switch_obj is not None:
1622             _c('    return %s;', fields[field.c_field_name][0])
1623         elif field.prev_varsized_field is None:
1624             _c('    return (%s *) (R + 1);', field.c_field_type)
1625         else:
1626             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1627             _c('    return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', 
1628                field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1629         _c('}')
1630
1631     _hc('')
1632     _hc('')
1633     _hc('/*****************************************************************************')
1634     _hc(' **')
1635     _hc(' ** int %s', field.c_length_name)
1636     _hc(' ** ')
1637     _hc(' ** @param const %s *R', c_type)
1638     _hc(' ** @returns int')
1639     _hc(' **')
1640     _hc(' *****************************************************************************/')
1641     _hc(' ')
1642     _hc('int')
1643     if switch_obj is not None:
1644         _hc('%s (const %s *R  /**< */,', field.c_length_name, R_obj.c_type)
1645         spacing = ' '*(len(field.c_length_name)+2)
1646         _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1647         _c('%sconst %s *S  /**< */)', spacing, S_obj.c_type)
1648         length = _c_accessor_get_expr(field.type.expr, fields)
1649     else:
1650         _h('%s (const %s *R  /**< */);', field.c_length_name, c_type)
1651         _c('%s (const %s *R  /**< */)', field.c_length_name, c_type)
1652         length = _c_accessor_get_expr(field.type.expr, fields)
1653     _c('{')
1654     _c('    return %s;', length)
1655     _c('}')
1656
1657     if field.type.member.is_simple:
1658         _hc('')
1659         _hc('')
1660         _hc('/*****************************************************************************')
1661         _hc(' **')
1662         _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1663         _hc(' ** ')
1664         _hc(' ** @param const %s *R', c_type)
1665         _hc(' ** @returns xcb_generic_iterator_t')
1666         _hc(' **')
1667         _hc(' *****************************************************************************/')
1668         _hc(' ')
1669         _hc('xcb_generic_iterator_t')
1670         if switch_obj is not None:
1671             _hc('%s (const %s *R  /**< */,', field.c_end_name, R_obj.c_type)
1672             spacing = ' '*(len(field.c_end_name)+2)
1673             _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1674             _c('%sconst %s *S  /**< */)', spacing, S_obj.c_type)
1675         else:
1676             _h('%s (const %s *R  /**< */);', field.c_end_name, c_type)
1677             _c('%s (const %s *R  /**< */)', field.c_end_name, c_type)
1678         _c('{')
1679         _c('    xcb_generic_iterator_t i;')
1680         
1681         param = 'R' if switch_obj is None else 'S'
1682         if switch_obj is not None:
1683             _c('    i.data = %s + %s;', fields[field.c_field_name][0], 
1684                _c_accessor_get_expr(field.type.expr, fields))
1685         elif field.prev_varsized_field == None:
1686             _c('    i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, 
1687                _c_accessor_get_expr(field.type.expr, fields))
1688         else:
1689             _c('    xcb_generic_iterator_t child = %s;', 
1690                _c_iterator_get_end(field.prev_varsized_field, 'R'))
1691             _c('    i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, 
1692                _c_accessor_get_expr(field.type.expr, fields))
1693
1694         _c('    i.rem = 0;')
1695         _c('    i.index = (char *) i.data - (char *) %s;', param)
1696         _c('    return i;')
1697         _c('}')
1698
1699     else:
1700         _hc('')
1701         _hc('')
1702         _hc('/*****************************************************************************')
1703         _hc(' **')
1704         _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1705         _hc(' ** ')
1706         _hc(' ** @param const %s *R', c_type)
1707         _hc(' ** @returns %s', field.c_iterator_type)
1708         _hc(' **')
1709         _hc(' *****************************************************************************/')
1710         _hc(' ')
1711
1712         _hc('%s', field.c_iterator_type)
1713         if switch_obj is not None:
1714             _hc('%s (const %s *R  /**< */,', field.c_iterator_name, R_obj.c_type)
1715             spacing = ' '*(len(field.c_iterator_name)+2)
1716             _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1717             _c('%sconst %s *S  /**< */)', spacing, S_obj.c_type)
1718         else:
1719             _h('%s (const %s *R  /**< */);', field.c_iterator_name, c_type)
1720             _c('%s (const %s *R  /**< */)', field.c_iterator_name, c_type)
1721         _c('{')
1722         _c('    %s i;', field.c_iterator_type)
1723
1724         if switch_obj is not None:
1725             _c('    i.data = %s;', fields[field.c_field_name][0])
1726             _c('    i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1727         elif field.prev_varsized_field == None:
1728             _c('    i.data = (%s *) (R + 1);', field.c_field_type)
1729         else:
1730             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1731             _c('    i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', 
1732                field.c_field_type, type_pad_type(field.c_field_type))
1733         if switch_obj is None:
1734             _c('    i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1735         _c('    i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1736         _c('    return i;')
1737         _c('}')
1738
1739 def _c_accessors(self, name, base):
1740     '''
1741     Declares the accessor functions for the fields of a structure.
1742     '''
1743     # no accessors for switch itself - 
1744     # switch always needs to be unpacked explicitly
1745 #    if self.is_switch:
1746 #        pass
1747 #    else:
1748     if True:
1749         for field in self.fields:
1750             if not field.type.is_pad:
1751                 if field.type.is_list and not field.type.fixed_size():
1752                     _c_accessors_list(self, field)
1753                 elif field.prev_varsized_field is not None or not field.type.fixed_size():
1754                     _c_accessors_field(self, field)
1755
1756 def c_simple(self, name):
1757     '''
1758     Exported function that handles cardinal type declarations.
1759     These are types which are typedef'd to one of the CARDx's, char, float, etc.
1760     '''
1761     _c_type_setup(self, name, ())
1762
1763     if (self.name != name):
1764         # Typedef
1765         _h_setlevel(0)
1766         my_name = _t(name)
1767         _h('')
1768         _h('typedef %s %s;', _t(self.name), my_name)
1769
1770         # Iterator
1771         _c_iterator(self, name)
1772
1773 def _c_complex(self, force_packed = False):
1774     '''
1775     Helper function for handling all structure types.
1776     Called for all structs, requests, replies, events, errors.
1777     '''
1778     _h_setlevel(0)
1779     _h('')
1780     _h('/**')
1781     _h(' * @brief %s', self.c_type)
1782     _h(' **/')
1783     _h('typedef %s %s {', self.c_container, self.c_type)
1784
1785     struct_fields = []
1786     maxtypelen = 0
1787
1788     varfield = None
1789     for field in self.fields:
1790         if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1791             varfield = field.c_field_name
1792             continue
1793         if field.wire:
1794             struct_fields.append(field)
1795     
1796     for field in struct_fields:
1797         length = len(field.c_field_type)
1798         # account for '*' pointer_spec
1799         if not field.type.fixed_size() and not self.is_union:
1800             length += 1
1801         maxtypelen = max(maxtypelen, length)
1802
1803     def _c_complex_field(self, field, space=''):
1804         if (field.type.fixed_size() or self.is_union or
1805             # in case of switch with switch children, don't make the field a pointer
1806             # necessary for unserialize to work
1807             (self.is_switch and field.type.is_switch)):
1808             spacing = ' ' * (maxtypelen - len(field.c_field_type))
1809             _h('%s    %s%s %s%s; /**<  */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1810         else:
1811             spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1812             _h('%s    %s%s *%s%s; /**<  */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1813
1814     if not self.is_switch:
1815         for field in struct_fields:
1816             _c_complex_field(self, field)
1817     else:
1818         for b in self.bitcases:
1819             space = ''
1820             if b.type.has_name:
1821                 _h('    struct _%s {', b.c_field_name)
1822                 space = '    '
1823             for field in b.type.fields:
1824                 _c_complex_field(self, field, space)
1825             if b.type.has_name:
1826                 _h('    } %s;', b.c_field_name)
1827
1828     _h('} %s%s;', 'XCB_PACKED ' if force_packed else '', self.c_type)
1829
1830 def c_struct(self, name):
1831     '''
1832     Exported function that handles structure declarations.
1833     '''
1834     _c_type_setup(self, name, ())
1835     _c_complex(self)
1836     _c_accessors(self, name, name)
1837     _c_iterator(self, name)
1838
1839 def c_union(self, name):
1840     '''
1841     Exported function that handles union declarations.
1842     '''
1843     _c_type_setup(self, name, ())
1844     _c_complex(self)
1845     _c_iterator(self, name)
1846
1847 def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_fds=False):
1848     '''
1849     Declares a request function.
1850     '''
1851
1852     # Four stunningly confusing possibilities here:
1853     #
1854     #   Void            Non-void
1855     # ------------------------------
1856     # "req"            "req"
1857     # 0 flag           CHECKED flag   Normal Mode
1858     # void_cookie      req_cookie
1859     # ------------------------------
1860     # "req_checked"    "req_unchecked"
1861     # CHECKED flag     0 flag         Abnormal Mode
1862     # void_cookie      req_cookie
1863     # ------------------------------
1864
1865
1866     # Whether we are _checked or _unchecked
1867     checked = void and not regular
1868     unchecked = not void and not regular
1869
1870     # What kind of cookie we return
1871     func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1872
1873     # What flag is passed to xcb_request
1874     func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1875
1876     if reply_fds:
1877         if func_flags == '0':
1878             func_flags = 'XCB_REQUEST_REPLY_FDS'
1879         else:
1880             func_flags = func_flags + '|XCB_REQUEST_REPLY_FDS'
1881
1882     # Global extension id variable or NULL for xproto
1883     func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1884
1885     # What our function name is
1886     func_name = self.c_request_name if not aux else self.c_aux_name
1887     if checked:
1888         func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1889     if unchecked:
1890         func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1891
1892     param_fields = []
1893     wire_fields = []
1894     maxtypelen = len('xcb_connection_t')
1895     serial_fields = []
1896     # special case: list with variable size elements
1897     list_with_var_size_elems = False
1898
1899     for field in self.fields:
1900         if field.visible:
1901             # The field should appear as a call parameter
1902             param_fields.append(field)
1903         if field.wire and not field.auto:
1904             # We need to set the field up in the structure
1905             wire_fields.append(field)
1906         if field.type.need_serialize or field.type.need_sizeof:
1907             serial_fields.append(field)
1908         
1909     for field in param_fields:
1910         c_field_const_type = field.c_field_const_type 
1911         if field.type.need_serialize and not aux:
1912             c_field_const_type = "const void"
1913         if len(c_field_const_type) > maxtypelen:
1914             maxtypelen = len(c_field_const_type)
1915         if field.type.is_list and not field.type.member.fixed_size():
1916             list_with_var_size_elems = True
1917
1918     _h_setlevel(1)
1919     _c_setlevel(1)
1920     _h('')
1921     _h('/**')
1922     if hasattr(self, "doc") and self.doc:
1923         if self.doc.brief:
1924             _h(' * @brief ' + self.doc.brief)
1925         else:
1926             _h(' * No brief doc yet')
1927
1928     _h(' *')
1929     _h(' * @param c The connection')
1930     param_names = [f.c_field_name for f in param_fields]
1931     if hasattr(self, "doc") and self.doc:
1932         for field in param_fields:
1933             # XXX: hard-coded until we fix xproto.xml
1934             base_func_name = self.c_request_name if not aux else self.c_aux_name
1935             if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
1936                 field.enum = 'GC'
1937             elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
1938                 field.enum = 'CW'
1939             elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
1940                 field.enum = 'CW'
1941             if field.enum:
1942                 # XXX: why the 'xcb' prefix?
1943                 key = ('xcb', field.enum)
1944
1945                 tname = _t(key)
1946                 if namecount[tname] > 1:
1947                     tname = _t(key + ('enum',))
1948                 _h(' * @param %s A bitmask of #%s values.' % (field.c_field_name, tname))
1949
1950             if self.doc and field.field_name in self.doc.fields:
1951                 desc = self.doc.fields[field.field_name]
1952                 for name in param_names:
1953                     desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1954                 desc = desc.split("\n")
1955                 desc = [line if line != '' else '\\n' for line in desc]
1956                 _h(' * @param %s %s' % (field.c_field_name, "\n * ".join(desc)))
1957             # If there is no documentation yet, we simply don't generate an
1958             # @param tag. Doxygen will then warn about missing documentation.
1959
1960     _h(' * @return A cookie')
1961     _h(' *')
1962
1963     if hasattr(self, "doc") and self.doc:
1964         if self.doc.description:
1965             desc = self.doc.description
1966             for name in param_names:
1967                 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1968             desc = desc.split("\n")
1969             _h(' * ' + "\n * ".join(desc))
1970         else:
1971             _h(' * No description yet')
1972     else:
1973         _h(' * Delivers a request to the X server.')
1974     _h(' * ')
1975     if checked:
1976         _h(' * This form can be used only if the request will not cause')
1977         _h(' * a reply to be generated. Any returned error will be')
1978         _h(' * saved for handling by xcb_request_check().')
1979     if unchecked:
1980         _h(' * This form can be used only if the request will cause')
1981         _h(' * a reply to be generated. Any returned error will be')
1982         _h(' * placed in the event queue.')
1983     _h(' */')
1984     _c('')
1985     _hc('')
1986     _hc('/*****************************************************************************')
1987     _hc(' **')
1988     _hc(' ** %s %s', cookie_type, func_name)
1989     _hc(' ** ')
1990
1991     spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1992     _hc(' ** @param xcb_connection_t%s *c', spacing)
1993
1994     for field in param_fields:
1995         c_field_const_type = field.c_field_const_type 
1996         if field.type.need_serialize and not aux:
1997             c_field_const_type = "const void"
1998         spacing = ' ' * (maxtypelen - len(c_field_const_type))
1999         _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
2000
2001     _hc(' ** @returns %s', cookie_type)
2002     _hc(' **')
2003     _hc(' *****************************************************************************/')
2004     _hc(' ')
2005     _hc('%s', cookie_type)
2006
2007     spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
2008     comma = ',' if len(param_fields) else ');'
2009     _h('%s (xcb_connection_t%s *c  /**< */%s', func_name, spacing, comma)
2010     comma = ',' if len(param_fields) else ')'
2011     _c('%s (xcb_connection_t%s *c  /**< */%s', func_name, spacing, comma)
2012
2013     func_spacing = ' ' * (len(func_name) + 2)
2014     count = len(param_fields)
2015     for field in param_fields:
2016         count = count - 1
2017         c_field_const_type = field.c_field_const_type 
2018         c_pointer = field.c_pointer
2019         if field.type.need_serialize and not aux:
2020             c_field_const_type = "const void"
2021             c_pointer = '*'
2022         spacing = ' ' * (maxtypelen - len(c_field_const_type))
2023         comma = ',' if count else ');'
2024         _h('%s%s%s %s%s  /**< */%s', func_spacing, c_field_const_type, 
2025            spacing, c_pointer, field.c_field_name, comma)
2026         comma = ',' if count else ')'
2027         _c('%s%s%s %s%s  /**< */%s', func_spacing, c_field_const_type, 
2028            spacing, c_pointer, field.c_field_name, comma)
2029
2030     count = 2
2031     if not self.var_followed_by_fixed_fields:
2032         for field in param_fields:
2033             if not field.type.fixed_size():
2034                 count = count + 2
2035                 if field.type.need_serialize:
2036                     # _serialize() keeps track of padding automatically
2037                     count -= 1
2038     dimension = count + 2
2039
2040     _c('{')
2041     _c('    static const xcb_protocol_request_t xcb_req = {')
2042     _c('        /* count */ %d,', count)
2043     _c('        /* ext */ %s,', func_ext_global)
2044     _c('        /* opcode */ %s,', self.c_request_name.upper())
2045     _c('        /* isvoid */ %d', 1 if void else 0)
2046     _c('    };')
2047     _c('    ')
2048
2049     _c('    struct iovec xcb_parts[%d];', dimension)
2050     _c('    %s xcb_ret;', func_cookie)
2051     _c('    %s xcb_out;', self.c_type)
2052     if self.var_followed_by_fixed_fields:
2053         _c('    /* in the protocol description, variable size fields are followed by fixed size fields */')
2054         _c('    void *xcb_aux = 0;')
2055         
2056
2057     for idx, f in enumerate(serial_fields):
2058         if aux:
2059             _c('    void *xcb_aux%d = 0;' % (idx))
2060     if list_with_var_size_elems:
2061         _c('    unsigned int i;')
2062         _c('    unsigned int xcb_tmp_len;')
2063         _c('    char *xcb_tmp;')
2064     _c('    ')
2065     # simple request call tracing
2066 #    _c('    printf("in function %s\\n");' % func_name)     
2067  
2068     # fixed size fields
2069     for field in wire_fields:
2070         if field.type.fixed_size():
2071             if field.type.is_expr:
2072                 _c('    xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
2073             elif field.type.is_pad:
2074                 if field.type.nmemb == 1:
2075                     _c('    xcb_out.%s = 0;', field.c_field_name)
2076                 else:
2077                     _c('    memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
2078             else:
2079                 if field.type.nmemb == 1:
2080                     _c('    xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
2081                 else:
2082                     _c('    memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
2083
2084     def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
2085         serialize_args = get_serialize_params(context, type_obj, 
2086                                               c_field_name, 
2087                                               aux_var)[2]
2088         return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
2089
2090     # calls in order to free dyn. all. memory
2091     free_calls = []
2092
2093     _c('    ')
2094     if not self.var_followed_by_fixed_fields:
2095         _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
2096         _c('    xcb_parts[2].iov_len = sizeof(xcb_out);')
2097         _c('    xcb_parts[3].iov_base = 0;')
2098         _c('    xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2099
2100         count = 4
2101
2102         for field in param_fields:
2103             if not field.type.fixed_size():
2104                 _c('    /* %s %s */', field.type.c_type, field.c_field_name)
2105                 # default: simple cast to char *
2106                 if not field.type.need_serialize and not field.type.need_sizeof:
2107                     _c('    xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2108                     if field.type.is_list:
2109                         if field.type.member.fixed_size():
2110                             _c('    xcb_parts[%d].iov_len = %s * sizeof(%s);', count, 
2111                                _c_accessor_get_expr(field.type.expr, None), 
2112                                field.type.member.c_wiretype)
2113                         else:
2114                             list_length = _c_accessor_get_expr(field.type.expr, None)
2115     
2116                             length = ''
2117                             _c("    xcb_parts[%d].iov_len = 0;" % count)
2118                             _c("    xcb_tmp = (char *)%s;", field.c_field_name)
2119                             _c("    for(i=0; i<%s; i++) {" % list_length)
2120                             _c("        xcb_tmp_len = %s(xcb_tmp);" % 
2121                                               (field.type.c_sizeof_name))
2122                             _c("        xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2123                             _c("        xcb_tmp += xcb_tmp_len;")
2124                             _c("    }")                        
2125                     else:
2126                         # not supposed to happen
2127                         raise Exception("unhandled variable size field %s" % field.c_field_name)
2128                 else:
2129                     if not aux:
2130                         _c('    xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2131                     idx = serial_fields.index(field)
2132                     aux_var = '&xcb_aux%d' % idx
2133                     context = 'serialize' if aux else 'sizeof'
2134                     _c('    xcb_parts[%d].iov_len = ', count)
2135                     if aux:
2136                         serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2137                         _c('      %s (%s);', field.type.c_serialize_name, serialize_args)
2138                         _c('    xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2139                         free_calls.append('    free(xcb_aux%d);' % idx)
2140                     else:
2141                         serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2142                         func_name = field.type.c_sizeof_name
2143                         _c('      %s (%s);', func_name, serialize_args)
2144
2145                 count += 1
2146                 if not (field.type.need_serialize or field.type.need_sizeof):
2147                     # the _serialize() function keeps track of padding automatically
2148                     _c('    xcb_parts[%d].iov_base = 0;', count)
2149                     _c('    xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2150                     count += 1
2151
2152     # elif self.var_followed_by_fixed_fields:
2153     else:
2154         _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
2155         # request header: opcodes + length
2156         _c('    xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);') 
2157         count += 1
2158         # call _serialize()
2159         buffer_var = '&xcb_aux'
2160         serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2161         _c('    xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2162         _c('    xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2163         free_calls.append('    free(xcb_aux);')
2164         # no padding necessary - _serialize() keeps track of padding automatically
2165
2166     _c('    ')
2167     for field in param_fields:
2168         if field.isfd:
2169             _c('    xcb_send_fd(c, %s);', field.c_field_name)
2170     
2171     _c('    xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2172     
2173     # free dyn. all. data, if any
2174     for f in free_calls:
2175         _c(f)
2176     _c('    return xcb_ret;')
2177     _c('}')
2178
2179 def _c_reply(self, name):
2180     '''
2181     Declares the function that returns the reply structure.
2182     '''
2183     spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2184     spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2185     spacing3 = ' ' * (len(self.c_reply_name) + 2)
2186     
2187     # check if _unserialize() has to be called for any field
2188     def look_for_special_cases(complex_obj):
2189         unserialize_fields = []
2190         # no unserialize call in case of switch
2191         if not complex_obj.is_switch:
2192             for field in complex_obj.fields:
2193                 # three cases: 1. field with special case
2194                 #              2. container that contains special case field
2195                 #              3. list with special case elements
2196                 if field.type.var_followed_by_fixed_fields:
2197                     unserialize_fields.append(field)
2198                 elif field.type.is_container:
2199                     unserialize_fields += look_for_special_cases(field.type)
2200                 elif field.type.is_list:
2201                     if field.type.member.var_followed_by_fixed_fields:
2202                         unserialize_fields.append(field)
2203                     if field.type.member.is_container:
2204                         unserialize_fields += look_for_special_cases(field.type.member)
2205         return unserialize_fields
2206     
2207     unserialize_fields = look_for_special_cases(self.reply)
2208     
2209     _h('')
2210     _h('/**')
2211     _h(' * Return the reply')
2212     _h(' * @param c      The connection')
2213     _h(' * @param cookie The cookie')
2214     _h(' * @param e      The xcb_generic_error_t supplied')
2215     _h(' *')
2216     _h(' * Returns the reply of the request asked by')
2217     _h(' * ')
2218     _h(' * The parameter @p e supplied to this function must be NULL if')
2219     _h(' * %s(). is used.', self.c_unchecked_name)
2220     _h(' * Otherwise, it stores the error if any.')
2221     _h(' *')
2222     _h(' * The returned value must be freed by the caller using free().')
2223     _h(' */')
2224     _c('')
2225     _hc('')
2226     _hc('/*****************************************************************************')
2227     _hc(' **')
2228     _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
2229     _hc(' ** ')
2230     _hc(' ** @param xcb_connection_t%s  *c', spacing1)
2231     _hc(' ** @param %s   cookie', self.c_cookie_type)
2232     _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
2233     _hc(' ** @returns %s *', self.c_reply_type)
2234     _hc(' **')
2235     _hc(' *****************************************************************************/')
2236     _hc(' ')
2237     _hc('%s *', self.c_reply_type)
2238     _hc('%s (xcb_connection_t%s  *c  /**< */,', self.c_reply_name, spacing1)
2239     _hc('%s%s   cookie  /**< */,', spacing3, self.c_cookie_type)
2240     _h('%sxcb_generic_error_t%s **e  /**< */);', spacing3, spacing2)
2241     _c('%sxcb_generic_error_t%s **e  /**< */)', spacing3, spacing2)
2242     _c('{')
2243     
2244     if len(unserialize_fields)>0:
2245         # certain variable size fields need to be unserialized explicitly
2246         _c('    %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', 
2247            self.c_reply_type, self.c_reply_type)
2248         _c('    int i;')
2249         for field in unserialize_fields:
2250             if field.type.is_list:
2251                 _c('    %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2252                 _c('    int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2253                 _c('    %s *%s_data;', field.c_field_type, field.c_field_name)
2254             else:
2255                 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2256         # call _unserialize(), using the reply as source and target buffer
2257         _c('    /* special cases: transform parts of the reply to match XCB data structures */')
2258         for field in unserialize_fields:
2259             if field.type.is_list:
2260                 _c('    for(i=0; i<%s_len; i++) {', field.c_field_name)
2261                 _c('        %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2262                 _c('        %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name, 
2263                    field.c_field_name, field.c_field_name)
2264                 _c('        %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2265                 _c('    }')
2266         # return the transformed reply
2267         _c('    return reply;')
2268     
2269     else:
2270         _c('    return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2271
2272     _c('}')
2273
2274 def _c_reply_has_fds(self):
2275     for field in self.fields:
2276         if field.isfd:
2277             return True
2278     return False
2279
2280 def _c_reply_fds(self, name):
2281     '''
2282     Declares the function that returns fds related to the reply.
2283     '''
2284     spacing1 = ' ' * (len(self.c_reply_type) - len('xcb_connection_t'))
2285     spacing3 = ' ' * (len(self.c_reply_fds_name) + 2)
2286     _h('')
2287     _h('/**')
2288     _h(' * Return the reply fds')
2289     _h(' * @param c      The connection')
2290     _h(' * @param reply  The reply')
2291     _h(' *')
2292     _h(' * Returns the array of reply fds of the request asked by')
2293     _h(' * ')
2294     _h(' * The returned value must be freed by the caller using free().')
2295     _h(' */')
2296     _c('')
2297     _hc('')
2298     _hc('/*****************************************************************************')
2299     _hc(' **')
2300     _hc(' ** int * %s', self.c_reply_fds_name)
2301     _hc(' ** ')
2302     _hc(' ** @param xcb_connection_t%s  *c', spacing1)
2303     _hc(' ** @param %s  *reply', self.c_reply_type)
2304     _hc(' ** @returns int *')
2305     _hc(' **')
2306     _hc(' *****************************************************************************/')
2307     _hc(' ')
2308     _hc('int *')
2309     _hc('%s (xcb_connection_t%s  *c  /**< */,', self.c_reply_fds_name, spacing1)
2310     _h('%s%s  *reply  /**< */);', spacing3, self.c_reply_type)
2311     _c('%s%s  *reply  /**< */)', spacing3, self.c_reply_type)
2312     _c('{')
2313     
2314     _c('    return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
2315
2316     _c('}')
2317     
2318
2319 def _c_opcode(name, opcode):
2320     '''
2321     Declares the opcode define for requests, events, and errors.
2322     '''
2323     _h_setlevel(0)
2324     _h('')
2325     _h('/** Opcode for %s. */', _n(name))
2326     _h('#define %s %s', _n(name).upper(), opcode)
2327     
2328 def _c_cookie(self, name):
2329     '''
2330     Declares the cookie type for a non-void request.
2331     '''
2332     _h_setlevel(0)
2333     _h('')
2334     _h('/**')
2335     _h(' * @brief %s', self.c_cookie_type)
2336     _h(' **/')
2337     _h('typedef struct %s {', self.c_cookie_type)
2338     _h('    unsigned int sequence; /**<  */')
2339     _h('} %s;', self.c_cookie_type)
2340
2341 def _man_request(self, name, cookie_type, void, aux):
2342     param_fields = [f for f in self.fields if f.visible]
2343
2344     func_name = self.c_request_name if not aux else self.c_aux_name
2345
2346     def create_link(linkname):
2347         name = 'man/%s.%s' % (linkname, section)
2348         if manpaths:
2349             sys.stdout.write(name)
2350         f = open(name, 'w')
2351         f.write('.so man%s/%s.%s' % (section, func_name, section))
2352         f.close()
2353
2354     if manpaths:
2355         sys.stdout.write('man/%s.%s ' % (func_name, section))
2356     # Our CWD is src/, so this will end up in src/man/
2357     f = open('man/%s.%s' % (func_name, section), 'w')
2358     f.write('.TH %s %s  "%s" "%s" "XCB Requests"\n' % (func_name, section, center_footer, left_footer))
2359     # Left-adjust instead of adjusting to both sides
2360     f.write('.ad l\n')
2361     f.write('.SH NAME\n')
2362     brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2363     f.write('%s \\- %s\n' % (func_name, brief))
2364     f.write('.SH SYNOPSIS\n')
2365     # Don't split words (hyphenate)
2366     f.write('.hy 0\n')
2367     f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2368
2369     # function prototypes
2370     prototype = ''
2371     count = len(param_fields)
2372     for field in param_fields:
2373         count = count - 1
2374         c_field_const_type = field.c_field_const_type
2375         c_pointer = field.c_pointer
2376         if c_pointer == ' ':
2377             c_pointer = ''
2378         if field.type.need_serialize and not aux:
2379             c_field_const_type = "const void"
2380             c_pointer = '*'
2381         comma = ', ' if count else ');'
2382         prototype += '%s\\ %s\\fI%s\\fP%s' % (c_field_const_type, c_pointer, field.c_field_name, comma)
2383
2384     f.write('.SS Request function\n')
2385     f.write('.HP\n')
2386     base_func_name = self.c_request_name if not aux else self.c_aux_name
2387     f.write('%s \\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\n' % (cookie_type, base_func_name, prototype))
2388     create_link('%s_%s' % (base_func_name, ('checked' if void else 'unchecked')))
2389     if not void:
2390         f.write('.PP\n')
2391         f.write('.SS Reply datastructure\n')
2392         f.write('.nf\n')
2393         f.write('.sp\n')
2394         f.write('typedef %s %s {\n' % (self.reply.c_container, self.reply.c_type))
2395         struct_fields = []
2396         maxtypelen = 0
2397
2398         for field in self.reply.fields:
2399             if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2400                 continue
2401             if field.wire:
2402                 struct_fields.append(field)
2403
2404         for field in struct_fields:
2405             length = len(field.c_field_type)
2406             # account for '*' pointer_spec
2407             if not field.type.fixed_size():
2408                 length += 1
2409             maxtypelen = max(maxtypelen, length)
2410
2411         def _c_complex_field(self, field, space=''):
2412             if (field.type.fixed_size() or
2413                 # in case of switch with switch children, don't make the field a pointer
2414                 # necessary for unserialize to work
2415                 (self.is_switch and field.type.is_switch)):
2416                 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2417                 f.write('%s    %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2418             else:
2419                 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
2420                 f.write('ELSE %s = %s\n' % (field.c_field_type, field.c_field_name))
2421                 #_h('%s    %s%s *%s%s; /**<  */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2422
2423         if not self.is_switch:
2424             for field in struct_fields:
2425                 _c_complex_field(self, field)
2426         else:
2427             for b in self.bitcases:
2428                 space = ''
2429                 if b.type.has_name:
2430                     space = '    '
2431                 for field in b.type.fields:
2432                     _c_complex_field(self, field, space)
2433                 if b.type.has_name:
2434                     print >> sys.stderr, 'ERROR: New unhandled documentation case'
2435                     pass
2436
2437         f.write('} \\fB%s\\fP;\n' % self.reply.c_type)
2438         f.write('.fi\n')
2439
2440         f.write('.SS Reply function\n')
2441         f.write('.HP\n')
2442         f.write(('%s *\\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\\ '
2443                  '\\fIcookie\\fP, xcb_generic_error_t\\ **\\fIe\\fP);\n') %
2444                 (self.c_reply_type, self.c_reply_name, self.c_cookie_type))
2445         create_link('%s' % self.c_reply_name)
2446
2447         has_accessors = False
2448         for field in self.reply.fields:
2449             if field.type.is_list and not field.type.fixed_size():
2450                 has_accessors = True
2451             elif field.prev_varsized_field is not None or not field.type.fixed_size():
2452                 has_accessors = True
2453
2454         if has_accessors:
2455             f.write('.SS Reply accessors\n')
2456
2457         def _c_accessors_field(self, field):
2458             '''
2459             Declares the accessor functions for a non-list field that follows a variable-length field.
2460             '''
2461             c_type = self.c_type
2462
2463             # special case: switch
2464             switch_obj = self if self.is_switch else None
2465             if self.is_bitcase:
2466                 switch_obj = self.parents[-1]
2467             if switch_obj is not None:
2468                 c_type = switch_obj.c_type
2469
2470             if field.type.is_simple:
2471                 f.write('%s %s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2472                 create_link('%s' % field.c_accessor_name)
2473             else:
2474                 f.write('%s *%s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2475                 create_link('%s' % field.c_accessor_name)
2476
2477         def _c_accessors_list(self, field):
2478             '''
2479             Declares the accessor functions for a list field.
2480             Declares a direct-accessor function only if the list members are fixed size.
2481             Declares length and get-iterator functions always.
2482             '''
2483             list = field.type
2484             c_type = self.reply.c_type
2485
2486             # special case: switch
2487             # in case of switch, 2 params have to be supplied to certain accessor functions:
2488             #   1. the anchestor object (request or reply)
2489             #   2. the (anchestor) switch object
2490             # the reason is that switch is either a child of a request/reply or nested in another switch,
2491             # so whenever we need to access a length field, we might need to refer to some anchestor type
2492             switch_obj = self if self.is_switch else None
2493             if self.is_bitcase:
2494                 switch_obj = self.parents[-1]
2495             if switch_obj is not None:
2496                 c_type = switch_obj.c_type
2497
2498             params = []
2499             fields = {}
2500             parents = self.parents if hasattr(self, 'parents') else [self]
2501             # 'R': parents[0] is always the 'toplevel' container type
2502             params.append(('const %s *\\fIreply\\fP' % parents[0].c_type, parents[0]))
2503             fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
2504             # auxiliary object for 'R' parameters
2505             R_obj = parents[0]
2506
2507             if switch_obj is not None:
2508                 # now look where the fields are defined that are needed to evaluate
2509                 # the switch expr, and store the parent objects in accessor_params and
2510                 # the fields in switch_fields
2511
2512                 # 'S': name for the 'toplevel' switch
2513                 toplevel_switch = parents[1]
2514                 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
2515                 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
2516
2517                 # initialize prefix for everything "below" S
2518                 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
2519                 prefix = [(prefix_str, '->', toplevel_switch)]
2520
2521                 # look for fields in the remaining containers
2522                 for p in parents[2:] + [self]:
2523                     # the separator between parent and child is always '.' here,
2524                     # because of nested switch statements
2525                     if not p.is_bitcase or (p.is_bitcase and p.has_name):
2526                         prefix.append((p.name[-1], '.', p))
2527                     fields.update(_c_helper_field_mapping(p, prefix, flat=True))
2528
2529                 # auxiliary object for 'S' parameter
2530                 S_obj = parents[1]
2531
2532             if list.member.fixed_size():
2533                 idx = 1 if switch_obj is not None else 0
2534                 f.write('.HP\n')
2535                 f.write('%s *\\fB%s\\fP(%s);\n' %
2536                         (field.c_field_type, field.c_accessor_name, params[idx][0]))
2537                 create_link('%s' % field.c_accessor_name)
2538
2539             f.write('.HP\n')
2540             f.write('int \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2541                     (field.c_length_name, c_type))
2542             create_link('%s' % field.c_length_name)
2543
2544             if field.type.member.is_simple:
2545                 f.write('.HP\n')
2546                 f.write('xcb_generic_iterator_t \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2547                         (field.c_end_name, c_type))
2548                 create_link('%s' % field.c_end_name)
2549             else:
2550                 f.write('.HP\n')
2551                 f.write('%s \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2552                         (field.c_iterator_type, field.c_iterator_name,
2553                          c_type))
2554                 create_link('%s' % field.c_iterator_name)
2555
2556         for field in self.reply.fields:
2557             if field.type.is_list and not field.type.fixed_size():
2558                 _c_accessors_list(self, field)
2559             elif field.prev_varsized_field is not None or not field.type.fixed_size():
2560                 _c_accessors_field(self, field)
2561
2562
2563     f.write('.br\n')
2564     # Re-enable hyphenation and adjusting to both sides
2565     f.write('.hy 1\n')
2566
2567     # argument reference
2568     f.write('.SH REQUEST ARGUMENTS\n')
2569     f.write('.IP \\fI%s\\fP 1i\n' % 'conn')
2570     f.write('The XCB connection to X11.\n')
2571     for field in param_fields:
2572         f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2573         printed_enum = False
2574         # XXX: hard-coded until we fix xproto.xml
2575         if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
2576             field.enum = 'GC'
2577         elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
2578             field.enum = 'CW'
2579         elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
2580             field.enum = 'CW'
2581         if hasattr(field, "enum") and field.enum:
2582             # XXX: why the 'xcb' prefix?
2583             key = ('xcb', field.enum)
2584             if key in enums:
2585                 f.write('One of the following values:\n')
2586                 f.write('.RS 1i\n')
2587                 enum = enums[key]
2588                 count = len(enum.values)
2589                 for (enam, eval) in enum.values:
2590                     count = count - 1
2591                     f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2592                     if hasattr(enum, "doc") and enum.doc and enam in enum.doc.fields:
2593                         desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2594                         f.write('%s\n' % desc)
2595                     else:
2596                         f.write('TODO: NOT YET DOCUMENTED.\n')
2597                 f.write('.RE\n')
2598                 f.write('.RS 1i\n')
2599                 printed_enum = True
2600
2601         if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2602             desc = self.doc.fields[field.field_name]
2603             desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2604             if printed_enum:
2605                 f.write('\n')
2606             f.write('%s\n' % desc)
2607         else:
2608             f.write('TODO: NOT YET DOCUMENTED.\n')
2609         if printed_enum:
2610             f.write('.RE\n')
2611
2612     # Reply reference
2613     if not void:
2614         f.write('.SH REPLY FIELDS\n')
2615         # These fields are present in every reply:
2616         f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2617         f.write(('The type of this reply, in this case \\fI%s\\fP. This field '
2618                  'is also present in the \\fIxcb_generic_reply_t\\fP and can '
2619                  'be used to tell replies apart from each other.\n') %
2620                  _n(self.reply.name).upper())
2621         f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2622         f.write('The sequence number of the last request processed by the X11 server.\n')
2623         f.write('.IP \\fI%s\\fP 1i\n' % 'length')
2624         f.write('The length of the reply, in words (a word is 4 bytes).\n')
2625         for field in self.reply.fields:
2626             if (field.c_field_name in frozenset(['response_type', 'sequence', 'length']) or
2627                 field.c_field_name.startswith('pad')):
2628                 continue
2629
2630             if field.type.is_list and not field.type.fixed_size():
2631                 continue
2632             elif field.prev_varsized_field is not None or not field.type.fixed_size():
2633                 continue
2634             f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2635             printed_enum = False
2636             if hasattr(field, "enum") and field.enum:
2637                 # XXX: why the 'xcb' prefix?
2638                 key = ('xcb', field.enum)
2639                 if key in enums:
2640                     f.write('One of the following values:\n')
2641                     f.write('.RS 1i\n')
2642                     enum = enums[key]
2643                     count = len(enum.values)
2644                     for (enam, eval) in enum.values:
2645                         count = count - 1
2646                         f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2647                         if enum.doc and enam in enum.doc.fields:
2648                             desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2649                             f.write('%s\n' % desc)
2650                         else:
2651                             f.write('TODO: NOT YET DOCUMENTED.\n')
2652                     f.write('.RE\n')
2653                     f.write('.RS 1i\n')
2654                     printed_enum = True
2655
2656             if hasattr(self.reply, "doc") and self.reply.doc and field.field_name in self.reply.doc.fields:
2657                 desc = self.reply.doc.fields[field.field_name]
2658                 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2659                 if printed_enum:
2660                     f.write('\n')
2661                 f.write('%s\n' % desc)
2662             else:
2663                 f.write('TODO: NOT YET DOCUMENTED.\n')
2664             if printed_enum:
2665                 f.write('.RE\n')
2666
2667
2668
2669     # text description
2670     f.write('.SH DESCRIPTION\n')
2671     if hasattr(self, "doc") and self.doc and self.doc.description:
2672         desc = self.doc.description
2673         desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2674         lines = desc.split('\n')
2675         f.write('\n'.join(lines) + '\n')
2676
2677     f.write('.SH RETURN VALUE\n')
2678     if void:
2679         f.write(('Returns an \\fIxcb_void_cookie_t\\fP. Errors (if any) '
2680                  'have to be handled in the event loop.\n\nIf you want to '
2681                  'handle errors directly with \\fIxcb_request_check\\fP '
2682                  'instead, use \\fI%s_checked\\fP. See '
2683                  '\\fBxcb-requests(%s)\\fP for details.\n') % (base_func_name, section))
2684     else:
2685         f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
2686                  'calling the reply function \\fI%s\\fP.\n\nIf you want to '
2687                  'handle errors in the event loop instead, use '
2688                  '\\fI%s_unchecked\\fP. See \\fBxcb-requests(%s)\\fP for '
2689                  'details.\n') %
2690                 (cookie_type, self.c_reply_name, base_func_name, section))
2691     f.write('.SH ERRORS\n')
2692     if hasattr(self, "doc") and self.doc:
2693         for errtype, errtext in self.doc.errors.items():
2694             f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
2695             errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
2696             f.write('%s\n' % (errtext))
2697     if not hasattr(self, "doc") or not self.doc or len(self.doc.errors) == 0:
2698         f.write('This request does never generate any errors.\n')
2699     if hasattr(self, "doc") and self.doc and self.doc.example:
2700         f.write('.SH EXAMPLE\n')
2701         f.write('.nf\n')
2702         f.write('.sp\n')
2703         lines = self.doc.example.split('\n')
2704         f.write('\n'.join(lines) + '\n')
2705         f.write('.fi\n')
2706     f.write('.SH SEE ALSO\n')
2707     if hasattr(self, "doc") and self.doc:
2708         see = ['.BR %s (%s)' % ('xcb-requests', section)]
2709         if self.doc.example:
2710             see.append('.BR %s (%s)' % ('xcb-examples', section))
2711         for seename, seetype in self.doc.see.items():
2712             if seetype == 'program':
2713                 see.append('.BR %s (1)' % seename)
2714             elif seetype == 'event':
2715                 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2716             elif seetype == 'request':
2717                 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2718             elif seetype == 'function':
2719                 see.append('.BR %s (%s)' % (seename, section))
2720             else:
2721                 see.append('TODO: %s (type %s)' % (seename, seetype))
2722         f.write(',\n'.join(see) + '\n')
2723     f.write('.SH AUTHOR\n')
2724     f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2725     f.close()
2726
2727 def _man_event(self, name):
2728     if manpaths:
2729         sys.stdout.write('man/%s.%s ' % (self.c_type, section))
2730     # Our CWD is src/, so this will end up in src/man/
2731     f = open('man/%s.%s' % (self.c_type, section), 'w')
2732     f.write('.TH %s %s  "%s" "%s" "XCB Events"\n' % (self.c_type, section, center_footer, left_footer))
2733     # Left-adjust instead of adjusting to both sides
2734     f.write('.ad l\n')
2735     f.write('.SH NAME\n')
2736     brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2737     f.write('%s \\- %s\n' % (self.c_type, brief))
2738     f.write('.SH SYNOPSIS\n')
2739     # Don't split words (hyphenate)
2740     f.write('.hy 0\n')
2741     f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2742
2743     f.write('.PP\n')
2744     f.write('.SS Event datastructure\n')
2745     f.write('.nf\n')
2746     f.write('.sp\n')
2747     f.write('typedef %s %s {\n' % (self.c_container, self.c_type))
2748     struct_fields = []
2749     maxtypelen = 0
2750
2751     for field in self.fields:
2752         if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2753             continue
2754         if field.wire:
2755             struct_fields.append(field)
2756
2757     for field in struct_fields:
2758         length = len(field.c_field_type)
2759         # account for '*' pointer_spec
2760         if not field.type.fixed_size():
2761             length += 1
2762         maxtypelen = max(maxtypelen, length)
2763
2764     def _c_complex_field(self, field, space=''):
2765         if (field.type.fixed_size() or
2766             # in case of switch with switch children, don't make the field a pointer
2767             # necessary for unserialize to work
2768             (self.is_switch and field.type.is_switch)):
2769             spacing = ' ' * (maxtypelen - len(field.c_field_type))
2770             f.write('%s    %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2771         else:
2772             print >> sys.stderr, 'ERROR: New unhandled documentation case'
2773
2774     if not self.is_switch:
2775         for field in struct_fields:
2776             _c_complex_field(self, field)
2777     else:
2778         for b in self.bitcases:
2779             space = ''
2780             if b.type.has_name:
2781                 space = '    '
2782             for field in b.type.fields:
2783                 _c_complex_field(self, field, space)
2784             if b.type.has_name:
2785                 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2786                 pass
2787
2788     f.write('} \\fB%s\\fP;\n' % self.c_type)
2789     f.write('.fi\n')
2790
2791
2792     f.write('.br\n')
2793     # Re-enable hyphenation and adjusting to both sides
2794     f.write('.hy 1\n')
2795
2796     # argument reference
2797     f.write('.SH EVENT FIELDS\n')
2798     f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2799     f.write(('The type of this event, in this case \\fI%s\\fP. This field is '
2800              'also present in the \\fIxcb_generic_event_t\\fP and can be used '
2801              'to tell events apart from each other.\n') % _n(name).upper())
2802     f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2803     f.write('The sequence number of the last request processed by the X11 server.\n')
2804
2805     if not self.is_switch:
2806         for field in struct_fields:
2807             # Skip the fields which every event has, we already documented
2808             # them (see above).
2809             if field.c_field_name in ('response_type', 'sequence'):
2810                 continue
2811             if isinstance(field.type, PadType):
2812                 continue
2813             f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2814             if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2815                 desc = self.doc.fields[field.field_name]
2816                 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2817                 f.write('%s\n' % desc)
2818             else:
2819                 f.write('NOT YET DOCUMENTED.\n')
2820
2821     # text description
2822     f.write('.SH DESCRIPTION\n')
2823     if hasattr(self, "doc") and self.doc and self.doc.description:
2824         desc = self.doc.description
2825         desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2826         lines = desc.split('\n')
2827         f.write('\n'.join(lines) + '\n')
2828
2829     if hasattr(self, "doc") and self.doc and self.doc.example:
2830         f.write('.SH EXAMPLE\n')
2831         f.write('.nf\n')
2832         f.write('.sp\n')
2833         lines = self.doc.example.split('\n')
2834         f.write('\n'.join(lines) + '\n')
2835         f.write('.fi\n')
2836     f.write('.SH SEE ALSO\n')
2837     if hasattr(self, "doc") and self.doc:
2838         see = ['.BR %s (%s)' % ('xcb_generic_event_t', section)]
2839         if self.doc.example:
2840             see.append('.BR %s (%s)' % ('xcb-examples', section))
2841         for seename, seetype in self.doc.see.items():
2842             if seetype == 'program':
2843                 see.append('.BR %s (1)' % seename)
2844             elif seetype == 'event':
2845                 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2846             elif seetype == 'request':
2847                 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2848             elif seetype == 'function':
2849                 see.append('.BR %s (%s)' % (seename, section))
2850             else:
2851                 see.append('TODO: %s (type %s)' % (seename, seetype))
2852         f.write(',\n'.join(see) + '\n')
2853     f.write('.SH AUTHOR\n')
2854     f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2855     f.close()
2856
2857
2858 def c_request(self, name):
2859     '''
2860     Exported function that handles request declarations.
2861     '''
2862     _c_type_setup(self, name, ('request',))
2863
2864     if self.reply:
2865         # Cookie type declaration
2866         _c_cookie(self, name)
2867
2868     # Opcode define
2869     _c_opcode(name, self.opcode)
2870
2871     # Request structure declaration
2872     _c_complex(self)
2873
2874     if self.reply:
2875         _c_type_setup(self.reply, name, ('reply',))
2876         # Reply structure definition
2877         _c_complex(self.reply)
2878         # Request prototypes
2879         has_fds = _c_reply_has_fds(self.reply)
2880         _c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds)
2881         _c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds)
2882         if self.need_aux:
2883             _c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds)
2884             _c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds)
2885         # Reply accessors
2886         _c_accessors(self.reply, name + ('reply',), name)
2887         _c_reply(self, name)
2888         if has_fds:
2889             _c_reply_fds(self, name)
2890     else:
2891         # Request prototypes
2892         _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2893         _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2894         if self.need_aux:
2895             _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2896             _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2897
2898     # We generate the manpage afterwards because _c_type_setup has been called.
2899     # TODO: what about aux helpers?
2900     cookie_type = self.c_cookie_type if self.reply else 'xcb_void_cookie_t'
2901     _man_request(self, name, cookie_type, not self.reply, False)
2902
2903 def c_event(self, name):
2904     '''
2905     Exported function that handles event declarations.
2906     '''
2907
2908     # The generic event structure xcb_ge_event_t has the full_sequence field
2909     # at the 32byte boundary. That's why we've to inject this field into GE
2910     # events while generating the structure for them. Otherwise we would read
2911     # garbage (the internal full_sequence) when accessing normal event fields
2912     # there.
2913     force_packed = False
2914     if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
2915         event_size = 0
2916         for field in self.fields:
2917             if field.type.size != None and field.type.nmemb != None:
2918                 event_size += field.type.size * field.type.nmemb
2919             if event_size == 32:
2920                 full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
2921                 idx = self.fields.index(field)
2922                 self.fields.insert(idx + 1, full_sequence)
2923
2924                 # If the event contains any 64-bit extended fields, they need
2925                 # to remain aligned on a 64-bit boundary.  Adding full_sequence
2926                 # would normally break that; force the struct to be packed.
2927                 force_packed = any(f.type.size == 8 and f.type.is_simple for f in self.fields[(idx+1):])
2928                 break
2929
2930     _c_type_setup(self, name, ('event',))
2931
2932     # Opcode define
2933     _c_opcode(name, self.opcodes[name])
2934
2935     if self.name == name:
2936         # Structure definition
2937         _c_complex(self, force_packed)
2938     else:
2939         # Typedef
2940         _h('')
2941         _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2942
2943     _man_event(self, name)
2944
2945 def c_error(self, name):
2946     '''
2947     Exported function that handles error declarations.
2948     '''
2949     _c_type_setup(self, name, ('error',))
2950
2951     # Opcode define
2952     _c_opcode(name, self.opcodes[name])
2953
2954     if self.name == name:
2955         # Structure definition
2956         _c_complex(self)
2957     else:
2958         # Typedef
2959         _h('')
2960         _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2961
2962
2963 # Main routine starts here
2964
2965 # Must create an "output" dictionary before any xcbgen imports.
2966 output = {'open'    : c_open,
2967           'close'   : c_close,
2968           'simple'  : c_simple,
2969           'enum'    : c_enum,
2970           'struct'  : c_struct,
2971           'union'   : c_union,
2972           'request' : c_request,
2973           'event'   : c_event,
2974           'error'   : c_error, 
2975           }
2976
2977 # Boilerplate below this point
2978
2979 # Check for the argument that specifies path to the xcbgen python package.
2980 try:
2981     opts, args = getopt.getopt(sys.argv[1:], 'c:l:s:p:m')
2982 except getopt.GetoptError as err:
2983     print(err)
2984     print('Usage: c_client.py -c center_footer -l left_footer -s section [-p path] file.xml')
2985     sys.exit(1)
2986
2987 for (opt, arg) in opts:
2988     if opt == '-c':
2989         center_footer=arg
2990     if opt == '-l':
2991         left_footer=arg
2992     if opt == '-s':
2993         section=arg
2994     if opt == '-p':
2995         sys.path.insert(1, arg)
2996     elif opt == '-m':
2997         manpaths = True
2998         sys.stdout.write('man_MANS = ')
2999
3000 # Import the module class
3001 try:
3002     from xcbgen.state import Module
3003     from xcbgen.xtypes import *
3004 except ImportError:
3005     print('''
3006 Failed to load the xcbgen Python package!
3007 Make sure that xcb/proto installed it on your Python path.
3008 If not, you will need to create a .pth file or define $PYTHONPATH
3009 to extend the path.
3010 Refer to the README file in xcb/proto for more info.
3011 ''')
3012     raise
3013
3014 # Ensure the man subdirectory exists
3015 try:
3016     os.mkdir('man')
3017 except OSError as e:
3018     if e.errno != errno.EEXIST:
3019         raise
3020
3021 today = time.strftime('%Y-%m-%d', time.gmtime(os.path.getmtime(args[0])))
3022
3023 # Parse the xml header
3024 module = Module(args[0], output)
3025
3026 # Build type-registry and resolve type dependencies
3027 module.register()
3028 module.resolve()
3029
3030 # Output the code
3031 module.generate()