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