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