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