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