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