attempt to fix special case: variable fields followed by fixed size fields
[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 import getopt
5 import sys
6 import re
7
8 # Jump to the bottom of this file for the main routine
9
10 # Some hacks to make the API more readable, and to keep backwards compability
11 _cname_re = re.compile('([A-Z0-9][a-z]+|[A-Z0-9]+(?![a-z])|[a-z]+)')
12 _cname_special_cases = {'DECnet':'decnet'}
13
14 _extension_special_cases = ['XPrint', 'XCMisc', 'BigRequests']
15
16 _cplusplus_annoyances = {'class' : '_class',
17                          'new'   : '_new',
18                          'delete': '_delete'}
19 _c_keywords = {'default' : '_default'}
20
21 _hlines = []
22 _hlevel = 0
23 _clines = []
24 _clevel = 0
25 _ns = None
26
27 # global variable to keep track of serializers and switch data types
28 # due to weird dependencies, I see no way to do this more elegant at the moment
29 finished_serializers = []
30 finished_switch = []
31
32 def _h(fmt, *args):
33     '''
34     Writes the given line to the header file.
35     '''
36     _hlines[_hlevel].append(fmt % args)
37     
38 def _c(fmt, *args):
39     '''
40     Writes the given line to the source file.
41     '''
42     _clines[_clevel].append(fmt % args)
43     
44 def _hc(fmt, *args):
45     '''
46     Writes the given line to both the header and source files.
47     '''
48     _h(fmt, *args)
49     _c(fmt, *args)
50
51 # XXX See if this level thing is really necessary.
52 def _h_setlevel(idx):
53     '''
54     Changes the array that header lines are written to.
55     Supports writing different sections of the header file.
56     '''
57     global _hlevel
58     while len(_hlines) <= idx:
59         _hlines.append([])
60     _hlevel = idx
61     
62 def _c_setlevel(idx):
63     '''
64     Changes the array that source lines are written to.
65     Supports writing to different sections of the source file.
66     '''
67     global _clevel
68     while len(_clines) <= idx:
69         _clines.append([])
70     _clevel = idx
71     
72 def _n_item(str):
73     '''
74     Does C-name conversion on a single string fragment.
75     Uses a regexp with some hard-coded special cases.
76     '''
77     if str in _cname_special_cases:
78         return _cname_special_cases[str]
79     else:
80         split = _cname_re.finditer(str)
81         name_parts = [match.group(0) for match in split]
82         return '_'.join(name_parts)
83     
84 def _cpp(str):
85     '''
86     Checks for certain C++ reserved words and fixes them.
87     '''
88     if str in _cplusplus_annoyances:
89         return _cplusplus_annoyances[str]
90     elif str in _c_keywords:
91         return  _c_keywords[str]
92     else:
93         return str
94
95 def _ext(str):
96     '''
97     Does C-name conversion on an extension name.
98     Has some additional special cases on top of _n_item.
99     '''
100     if str in _extension_special_cases:
101         return _n_item(str).lower()
102     else:
103         return str.lower()
104     
105 def _n(list):
106     '''
107     Does C-name conversion on a tuple of strings.
108     Different behavior depending on length of tuple, extension/not extension, etc.
109     Basically C-name converts the individual pieces, then joins with underscores.
110     '''
111     if len(list) == 1:
112         parts = list
113     elif len(list) == 2:
114         parts = [list[0], _n_item(list[1])]
115     elif _ns.is_ext:
116         parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
117     else:
118         parts = [list[0]] + [_n_item(i) for i in list[1:]]
119     return '_'.join(parts).lower()
120
121 def _t(list):
122     '''
123     Does C-name conversion on a tuple of strings representing a type.
124     Same as _n but adds a "_t" on the end.
125     '''
126     if len(list) == 1:
127         parts = list
128     elif len(list) == 2:
129         parts = [list[0], _n_item(list[1]), 't']
130     elif _ns.is_ext:
131         parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
132     else:
133         parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
134     return '_'.join(parts).lower()
135         
136
137 def c_open(self):
138     '''
139     Exported function that handles module open.
140     Opens the files and writes out the auto-generated comment, header file includes, etc.
141     '''
142     global _ns
143     _ns = self.namespace
144     _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
145
146     # Build the type-name collision avoidance table used by c_enum
147     build_collision_table()
148
149     _h_setlevel(0)
150     _c_setlevel(0)
151
152     _hc('/*')
153     _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
154     _hc(' * Edit at your peril.')
155     _hc(' */')
156     _hc('')
157
158     _h('/**')
159     _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
160     _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
161     _h(' * @{')
162     _h(' **/')
163     _h('')
164     _h('#ifndef __%s_H', _ns.header.upper())
165     _h('#define __%s_H', _ns.header.upper())
166     _h('')
167     _h('#include "xcb.h"')
168
169     _c('#include <stdlib.h>')
170     _c('#include <string.h>')
171     _c('#include <assert.h>')
172     _c('#include "xcbext.h"')
173     _c('#include "%s.h"', _ns.header)
174         
175     if _ns.is_ext:
176         for (n, h) in self.imports:
177             _hc('#include "%s.h"', h)
178
179     _h('')
180     _h('#ifdef __cplusplus')
181     _h('extern "C" {')
182     _h('#endif')
183
184     if _ns.is_ext:
185         _h('')
186         _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
187         _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
188         _h('  ') #XXX
189         _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
190
191         _c('')
192         _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
193
194 def c_close(self):
195     '''
196     Exported function that handles module close.
197     Writes out all the stored content lines, then closes the files.
198     '''
199     _h_setlevel(2)
200     _c_setlevel(2)
201     _hc('')
202
203     _h('')
204     _h('#ifdef __cplusplus')
205     _h('}')
206     _h('#endif')
207
208     _h('')
209     _h('#endif')
210     _h('')
211     _h('/**')
212     _h(' * @}')
213     _h(' */')
214
215     # Write header file
216     hfile = open('%s.h' % _ns.header, 'w')
217     for list in _hlines:
218         for line in list:
219             hfile.write(line)
220             hfile.write('\n')
221     hfile.close()
222
223     # Write source file
224     cfile = open('%s.c' % _ns.header, 'w')
225     for list in _clines:
226         for line in list:
227             cfile.write(line)
228             cfile.write('\n')
229     cfile.close()
230
231 def build_collision_table():
232     global namecount
233     namecount = {}
234
235     for v in module.types.values():
236         name = _t(v[0])
237         namecount[name] = (namecount.get(name) or 0) + 1
238
239 def c_enum(self, name):
240     '''
241     Exported function that handles enum declarations.
242     '''
243
244     tname = _t(name)
245     if namecount[tname] > 1:
246         tname = _t(name + ('enum',))
247
248     _h_setlevel(0)
249     _h('')
250     _h('typedef enum %s {', tname)
251
252     count = len(self.values)
253
254     for (enam, eval) in self.values:
255         count = count - 1
256         equals = ' = ' if eval != '' else ''
257         comma = ',' if count > 0 else ''
258         _h('    %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
259
260     _h('} %s;', tname)
261
262 def _c_type_setup(self, name, postfix):
263     '''
264     Sets up all the C-related state by adding additional data fields to
265     all Field and Type objects.  Here is where we figure out most of our
266     variable and function names.
267
268     Recurses into child fields and list member types.
269     '''
270     # Do all the various names in advance
271     self.c_type = _t(name + postfix)
272     self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
273
274     self.c_iterator_type = _t(name + ('iterator',))
275     self.c_next_name = _n(name + ('next',))
276     self.c_end_name = _n(name + ('end',))
277
278     self.c_request_name = _n(name)
279     self.c_checked_name = _n(name + ('checked',))
280     self.c_unchecked_name = _n(name + ('unchecked',))
281     self.c_reply_name = _n(name + ('reply',))
282     self.c_reply_type = _t(name + ('reply',))
283     self.c_cookie_type = _t(name + ('cookie',))
284
285     self.c_aux_name = _n(name + ('aux',))
286     self.c_aux_checked_name = _n(name + ('aux', 'checked'))
287     self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
288     self.c_serialize_name = _n(name + ('serialize',))
289     self.c_unserialize_name = _n(name + ('unserialize',))
290 #    if hasattr(self, 'reply'):
291 #        if self.reply is not None:
292 #            self.c_serialize_name = _n(name + ('reply', 'serialize'))
293 #            self.c_unserialize_name = _n(name + ('reply', 'unserialize'))
294     # indicates rare structs where variable size fields are followed fixed size fields
295     self.var_followed_by_fixed_fields = False
296
297     # whether a request or reply has a switch field
298     self.need_aux = False
299     self.need_serialize = False
300     if self.is_switch:
301         self.need_serialize = True
302         self.c_container = 'struct'
303         for bitcase in self.bitcases:
304             bitcase.c_field_name = _cpp(bitcase.field_name)
305             _c_type_setup(bitcase.type, bitcase.field_type, ())
306
307     elif self.is_container:
308
309         self.c_container = 'union' if self.is_union else 'struct'
310         prev_varsized_field = None
311         prev_varsized_offset = 0
312         first_field_after_varsized = None
313
314         for field in self.fields:
315             _c_type_setup(field.type, field.field_type, ())
316             if field.type.is_list:
317                 _c_type_setup(field.type.member, field.field_type, ())
318                 # FIXME - structures with variable sized members, sort out when serialize() is needed
319                 if (field.type.nmemb is None): # and not field.type.member.fixed_size():
320                     self.need_serialize = True
321
322             field.c_field_type = _t(field.field_type)
323             field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
324             field.c_field_name = _cpp(field.field_name)
325             field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
326             field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
327             if field.type.is_switch:
328                 field.c_pointer = '*'
329                 field.c_field_const_type = 'const ' + field.c_field_type
330                 self.need_aux = True
331             elif not field.type.fixed_size() and not field.type.is_bitcase:
332                 self.need_serialize = True
333
334             field.c_iterator_type = _t(field.field_type + ('iterator',))      # xcb_fieldtype_iterator_t
335             field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
336             field.c_accessor_name = _n(name + (field.field_name,))            # xcb_container_field
337             field.c_length_name = _n(name + (field.field_name, 'length'))     # xcb_container_field_length
338
339             # special case - c_field_name ends with _length as well
340             # if field.c_accessor_name.endswith('_length'):
341             #     raise Exception(field.c_field_name)
342             #if field.c_field_name.endswith('length'):
343             #    c_field_name = field.c_field_name.rsplit('length', 1)
344             #    field.c_field_name = c_field_name[0] + "_length"
345             field.c_end_name = _n(name + (field.field_name, 'end'))           # xcb_container_field_end
346
347             field.prev_varsized_field = prev_varsized_field
348             field.prev_varsized_offset = prev_varsized_offset
349
350             if prev_varsized_offset == 0:
351                 first_field_after_varsized = field
352             field.first_field_after_varsized = first_field_after_varsized
353
354             if field.type.fixed_size():
355                 prev_varsized_offset += field.type.size
356                 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
357                     if not self.is_union:
358                         self.need_serialize = True
359                         self.var_followed_by_fixed_fields = True
360             else:
361                 self.last_varsized_field = field
362                 prev_varsized_field = field
363                 prev_varsized_offset = 0                    
364
365             # very special case - if self.var_followed_by_fixed_fields==True, 
366             # we have to generate accessor functions also for fixed size fields
367             # now there might a naming conflict if the length field ends with _length
368             if self.var_followed_by_fixed_fields:
369                 if field.type.is_list:
370                     if field.type.expr.lenfield_name is not None:
371                         full_lenfield_name = _n(name + (field.type.expr.lenfield_name,))
372                         if full_lenfield_name == field.c_length_name:
373                             field.c_length_name += '_'
374
375     # as switch does never appear at toplevel, 
376     # continue here with type construction
377     if self.is_switch:
378         if self.c_type not in finished_switch:
379             finished_switch.append(self.c_type)
380             # special: switch C structs get pointer fields for variable-sized members
381             _c_complex(self)
382             # FIXME: declare switch (un)packing functions
383             _c_accessors(self, name, name)
384
385     # FIXME - in case of request/reply, serialize() is not always needed
386     if self.need_serialize and not self.is_bitcase:
387         if self.c_serialize_name not in finished_serializers:
388             finished_serializers.append(self.c_serialize_name)
389             _c_serialize(self)
390             _c_unserialize(self)
391 # _c_type_setup()
392
393 def get_request_fields(self):
394     param_fields = []
395     wire_fields = []
396
397     for field in self.fields:
398         if field.visible:
399             # the field should appear as a parameter in the function call
400             param_fields.append(field)
401         if field.wire and not field.auto:
402             if field.type.fixed_size() and not self.is_switch:
403                 # field in the xcb_out structure
404                 wire_fields.append(field)
405         # fields like 'pad0' are skipped!
406                     
407     return (param_fields, wire_fields)
408 # get_request_fields()
409
410 def get_expr_fields(self):
411     # get the fields referenced by switch or list expression
412     def get_expr_field_names(expr):
413         if expr.op is None:
414             if expr.lenfield_name is not None:
415                 return [expr.lenfield_name]
416             else:
417                 # constant value expr
418                 return []
419         else:
420             if expr.op == '~':
421                 return get_expr_field_names(expr.rhs)
422             elif expr.op == 'popcount':
423                 return get_expr_field_names(expr.rhs)
424             elif expr.op == 'sumof':
425                 return [expr.lenfield_name]
426             elif expr.op == 'enumref':
427                 return []
428             else:
429                 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
430     # get_expr_field_names()
431     
432     # resolve the field names with the parent structure(s)
433     unresolved_fields = get_expr_field_names(self.expr)
434     if unresolved_fields is None:
435         return []
436     expr_fields = dict.fromkeys(unresolved_fields)
437     for p in reversed(self.parent):
438         parent_fields = dict((f.field_name, f) for f in p.fields)
439         for f in parent_fields.keys():
440             if f in unresolved_fields:
441                 expr_fields[f] = parent_fields[f]
442                 unresolved_fields.remove(f)
443         if len(unresolved_fields) == 0:
444             break
445                 
446     if None in expr_fields.values():
447         raise Exception("could not resolve all fields for %s" % self.name)
448
449     params = expr_fields.values()
450     return params
451 # get_expr_fields()
452
453 def resolve_fields(anchestor, complex_obj=None):
454     """find fields referenced by anchestor or descendents with external scope"""
455     expr_fields = []
456     unresolved = []
457     all_fields = []
458     if complex_obj is None:
459         complex_obj = anchestor
460     for field in complex_obj.fields:
461         all_fields.append(field)
462         if field.type.is_switch or field.type.is_list:
463             expr_fields += get_expr_fields(field.type)
464         if field.type.is_container:
465             expr_fields += resolve_fields(anchestor, field.type)
466     # try to resolve expr fields
467     for e in expr_fields:
468         if e not in all_fields:
469             unresolved.append(e)
470     return unresolved
471             
472 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
473     def add_param(params, param):
474         if param not in params:
475             params.append(param)
476
477     param_fields, wire_fields = get_request_fields(self)
478     if self.is_switch:
479         param_fields = get_expr_fields(self)
480
481     # _serialize function parameters
482     # cannot use set() for params, as series is important
483     params = []
484     if  'serialize' == context:
485         params.append(('void', '**', buffer_var))
486     elif 'unserialize' == context:
487         params.append(('const void', '*', buffer_var))
488
489     # look for special cases
490     unresolved_fields = resolve_fields(self)
491     for f in unresolved_fields:
492         add_param(params, (f.c_field_type, '', f.c_field_name))
493
494     # make sure all required length fields are present
495     for p in param_fields:
496         if p.visible and not p.wire and not p.auto:
497             typespec = p.c_field_type
498             pointerspec = ''
499             add_param(params, (typespec, pointerspec, p.c_field_name))
500
501     # parameter fields if any
502     if self.is_switch:
503         for p in get_expr_fields(self):
504             typespec = p.c_field_const_type
505             pointerspec = p.c_pointer 
506             add_param(params, (typespec, pointerspec, p.c_field_name))
507   
508     # aux argument - structure to be serialized
509     if 'serialize' == context:
510         add_param(params, ('const %s' % self.c_type, '*', aux_var))
511     elif 'unserialize' == context and self.is_switch:
512         add_param(params, ('%s' % self.c_type, '*', aux_var))
513     if not self.is_switch and 'serialize' == context:
514         for p in param_fields:
515             if not p.type.fixed_size():
516                 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
517     return (param_fields, wire_fields, params)
518 # get_serialize_params()
519
520 def _c_serialize_helper_prefix(prefix):
521     # prefix is a list of (field_name, anchestor object) tuples
522     # concatenate field names
523     prefix_str = ''
524     for name, sep, obj in prefix:
525         prefix_str += name
526         if sep == '':
527             sep = '.' if (obj.is_bitcase and obj.has_name) else '->'
528         prefix_str += sep
529     lenfield_prefix = '' if prefix_str.find('_aux')==0 else "_aux"
530     if prefix_str != '':
531         if lenfield_prefix != '':
532             lenfield_prefix += '->' 
533         lenfield_prefix += prefix_str
534     return (prefix_str, lenfield_prefix)
535 # _c_serialize_helper_prefix
536
537 def _c_field_mapping(context, complex_type, prefix):
538     def get_prefix(field, prefix):
539         prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
540         if prefix_str == '':
541             if context in ('serialize', 'unserialize'):
542                 if field.type.fixed_size() or complex_type.is_switch:
543                     prefix_str = '_aux->'
544             else:
545                 raise Exception("unknown context '%s' in c_field_mapping" % context)
546         return prefix_str
547     # get_prefix()
548     def get_field_name(fields, complex_type, prefix):
549         for f in complex_type.fields:
550             prefix_str = get_prefix(f, prefix)
551
552             fname = "%s%s" % (prefix_str, f.c_field_name)
553             if fields.has_key(f.field_name):
554                 continue
555                 # FIXME 
556                 raise Exception("field name %s has been registered before" % f.field_name)
557             fields[f.field_name] = (fname, f)
558             if f.type.is_container:
559                 get_field_name(fields, f.type, prefix+[(f.c_field_name, '', f.type)])
560     # get_field_name()
561
562     # dict(field_name : (c_field_name, field))
563     fields = {}
564     get_field_name(fields, complex_type, prefix)
565     
566     # switch: get the fields referenced by the switch expr as well
567     #         these may not belong to any structure
568     if complex_type.is_switch:
569         pass
570 #       FIXME: fields += get_serialize_params(context, complex_type)
571
572     return fields
573 # _c_field_mapping()
574
575 def _c_serialize_helper_insert_padding(context, code_lines, space):
576     code_lines.append('%s    xcb_buffer_len += xcb_block_len;' % space)
577     code_lines.append('%s    /* padding */' % space)
578     code_lines.append('%s    xcb_pad = -xcb_block_len & 3;' % space)
579     code_lines.append('%s    if (0 != xcb_pad) {' % space)
580
581     if 'serialize' == context:
582         code_lines.append('%s        xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
583         code_lines.append('%s        xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
584         code_lines.append('%s        xcb_parts_idx++;' % space)
585     elif 'unserialize' == context:
586         code_lines.append('%s        xcb_tmp += xcb_pad;' % space)
587
588     code_lines.append('%s        xcb_buffer_len += xcb_pad;' % space)    
589     code_lines.append('%s        xcb_pad = 0;' % space)
590     code_lines.append('%s    }' % space)
591     code_lines.append('%s    xcb_block_len = 0;' % space)
592     
593     return 1
594 # _c_serialize_helper_insert_padding()
595
596 def _c_serialize_helper_switch(context, self, complex_name, 
597                                code_lines, temp_vars, 
598                                space, prefix):
599     count = 0
600     switch_prefix = prefix + [(complex_name, '->', self)]
601     prefix_str, lenfield_prefix = _c_serialize_helper_prefix(switch_prefix)
602     switch_expr = _c_accessor_get_expr(self.expr)
603     
604     for b in self.bitcases:            
605         bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix_str)
606         code_lines.append('    if(%s & %s) {' % (switch_expr, bitcase_expr))
607         b_prefix = switch_prefix
608         if b.type.has_name:
609             b_prefix = switch_prefix + [(b.c_field_name, '.', b.type)]
610         _c_serialize_helper_fields(context, b.type, 
611                                    code_lines, temp_vars, 
612                                    "%s    " % space, 
613                                    b_prefix, 
614                                    is_bitcase = True)
615         code_lines.append('    }')
616
617     if 'serialize' == context:
618         count = _c_serialize_helper_insert_padding(context, code_lines, space)
619     if 'unserialize' == context:
620         # padding
621         code_lines.append('%s    xcb_pad = -xcb_block_len & 3;' % space)
622         code_lines.append('%s    xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
623     
624     return count
625 # _c_serialize_helper_switch
626
627 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
628     # switch is handled by this function as a special case
629     param_fields, wire_fields, params = get_serialize_params(context, self)
630     args = get_expr_fields(field.type)
631     field_mapping = _c_field_mapping(context, self, prefix)
632
633     # determine which params to pass to _unserialize() and their prefixes
634     switch_len_fields = resolve_fields(self, field.type)
635     bitcase_unresolved = resolve_fields(self, self)
636     if len(bitcase_unresolved) != 0:
637         raise Exception('unresolved fields within bitcase is not supported at this point')
638     c_field_names = ''
639     for a in switch_len_fields:
640         c_field_names += "%s, " % field_mapping[a.c_field_name][0]
641     for a in args:
642         c_field_names += "%s, " % field_mapping[a.c_field_name][0]
643 #    switch_field_name = field_mapping[field.field_name][0]
644     # call _unserialize() to determine the actual size
645     length = "%s(xcb_tmp, %s&%s)" % (field.type.c_unserialize_name, 
646                                      c_field_names, c_switch_variable) #switch_field_name)
647     return length
648 # _c_serialize_helper_switch_field()
649
650 def _c_serialize_helper_list_field(context, self, field, 
651                                    code_lines, temp_vars, 
652                                    space, prefix):
653     """
654     helper function for (un)serialize to cope with lists of variable length
655     """
656     expr = field.type.expr
657     prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
658     param_fields, wire_fields, params = get_serialize_params('unserialize', self)
659     param_names = [p[2] for p in params]
660
661     # look if the list's lenfield is a struct member or a function argument
662     # special case: if the list has a length field, its name will be returned 
663     # unchanged by calling c_accessor_get_length(expr)
664     if expr.lenfield_name == _c_accessor_get_length(expr):
665         if expr.lenfield_name in param_names:
666             # the length field appears as separate argument in unserialize, 
667             # so no need for a prefix
668             lenfield_prefix = ''
669     sep = '.' if (self.is_bitcase and self.has_name) else '->'
670     list_length = _c_accessor_get_expr(expr, lenfield_prefix, sep)
671
672     # default: list with fixed size elements
673     length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
674     # list with variable-sized elements 
675     if field.type.size is None:
676         length = ''
677         if 'unserialize' == context:
678             int_i = '    unsigned int i;'
679             xcb_tmp_len = '    unsigned int xcb_tmp_len;'
680             if int_i not in temp_vars:
681                 temp_vars.append(int_i)
682             if xcb_tmp_len not in temp_vars:
683                 temp_vars.append(xcb_tmp_len)
684             code_lines.append("%s    for(i=0; i<%s; i++) {" % (space, list_length))
685             code_lines.append("%s        xcb_tmp_len = %s(xcb_tmp);" % 
686                               (space, field.type.c_unserialize_name))
687             code_lines.append("%s        xcb_block_len += xcb_tmp_len;" % space)
688             code_lines.append("%s        xcb_tmp += xcb_tmp_len;" % space)
689             code_lines.append("%s    }" % space)                        
690         elif 'serialize' == context:
691             code_lines.append('%s    xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
692             code_lines.append('%s    xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
693             code_lines.append('%s    for(i=0; i<%s; i++) { ' 
694                               % (space, _c_accessor_get_expr(expr, lenfield_prefix, sep)))
695             code_lines.append('%s        xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_unserialize_name))
696             code_lines.append('%s        xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
697             code_lines.append('%s    }' % space)
698             code_lines.append('%s    xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
699             
700     return length
701 # _c_serialize_helper_list_field()
702
703 def _c_serialize_helper_fields_fixed_size(context, self, field, 
704                                           code_lines, temp_vars, 
705                                           space, prefix):
706     code_lines.append('%s    /* %s.%s */' % (space, self.c_type, field.c_field_name))
707     prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
708
709     length = "sizeof(%s)" % field.c_field_type
710
711     if 'unserialize' == context:
712         value = '    %s%s = *(%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type) 
713         if field.type.is_pad and field.type.nmemb > 1:
714             value = ''
715             for i in range(field.type.nmemb):
716                 code_lines.append('%s    %s%s[%d] = *(%s *)xcb_tmp;' % 
717                                   (space, prefix_str, field.c_field_name, i, field.c_field_type)) 
718             length += " * %d" % field.type.nmemb
719         # FIXME? - lists
720         if field.type.is_list:
721             raise Exception('list with fixed number of elemens unhandled in _unserialize()')
722     elif 'serialize' == context:
723         value = '    xcb_parts[xcb_parts_idx].iov_base = (char *) ' 
724
725         if field.type.is_expr:
726             # need to register a temporary variable for the expression
727             if field.type.c_type is None:
728                 raise Exception("type for field '%s' (expression '%s') unkown" % 
729                                 (field.field_name, _c_accessor_get_expr(field.type.expr)))
730             temp_vars.append('    %s xcb_expr_%s = %s;' % (field.type.c_type, field.field_name, 
731                                                            _c_accessor_get_expr(field.type.expr, prefix)))
732             value += "&xcb_expr_%s;" % field.field_name 
733
734         elif field.type.is_pad:
735             if field.type.nmemb == 1:
736                 value += "&xcb_pad;"
737             else:
738                 # FIXME - possible segmentation fault!!
739                 value = '    memset(xcb_parts[xcb_parts_idx].iov_base, 0, %d);' % field.type.nmemb
740                 length += "*%d" % field.type.nmemb
741
742         else:
743             # non-list type with fixed size
744             if field.type.nmemb == 1:
745                 value += "&%s%s;" % (prefix_str, field.c_field_name)
746             # list with nmemb (fixed size) elements
747             else:
748                 value += '%s%s;' % (prefix_str, field.c_field_name)
749                 length = '%d' % field.type.nmemb
750
751     return (value, length)
752 # _c_serialize_helper_fields_fixed_size()
753
754 def _c_serialize_helper_fields_variable_size(context, self, field, 
755                                              code_lines, temp_vars, 
756                                              space, prefix):
757     prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
758
759     if 'unserialize' == context:
760         value = ''
761     elif 'serialize' == context:
762         address_of = '&' if (self.is_bitcase and self.has_name) else ''
763         value = '    xcb_parts[xcb_parts_idx].iov_base = (char *) %s%s%s;' % (address_of, prefix_str, field.c_field_name)
764     length = ''
765
766     prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
767     code_lines.append('%s    /* %s */' % (space, field.c_field_name))
768
769     if field.type.is_list:
770         length = _c_serialize_helper_list_field(context, self, field, 
771                                                 code_lines, temp_vars, 
772                                                 space, prefix)
773     elif field.type.is_switch:
774         prev = filter(lambda x: x.find('xcb_switch_field'), temp_vars)
775         var_name = 'xcb_switch_field%d' % len(prev)
776         temp_vars.append('    %s %s;' % (field.type.c_type, var_name))
777         length = _c_serialize_helper_switch_field(context, self, field, var_name, prefix)
778     else:
779         length = "%s(xcb_tmp)" % (field.type.c_unserialize_name)
780
781     return (value, length)
782 # _c_serialize_helper_fields_variable_size
783
784 def _c_serialize_helper_fields(context, self, 
785                                code_lines, temp_vars, 
786                                space, prefix, is_bitcase):
787     count = 0
788     need_padding = False
789     prev_field_was_variable = False
790
791     for field in self.fields:
792         if not ((field.wire and not field.auto) or field.visible):
793             continue
794
795         # switch/bitcase: fixed size fields must be considered explicitly 
796         if field.type.fixed_size():
797             if self.is_bitcase or self.var_followed_by_fixed_fields:
798                 if prev_field_was_variable and need_padding:
799                     # insert padding
800                     _c_serialize_helper_insert_padding(context, code_lines, space)
801                     prev_field_was_variable = False
802                 fixed_prefix = prefix
803                 if self.var_followed_by_fixed_fields and len(prefix)==0:
804                     fixed_prefix = [('_aux', '->', self)]
805                 value, length = _c_serialize_helper_fields_fixed_size(context, self, field, 
806                                                                       code_lines, temp_vars, 
807                                                                       space, fixed_prefix)
808             else:
809                 continue
810
811         # fields with variable size
812         else:
813             # switch/bitcase: always calculate padding before and after variable sized fields
814             if need_padding or is_bitcase:
815                 _c_serialize_helper_insert_padding(context, code_lines, space)
816
817             value, length = _c_serialize_helper_fields_variable_size(context, self, field, 
818                                                                      code_lines, temp_vars, 
819                                                                      space, prefix)
820             prev_field_was_variable = True
821                 
822         # save (un)serialization C code
823         if '' != value:
824             code_lines.append('%s%s' % (space, value))
825         if field.type.fixed_size() and is_bitcase:
826             code_lines.append('%s    xcb_block_len += %s;' % (space, length))
827             if 'unserialize' == context:
828                 code_lines.append('%s    xcb_tmp += %s;' % (space, length))
829         else:
830             # padding
831             if '' != length:
832                 code_lines.append('%s    xcb_block_len = %s;' % (space, length))
833                 if 'unserialize' == context:
834                     code_lines.append('%s    xcb_tmp += xcb_block_len;' % space)
835         if 'serialize' == context:
836             if '' != length:
837                 code_lines.append('%s    xcb_parts[xcb_parts_idx].iov_len = xcb_block_len;' % space)
838             code_lines.append('%s    xcb_parts_idx++;' % space)
839             count += 1
840         need_padding = True
841         
842     return count
843 # _c_serialize_helper_fields()    
844
845 def _c_serialize_helper(context, complex_type, 
846                         code_lines, temp_vars, 
847                         space='', prefix=[]):
848     count = 0
849     if hasattr(complex_type, 'type'):
850         self = complex_type.type
851         complex_name = complex_type.name
852     else:
853         self = complex_type
854         complex_name = '_aux'
855
856     # special case: switch is serialized by evaluating each bitcase separately
857     if self.is_switch:
858         count += _c_serialize_helper_switch(context, self, complex_name, 
859                                             code_lines, temp_vars, 
860                                             space, prefix)
861
862     # all other data types can be evaluated one field a time
863     else: 
864         # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
865         if 'unserialize' == context and not self.var_followed_by_fixed_fields:
866             code_lines.append('%s    xcb_block_len += sizeof(%s);' % (space, self.c_type))
867             code_lines.append('%s    xcb_tmp += xcb_block_len;' % space)
868             _c_serialize_helper_insert_padding(context, code_lines, space)
869
870         count += _c_serialize_helper_fields(context, self, 
871                                             code_lines, temp_vars, 
872                                             space, prefix, False)
873         # "final padding"
874         count += _c_serialize_helper_insert_padding(context, code_lines, space)
875
876     return count    
877 # _c_serialize_helper()
878
879 def _c_serialize(self):
880     _h_setlevel(1)
881     _c_setlevel(1)
882
883     _hc('')
884     # _serialize() returns the buffer size
885     _hc('int')
886
887     variable_size_fields = 0
888     # maximum space required for type definition of function arguments
889     maxtypelen = 0
890     param_fields, wire_fields, params = get_serialize_params('serialize', self)
891
892     # determine N(variable_fields) 
893     for field in param_fields:
894         # if self.is_switch, treat all fields as if they are variable sized
895         if not field.type.fixed_size() or self.is_switch:
896             variable_size_fields += 1
897     # determine maxtypelen
898     for p in params:
899         maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))    
900
901     # write to .c/.h
902     for idx, p in enumerate(params):
903         line = ""
904         typespec, pointerspec, field_name = p
905         indent = ' '*(len(self.c_serialize_name)+2)
906         # p==0: function declaration
907         if 0==idx:
908             line = "%s (" % self.c_serialize_name
909             indent = ''
910         spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
911         line += "%s%s%s  %s%s  /**< */" % (indent, typespec, spacing, pointerspec, field_name)
912         if idx < len(params)-1:
913             _hc("%s," % line)
914         else:
915             _h("%s);" % line)
916             _c("%s)" % line)
917                 
918     _c('{')
919     if not self.is_switch:
920         _c('    %s *xcb_out = *_buffer;', self.c_type)
921         _c('    unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
922         _c('    unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
923     else:
924         _c('    char *xcb_out = *_buffer;')
925         _c('    unsigned int xcb_buffer_len = 0;')
926     if variable_size_fields > 0:        
927         code_lines = []
928         temp_vars = []
929         count =_c_serialize_helper('serialize', self, 
930                                    code_lines, temp_vars)
931         # update variable size fields 
932         variable_size_fields = count
933         temp_vars.append('    unsigned int xcb_pad = 0;')
934         temp_vars.append('    char xcb_pad0[3] = {0, 0, 0};') 
935         temp_vars.append('    struct iovec xcb_parts[%d];' % (count+1))
936         temp_vars.append('    unsigned int xcb_parts_idx = 0;')
937         temp_vars.append('    unsigned int xcb_block_len = 0;')
938         temp_vars.append('    unsigned int i;')
939         temp_vars.append('    char *xcb_tmp;')
940         for t in temp_vars:
941             _c(t)
942
943     _c('')
944     
945     if variable_size_fields > 0:        
946         for l in code_lines:
947             _c(l)
948     _c('')
949
950     # variable sized fields have been collected, now
951     # allocate memory and copy everything into a continuous memory area
952     _c('    if (NULL == xcb_out) {')
953     _c('        /* allocate memory  */')
954     _c('        *_buffer = malloc(xcb_buffer_len);')
955     _c('        xcb_out = *_buffer;')
956     _c('    }')
957     _c('')
958
959     # fill in struct members
960     if not self.is_switch:
961         if len(wire_fields)>0:
962             _c('    *xcb_out = *_aux;')
963
964     # copy variable size fields into the buffer
965     if variable_size_fields > 0:
966         # xcb_out padding
967         if not self.is_switch:
968             _c('    xcb_tmp = (char*)++xcb_out;')
969             _c('    xcb_tmp += xcb_out_pad;')
970         else:
971             _c('    xcb_tmp = xcb_out;')
972             
973         # variable sized fields
974         _c('    for(i=0; i<xcb_parts_idx; i++) {')
975         _c('        memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
976         _c('        xcb_tmp += xcb_parts[i].iov_len;')
977         _c('    }')
978     _c('')
979     _c('    return xcb_buffer_len;')
980     _c('}')
981 # _c_serialize()
982
983 def _c_unserialize(self):
984     _h_setlevel(1)
985     _c_setlevel(1)
986
987     # _unserialize()
988     _hc('')
989     # _unserialize() returns the buffer size as well
990     _hc('int')
991
992
993     variable_size_fields = 0
994     # maximum space required for type definition of function arguments
995     maxtypelen = 0
996     param_fields, wire_fields, params = get_serialize_params('unserialize', self)
997
998     # determine N(variable_fields) 
999     for field in param_fields:
1000         # if self.is_switch, treat all fields as if they are variable sized
1001         if not field.type.fixed_size() or self.is_switch:
1002             variable_size_fields += 1
1003     # determine maxtypelen
1004     for p in params:
1005         maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))    
1006
1007     # write to .c/.h
1008     for idx, p in enumerate(params):
1009         line = ""
1010         typespec, pointerspec, field_name = p
1011         indent = ' '*(len(self.c_unserialize_name)+2)
1012         # p==0: function declaration
1013         if 0==idx:
1014             line = "%s (" % self.c_unserialize_name
1015             indent = ''
1016         spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1017         line += "%s%s%s %s%s  /**< */" % (indent, typespec, spacing, pointerspec, field_name)
1018         if idx < len(params)-1:
1019             _hc("%s," % line)
1020         else:
1021             _h("%s);" % line)
1022             _c("%s)" % line)
1023                 
1024     _c('{')
1025     _c('    char *xcb_tmp = (char *)_buffer;')
1026     if not self.is_switch:
1027         if not self.var_followed_by_fixed_fields:
1028             _c('    const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1029         else:
1030             _c('    %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1031     _c('    unsigned int xcb_buffer_len = 0;')
1032     _c('    unsigned int xcb_block_len = 0;')
1033     _c('    unsigned int xcb_pad = 0;')
1034
1035     code_lines = []
1036     temp_vars = []
1037     _c_serialize_helper('unserialize', self, 
1038                         code_lines, temp_vars)
1039     for t in temp_vars:
1040         _c(t)
1041     _c('')
1042
1043     for l in code_lines:
1044         _c(l)
1045     _c('')
1046     if not self.is_switch:
1047         if self.var_followed_by_fixed_fields:
1048             _c('    free(_aux);')
1049
1050     _c('    return xcb_buffer_len;')
1051     _c('}')
1052 # _c_unserialize()
1053
1054 def _c_iterator_get_end(field, accum):
1055     '''
1056     Figures out what C code is needed to find the end of a variable-length structure field.
1057     For nested structures, recurses into its last variable-sized field.
1058     For lists, calls the end function
1059     '''
1060     if field.type.is_container:
1061         accum = field.c_accessor_name + '(' + accum + ')'
1062         # XXX there could be fixed-length fields at the end
1063         return _c_iterator_get_end(field.type.last_varsized_field, accum)
1064     if field.type.is_list:
1065         # XXX we can always use the first way
1066         if field.type.member.is_simple:
1067             return field.c_end_name + '(' + accum + ')'
1068         else:
1069             return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1070
1071 def _c_iterator(self, name):
1072     '''
1073     Declares the iterator structure and next/end functions for a given type.
1074     '''
1075     _h_setlevel(0)
1076     _h('')
1077     _h('/**')
1078     _h(' * @brief %s', self.c_iterator_type)
1079     _h(' **/')
1080     _h('typedef struct %s {', self.c_iterator_type)
1081     _h('    %s *data; /**<  */', self.c_type)
1082     _h('    int%s rem; /**<  */', ' ' * (len(self.c_type) - 2))
1083     _h('    int%s index; /**<  */', ' ' * (len(self.c_type) - 2))
1084     _h('} %s;', self.c_iterator_type)
1085
1086     _h_setlevel(1)
1087     _c_setlevel(1)
1088     _h('')
1089     _h('/**')
1090     _h(' * Get the next element of the iterator')
1091     _h(' * @param i Pointer to a %s', self.c_iterator_type)
1092     _h(' *')
1093     _h(' * Get the next element in the iterator. The member rem is')
1094     _h(' * decreased by one. The member data points to the next')
1095     _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1096     _h(' */')
1097     _c('')
1098     _hc('')
1099     _hc('/*****************************************************************************')
1100     _hc(' **')
1101     _hc(' ** void %s', self.c_next_name)
1102     _hc(' ** ')
1103     _hc(' ** @param %s *i', self.c_iterator_type)
1104     _hc(' ** @returns void')
1105     _hc(' **')
1106     _hc(' *****************************************************************************/')
1107     _hc(' ')
1108     _hc('void')
1109     _h('%s (%s *i  /**< */);', self.c_next_name, self.c_iterator_type)
1110     _c('%s (%s *i  /**< */)', self.c_next_name, self.c_iterator_type)
1111     _c('{')
1112
1113     if not self.fixed_size():
1114         _c('    %s *R = i->data;', self.c_type)
1115         if self.is_union:
1116             # FIXME - how to determine the size of a variable size union??
1117             _c('    /* FIXME - determine the size of the union %s */', self.c_type)
1118         else:
1119             _c('    xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1120             _c('    --i->rem;')
1121             _c('    i->data = (%s *) child.data;', self.c_type)
1122             _c('    i->index = child.index;')
1123     else:
1124         _c('    --i->rem;')
1125         _c('    ++i->data;')
1126         _c('    i->index += sizeof(%s);', self.c_type)
1127
1128     _c('}')
1129
1130     _h('')
1131     _h('/**')
1132     _h(' * Return the iterator pointing to the last element')
1133     _h(' * @param i An %s', self.c_iterator_type)
1134     _h(' * @return  The iterator pointing to the last element')
1135     _h(' *')
1136     _h(' * Set the current element in the iterator to the last element.')
1137     _h(' * The member rem is set to 0. The member data points to the')
1138     _h(' * last element.')
1139     _h(' */')
1140     _c('')
1141     _hc('')
1142     _hc('/*****************************************************************************')
1143     _hc(' **')
1144     _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1145     _hc(' ** ')
1146     _hc(' ** @param %s i', self.c_iterator_type)
1147     _hc(' ** @returns xcb_generic_iterator_t')
1148     _hc(' **')
1149     _hc(' *****************************************************************************/')
1150     _hc(' ')
1151     _hc('xcb_generic_iterator_t')
1152     _h('%s (%s i  /**< */);', self.c_end_name, self.c_iterator_type)
1153     _c('%s (%s i  /**< */)', self.c_end_name, self.c_iterator_type)
1154     _c('{')
1155     _c('    xcb_generic_iterator_t ret;')
1156
1157     if self.fixed_size():
1158         _c('    ret.data = i.data + i.rem;')
1159         _c('    ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1160         _c('    ret.rem = 0;')
1161     else:
1162         _c('    while(i.rem > 0)')
1163         _c('        %s(&i);', self.c_next_name)
1164         _c('    ret.data = i.data;')
1165         _c('    ret.rem = i.rem;')
1166         _c('    ret.index = i.index;')
1167
1168     _c('    return ret;')
1169     _c('}')
1170
1171 def _c_accessor_get_length(expr, prefix='', sep='->'):
1172     '''
1173     Figures out what C code is needed to get a length field.
1174     For fields that follow a variable-length field, use the accessor.
1175     Otherwise, just reference the structure field directly.
1176     '''
1177     prefarrow = '' if prefix == '' else prefix + sep
1178     
1179     if expr.lenfield != None and expr.lenfield.prev_varsized_field != None:
1180         # special case: variable and fixed size fields are intermixed
1181         retval = expr.lenfield.c_accessor_name + '(' + prefix + ')'
1182         if prefix in ('', '_aux'):
1183             prefix_str = '' if prefix=='' else '%s' % (prefarrow)
1184             retval = '%s%s' % (prefix_str, expr.lenfield_name)
1185         return retval
1186     elif expr.lenfield_name != None:
1187         if prefix.endswith(sep):
1188             return prefix + expr.lenfield_name
1189         else:
1190             return prefarrow + expr.lenfield_name
1191     else:
1192         return str(expr.nmemb)
1193
1194 def _c_accessor_get_expr(expr, prefix='', sep='->'):
1195     '''
1196     Figures out what C code is needed to get the length of a list field.
1197     Recurses for math operations.
1198     Returns bitcount for value-mask fields.
1199     Otherwise, uses the value of the length field.
1200     '''
1201     lenexp = _c_accessor_get_length(expr, prefix, sep)
1202
1203     if expr.op == '~':
1204         return '(' + '~' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1205     elif expr.op == 'popcount':
1206         return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1207     elif expr.op == 'enumref':
1208         enum_name = expr.lenfield_type.name
1209         constant_name = expr.lenfield_name
1210         c_name = _n(enum_name + (constant_name,)).upper()
1211         return c_name
1212     elif expr.op == 'sumof':
1213         # 1. locate the referenced list object
1214         list_obj = expr.lenfield_type
1215         field = None
1216         for f in expr.lenfield_parent.fields:
1217             if f.field_name == expr.lenfield_name:
1218                 field = f
1219                 break
1220         if field is None:
1221             raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1222         if prefix != '' and not prefix.endswith(sep):
1223             prefix += sep
1224         list_name = "%s%s" % (prefix, field.c_field_name)
1225         c_length_func = "%s(%s%s)" % (field.c_length_name, prefix, field.c_field_name)
1226         # FIXME
1227         c_length_func = _c_accessor_get_expr(field.type.expr, prefix='', sep='')
1228         return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1229     elif expr.op != None:
1230         return '(' + _c_accessor_get_expr(expr.lhs, prefix, sep) + ' ' + expr.op + ' ' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1231     elif expr.bitfield:
1232         return 'xcb_popcount(' + lenexp + ')'
1233     else:
1234         return lenexp + '/* bla */'
1235
1236 def _c_accessors_field(self, field):
1237     '''
1238     Declares the accessor functions for a non-list field that follows a variable-length field.
1239     '''
1240     if field.type.is_simple:
1241         _hc('')
1242         _hc('')
1243         _hc('/*****************************************************************************')
1244         _hc(' **')
1245         _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1246         _hc(' ** ')
1247         _hc(' ** @param const %s *R', self.c_type)
1248         _hc(' ** @returns %s', field.c_field_type)
1249         _hc(' **')
1250         _hc(' *****************************************************************************/')
1251         _hc(' ')
1252         _hc('%s', field.c_field_type)
1253         _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
1254         _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
1255         _c('{')
1256         if field.prev_varsized_field is None:
1257             _c('    return (%s *) (R + 1);', field.c_field_type)
1258         else:
1259             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1260             _c('    return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', 
1261                field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1262         _c('}')
1263     else:
1264         _hc('')
1265         _hc('')
1266         _hc('/*****************************************************************************')
1267         _hc(' **')
1268         _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1269         _hc(' ** ')
1270         _hc(' ** @param const %s *R', self.c_type)
1271         _hc(' ** @returns %s *', field.c_field_type)
1272         _hc(' **')
1273         _hc(' *****************************************************************************/')
1274         _hc(' ')
1275         _hc('%s *', field.c_field_type)
1276         _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
1277         _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
1278         _c('{')
1279         if field.prev_varsized_field is None:
1280             _c('    return (%s *) (R + 1);', field.c_field_type)
1281         else:
1282             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1283             _c('    return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', 
1284                field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1285         _c('}')
1286     
1287 def _c_accessors_list(self, field):
1288     '''
1289     Declares the accessor functions for a list field.
1290     Declares a direct-accessor function only if the list members are fixed size.
1291     Declares length and get-iterator functions always.
1292     '''
1293     list = field.type
1294
1295     _h_setlevel(1)
1296     _c_setlevel(1)
1297     if list.member.fixed_size():
1298         _hc('')
1299         _hc('')
1300         _hc('/*****************************************************************************')
1301         _hc(' **')
1302         _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1303         _hc(' ** ')
1304         _hc(' ** @param const %s *R', self.c_type)
1305         _hc(' ** @returns %s *', field.c_field_type)
1306         _hc(' **')
1307         _hc(' *****************************************************************************/')
1308         _hc(' ')
1309         _hc('%s *', field.c_field_type)
1310         _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
1311         _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
1312         _c('{')
1313
1314         if field.prev_varsized_field is None:
1315             _c('    return (%s *) (R + 1);', field.c_field_type)
1316         else:
1317             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1318             _c('    return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1319
1320         _c('}')
1321
1322     _hc('')
1323     _hc('')
1324     _hc('/*****************************************************************************')
1325     _hc(' **')
1326     _hc(' ** int %s', field.c_length_name)
1327     _hc(' ** ')
1328     _hc(' ** @param const %s *R', self.c_type)
1329     _hc(' ** @returns int')
1330     _hc(' **')
1331     _hc(' *****************************************************************************/')
1332     _hc(' ')
1333     _hc('int')
1334     _h('%s (const %s *R  /**< */);', field.c_length_name, self.c_type)
1335     _c('%s (const %s *R  /**< */)', field.c_length_name, self.c_type)
1336     _c('{')
1337     _c('    return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1338     _c('}')
1339
1340     if field.type.member.is_simple:
1341         _hc('')
1342         _hc('')
1343         _hc('/*****************************************************************************')
1344         _hc(' **')
1345         _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1346         _hc(' ** ')
1347         _hc(' ** @param const %s *R', self.c_type)
1348         _hc(' ** @returns xcb_generic_iterator_t')
1349         _hc(' **')
1350         _hc(' *****************************************************************************/')
1351         _hc(' ')
1352         _hc('xcb_generic_iterator_t')
1353         _h('%s (const %s *R  /**< */);', field.c_end_name, self.c_type)
1354         _c('%s (const %s *R  /**< */)', field.c_end_name, self.c_type)
1355         _c('{')
1356         _c('    xcb_generic_iterator_t i;')
1357
1358         if field.prev_varsized_field == None:
1359             _c('    i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1360         else:
1361             _c('    xcb_generic_iterator_t child = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1362             _c('    i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1363
1364         _c('    i.rem = 0;')
1365         _c('    i.index = (char *) i.data - (char *) R;')
1366         _c('    return i;')
1367         _c('}')
1368
1369     else:
1370         _hc('')
1371         _hc('')
1372         _hc('/*****************************************************************************')
1373         _hc(' **')
1374         _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1375         _hc(' ** ')
1376         _hc(' ** @param const %s *R', self.c_type)
1377         _hc(' ** @returns %s', field.c_iterator_type)
1378         _hc(' **')
1379         _hc(' *****************************************************************************/')
1380         _hc(' ')
1381         _hc('%s', field.c_iterator_type)
1382         _h('%s (const %s *R  /**< */);', field.c_iterator_name, self.c_type)
1383         _c('%s (const %s *R  /**< */)', field.c_iterator_name, self.c_type)
1384         _c('{')
1385         _c('    %s i;', field.c_iterator_type)
1386
1387         if field.prev_varsized_field == None:
1388             _c('    i.data = (%s *) (R + 1);', field.c_field_type)
1389         else:
1390             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1391             _c('    i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', field.c_field_type, field.c_field_type)
1392
1393         _c('    i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1394         _c('    i.index = (char *) i.data - (char *) R;')
1395         _c('    return i;')
1396         _c('}')
1397
1398 def _c_accessors(self, name, base):
1399     '''
1400     Declares the accessor functions for the fields of a structure.
1401     '''
1402     for field in self.fields:
1403         # no accessors for switch - 
1404         # switch always needs to be unserialized explicitly
1405         if self.is_switch:
1406             continue
1407         if field.type.is_list and not field.type.fixed_size():
1408             _c_accessors_list(self, field)
1409         elif field.prev_varsized_field != None or not field.type.fixed_size():
1410             _c_accessors_field(self, field)
1411
1412 def c_simple(self, name):
1413     '''
1414     Exported function that handles cardinal type declarations.
1415     These are types which are typedef'd to one of the CARDx's, char, float, etc.
1416     '''
1417     _c_type_setup(self, name, ())
1418
1419     if (self.name != name):
1420         # Typedef
1421         _h_setlevel(0)
1422         my_name = _t(name)
1423         _h('')
1424         _h('typedef %s %s;', _t(self.name), my_name)
1425
1426         # Iterator
1427         _c_iterator(self, name)
1428
1429 def _c_complex(self):
1430     '''
1431     Helper function for handling all structure types.
1432     Called for all structs, requests, replies, events, errors.
1433     '''
1434     _h_setlevel(0)
1435     _h('')
1436     _h('/**')
1437     _h(' * @brief %s', self.c_type)
1438     _h(' **/')
1439     _h('typedef %s %s {', self.c_container, self.c_type)
1440
1441     struct_fields = []
1442     maxtypelen = 0
1443
1444     varfield = None
1445     for field in self.fields:
1446         if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1447             varfield = field.c_field_name
1448             continue
1449 #        if varfield != None and not field.type.is_pad and field.wire:
1450 #            errmsg = '%s: warning: variable field %s followed by fixed field %s\n' % (self.c_type, varfield, field.c_field_name)
1451 #            sys.stderr.write(errmsg)
1452 #            sys.exit(1)
1453         if field.wire:
1454             struct_fields.append(field)
1455     
1456     for field in struct_fields:
1457         length = len(field.c_field_type)
1458         # account for '*' pointer_spec
1459         if not field.type.fixed_size():
1460             length += 1
1461         maxtypelen = max(maxtypelen, length)
1462
1463     def _c_complex_field(self, field, space=''):
1464         if (field.type.fixed_size() or 
1465             # in case of switch with switch children, don't make the field a pointer
1466             # necessary for unserialize to work
1467             (self.is_switch and field.type.is_switch)):
1468             spacing = ' ' * (maxtypelen - len(field.c_field_type))
1469             _h('%s    %s%s %s%s; /**<  */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1470         else:
1471             spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1472             _h('%s    %s%s *%s%s; /**<  */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1473
1474     if not self.is_switch:
1475         for field in struct_fields:
1476             _c_complex_field(self, field)
1477     else:
1478         for b in self.bitcases:
1479             space = ''
1480             if b.type.has_name:
1481                 _h('    struct _%s {', b.c_field_name)
1482                 space = '    '
1483             for field in b.type.fields:
1484                 _c_complex_field(self, field, space)
1485             if b.type.has_name:
1486                 _h('    } %s;', b.c_field_name)
1487
1488     _h('} %s;', self.c_type)
1489
1490 def c_struct(self, name):
1491     '''
1492     Exported function that handles structure declarations.
1493     '''
1494     _c_type_setup(self, name, ())
1495     _c_complex(self)
1496     _c_accessors(self, name, name)
1497     _c_iterator(self, name)
1498
1499 def c_union(self, name):
1500     '''
1501     Exported function that handles union declarations.
1502     '''
1503     _c_type_setup(self, name, ())
1504     _c_complex(self)
1505     _c_iterator(self, name)
1506
1507 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1508     '''
1509     Declares a request function.
1510     '''
1511
1512     # Four stunningly confusing possibilities here:
1513     #
1514     #   Void            Non-void
1515     # ------------------------------
1516     # "req"            "req"
1517     # 0 flag           CHECKED flag   Normal Mode
1518     # void_cookie      req_cookie
1519     # ------------------------------
1520     # "req_checked"    "req_unchecked"
1521     # CHECKED flag     0 flag         Abnormal Mode
1522     # void_cookie      req_cookie
1523     # ------------------------------
1524
1525
1526     # Whether we are _checked or _unchecked
1527     checked = void and not regular
1528     unchecked = not void and not regular
1529
1530     # What kind of cookie we return
1531     func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1532
1533     # What flag is passed to xcb_request
1534     func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1535
1536     # Global extension id variable or NULL for xproto
1537     func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1538
1539     # What our function name is
1540     func_name = self.c_request_name if not aux else self.c_aux_name
1541     if checked:
1542         func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1543     if unchecked:
1544         func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1545
1546     param_fields = []
1547     wire_fields = []
1548     maxtypelen = len('xcb_connection_t')
1549     serial_fields = []
1550
1551     for field in self.fields:
1552         if field.visible:
1553             # The field should appear as a call parameter
1554             param_fields.append(field)
1555         if field.wire and not field.auto:
1556             # We need to set the field up in the structure
1557             wire_fields.append(field)
1558         if field.type.need_serialize:
1559             serial_fields.append(field)
1560         
1561     for field in param_fields:
1562         c_field_const_type = field.c_field_const_type 
1563         if field.type.need_serialize and not aux:
1564             c_field_const_type = "const void"
1565         if len(c_field_const_type) > maxtypelen:
1566             maxtypelen = len(c_field_const_type)
1567
1568     _h_setlevel(1)
1569     _c_setlevel(1)
1570     _h('')
1571     _h('/**')
1572     _h(' * Delivers a request to the X server')
1573     _h(' * @param c The connection')
1574     _h(' * @return A cookie')
1575     _h(' *')
1576     _h(' * Delivers a request to the X server.')
1577     _h(' * ')
1578     if checked:
1579         _h(' * This form can be used only if the request will not cause')
1580         _h(' * a reply to be generated. Any returned error will be')
1581         _h(' * saved for handling by xcb_request_check().')
1582     if unchecked:
1583         _h(' * This form can be used only if the request will cause')
1584         _h(' * a reply to be generated. Any returned error will be')
1585         _h(' * placed in the event queue.')
1586     _h(' */')
1587     _c('')
1588     _hc('')
1589     _hc('/*****************************************************************************')
1590     _hc(' **')
1591     _hc(' ** %s %s', cookie_type, func_name)
1592     _hc(' ** ')
1593
1594     spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1595     _hc(' ** @param xcb_connection_t%s *c', spacing)
1596
1597     for field in param_fields:
1598         c_field_const_type = field.c_field_const_type 
1599         if field.type.need_serialize and not aux:
1600             c_field_const_type = "const void"
1601         spacing = ' ' * (maxtypelen - len(c_field_const_type))
1602         _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1603
1604     _hc(' ** @returns %s', cookie_type)
1605     _hc(' **')
1606     _hc(' *****************************************************************************/')
1607     _hc(' ')
1608     _hc('%s', cookie_type)
1609
1610     spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1611     comma = ',' if len(param_fields) else ');'
1612     _h('%s (xcb_connection_t%s *c  /**< */%s', func_name, spacing, comma)
1613     comma = ',' if len(param_fields) else ')'
1614     _c('%s (xcb_connection_t%s *c  /**< */%s', func_name, spacing, comma)
1615
1616     func_spacing = ' ' * (len(func_name) + 2)
1617     count = len(param_fields)
1618     for field in param_fields:
1619         count = count - 1
1620         c_field_const_type = field.c_field_const_type 
1621         c_pointer = field.c_pointer
1622         if field.type.need_serialize and not aux:
1623             c_field_const_type = "const void"
1624             c_pointer = '*'
1625         spacing = ' ' * (maxtypelen - len(c_field_const_type))
1626         comma = ',' if count else ');'
1627         _h('%s%s%s %s%s  /**< */%s', func_spacing, c_field_const_type, 
1628            spacing, c_pointer, field.c_field_name, comma)
1629         comma = ',' if count else ')'
1630         _c('%s%s%s %s%s  /**< */%s', func_spacing, c_field_const_type, 
1631            spacing, c_pointer, field.c_field_name, comma)
1632
1633     count = 2
1634     if not self.var_followed_by_fixed_fields:
1635         for field in param_fields:
1636             if not field.type.fixed_size():
1637                 count = count + 2
1638                 if field.type.need_serialize:
1639                     # _serialize() keeps track of padding automatically
1640                     count -= 1
1641     else:
1642         # there will be only one call to _serialize() and no need for additional padding
1643         count -= 1
1644
1645     _c('{')
1646     _c('    static const xcb_protocol_request_t xcb_req = {')
1647     _c('        /* count */ %d,', count)
1648     _c('        /* ext */ %s,', func_ext_global)
1649     _c('        /* opcode */ %s,', self.c_request_name.upper())
1650     _c('        /* isvoid */ %d', 1 if void else 0)
1651     _c('    };')
1652     _c('    ')
1653
1654     _c('    struct iovec xcb_parts[%d];', count + 2)
1655     _c('    %s xcb_ret;', func_cookie)
1656     _c('    %s xcb_out;', self.c_type)
1657     if self.var_followed_by_fixed_fields:
1658         _c('    /* in the protocol description, variable size fields are followed by fixed size fields */')
1659         
1660
1661     for idx, f in enumerate(serial_fields):
1662         if not aux:
1663             _c('    %s xcb_aux%d;' % (f.type.c_type, idx))
1664         else:
1665             _c('    void *xcb_aux%d = 0;' % (idx))
1666     _c('    ')
1667     _c('    printf("in function %s\\n");' % func_name)     
1668  
1669     # fixed size fields
1670     for field in wire_fields:
1671         if field.type.fixed_size():
1672             if field.type.is_expr:
1673                 _c('    xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr))
1674             elif field.type.is_pad:
1675                 if field.type.nmemb == 1:
1676                     _c('    xcb_out.%s = 0;', field.c_field_name)
1677                 else:
1678                     _c('    memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
1679             else:
1680                 if field.type.nmemb == 1:
1681                     _c('    xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
1682                 else:
1683                     _c('    memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
1684
1685     def get_serialize_args(type_obj, c_field_name, aux_var, unserialize=False):
1686         if unserialize:
1687             serialize_args = get_serialize_params('unserialize', type_obj, 
1688                                                   c_field_name, 
1689                                                   aux_var)[2]
1690         else:
1691             serialize_args = get_serialize_params('serialize', type_obj, 
1692                                                   aux_var, 
1693                                                   c_field_name)[2]
1694         serialize_args = reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
1695         return serialize_args
1696
1697     # calls in order to free dyn. all. memory
1698     free_calls = []
1699
1700     if not self.var_followed_by_fixed_fields:
1701         _c('    ')
1702         _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
1703         _c('    xcb_parts[2].iov_len = sizeof(xcb_out);')
1704         _c('    xcb_parts[3].iov_base = 0;')
1705         _c('    xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
1706
1707         count = 4
1708
1709         for field in param_fields:
1710             if not field.type.fixed_size():
1711                 _c('    /* %s %s */', field.type.c_type, field.c_field_name)
1712                 # default: simple cast to char *
1713                 if not field.type.need_serialize:
1714                     _c('    xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1715                     if field.type.is_list:
1716                         _c('    xcb_parts[%d].iov_len = %s * sizeof(%s);', count, 
1717                            _c_accessor_get_expr(field.type.expr), field.type.member.c_wiretype)
1718                     else:
1719                         # not supposed to happen
1720                         raise Exception("unhandled variable size field %s" % field.c_field_name)
1721                 else:
1722                     if not aux:
1723                         _c('    xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1724                     idx = serial_fields.index(field)
1725                     aux_var = '&xcb_aux%d' % idx
1726                     serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, not aux)
1727                     _c('    xcb_parts[%d].iov_len = ', count)
1728                     if aux:
1729                         _c('      %s (%s);', field.type.c_serialize_name, serialize_args)
1730                         _c('    xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
1731                         free_calls.append('    free(xcb_aux%d);' % idx)
1732                     else:
1733                         _c('      %s (%s);', field.type.c_unserialize_name, serialize_args)
1734
1735                 count += 1
1736                 if not field.type.need_serialize:
1737                     # the _serialize() function keeps track of padding automatically
1738                     _c('    xcb_parts[%d].iov_base = 0;', count)
1739                     _c('    xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
1740                     count += 1
1741
1742     # elif self.var_followed_by_fixed_fields:
1743     else:
1744         # call _serialize()
1745         buffer_var = 'xcb_parts[%d].iov_base' % count
1746         serialize_args = get_serialize_args(self, '&xcb_out', '&%s' % buffer_var, False)
1747         _c('    %s = (char *) 0;', buffer_var)
1748         _c('    xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
1749         free_calls.append('    free(xcb_parts[%d].iov_base);' % count)
1750         # no padding necessary - _serialize() keeps track of padding automatically
1751
1752     _c('    ')
1753     _c('    xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
1754     
1755     # free dyn. all. data, if any
1756     for f in free_calls:
1757         _c(f)
1758     _c('    return xcb_ret;')
1759     _c('}')
1760
1761 def _c_reply(self, name):
1762     '''
1763     Declares the function that returns the reply structure.
1764     '''
1765     spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
1766     spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
1767     spacing3 = ' ' * (len(self.c_reply_name) + 2)
1768
1769     _h('')
1770     _h('/**')
1771     _h(' * Return the reply')
1772     _h(' * @param c      The connection')
1773     _h(' * @param cookie The cookie')
1774     _h(' * @param e      The xcb_generic_error_t supplied')
1775     _h(' *')
1776     _h(' * Returns the reply of the request asked by')
1777     _h(' * ')
1778     _h(' * The parameter @p e supplied to this function must be NULL if')
1779     _h(' * %s(). is used.', self.c_unchecked_name)
1780     _h(' * Otherwise, it stores the error if any.')
1781     _h(' *')
1782     _h(' * The returned value must be freed by the caller using free().')
1783     _h(' */')
1784     _c('')
1785     _hc('')
1786     _hc('/*****************************************************************************')
1787     _hc(' **')
1788     _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
1789     _hc(' ** ')
1790     _hc(' ** @param xcb_connection_t%s  *c', spacing1)
1791     _hc(' ** @param %s   cookie', self.c_cookie_type)
1792     _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
1793     _hc(' ** @returns %s *', self.c_reply_type)
1794     _hc(' **')
1795     _hc(' *****************************************************************************/')
1796     _hc(' ')
1797     _hc('%s *', self.c_reply_type)
1798     _hc('%s (xcb_connection_t%s  *c  /**< */,', self.c_reply_name, spacing1)
1799     _hc('%s%s   cookie  /**< */,', spacing3, self.c_cookie_type)
1800     _h('%sxcb_generic_error_t%s **e  /**< */);', spacing3, spacing2)
1801     _c('%sxcb_generic_error_t%s **e  /**< */)', spacing3, spacing2)
1802     _c('{')
1803     _c('    return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
1804     _c('}')
1805
1806 def _c_opcode(name, opcode):
1807     '''
1808     Declares the opcode define for requests, events, and errors.
1809     '''
1810     _h_setlevel(0)
1811     _h('')
1812     _h('/** Opcode for %s. */', _n(name))
1813     _h('#define %s %s', _n(name).upper(), opcode)
1814     
1815 def _c_cookie(self, name):
1816     '''
1817     Declares the cookie type for a non-void request.
1818     '''
1819     _h_setlevel(0)
1820     _h('')
1821     _h('/**')
1822     _h(' * @brief %s', self.c_cookie_type)
1823     _h(' **/')
1824     _h('typedef struct %s {', self.c_cookie_type)
1825     _h('    unsigned int sequence; /**<  */')
1826     _h('} %s;', self.c_cookie_type)
1827
1828 def c_request(self, name):
1829     '''
1830     Exported function that handles request declarations.
1831     '''
1832     _c_type_setup(self, name, ('request',))
1833
1834     if self.reply:
1835         # Cookie type declaration
1836         _c_cookie(self, name)
1837
1838     # Opcode define
1839     _c_opcode(name, self.opcode)
1840
1841     # Request structure declaration
1842     _c_complex(self)
1843
1844     if self.reply:
1845         _c_type_setup(self.reply, name, ('reply',))
1846         # Reply structure definition
1847         _c_complex(self.reply)
1848         # Request prototypes
1849         _c_request_helper(self, name, self.c_cookie_type, False, True)
1850         _c_request_helper(self, name, self.c_cookie_type, False, False)
1851         if self.need_aux:
1852             _c_request_helper(self, name, self.c_cookie_type, False, True, True)
1853             _c_request_helper(self, name, self.c_cookie_type, False, False, True)
1854         # Reply accessors
1855         _c_accessors(self.reply, name + ('reply',), name)
1856         _c_reply(self, name)
1857     else:
1858         # Request prototypes
1859         _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
1860         _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
1861         if self.need_aux:
1862             _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
1863             _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
1864
1865
1866 def c_event(self, name):
1867     '''
1868     Exported function that handles event declarations.
1869     '''
1870     _c_type_setup(self, name, ('event',))
1871
1872     # Opcode define
1873     _c_opcode(name, self.opcodes[name])
1874
1875     if self.name == name:
1876         # Structure definition
1877         _c_complex(self)
1878     else:
1879         # Typedef
1880         _h('')
1881         _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
1882
1883 def c_error(self, name):
1884     '''
1885     Exported function that handles error declarations.
1886     '''
1887     _c_type_setup(self, name, ('error',))
1888
1889     # Opcode define
1890     _c_opcode(name, self.opcodes[name])
1891
1892     if self.name == name:
1893         # Structure definition
1894         _c_complex(self)
1895     else:
1896         # Typedef
1897         _h('')
1898         _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
1899
1900
1901 # Main routine starts here
1902
1903 # Must create an "output" dictionary before any xcbgen imports.
1904 output = {'open'    : c_open,
1905           'close'   : c_close,
1906           'simple'  : c_simple,
1907           'enum'    : c_enum,
1908           'struct'  : c_struct,
1909           'union'   : c_union,
1910           'request' : c_request,
1911           'event'   : c_event,
1912           'error'   : c_error, 
1913           }
1914
1915 # Boilerplate below this point
1916
1917 # Check for the argument that specifies path to the xcbgen python package.
1918 try:
1919     opts, args = getopt.getopt(sys.argv[1:], 'p:')
1920 except getopt.GetoptError, err:
1921     print str(err)
1922     print 'Usage: c_client.py [-p path] file.xml'
1923     sys.exit(1)
1924
1925 for (opt, arg) in opts:
1926     if opt == '-p':
1927         sys.path.append(arg)
1928
1929 # Import the module class
1930 try:
1931     from xcbgen.state import Module
1932 except ImportError:
1933     print ''
1934     print 'Failed to load the xcbgen Python package!'
1935     print 'Make sure that xcb/proto installed it on your Python path.'
1936     print 'If not, you will need to create a .pth file or define $PYTHONPATH'
1937     print 'to extend the path.'
1938     print 'Refer to the README file in xcb/proto for more info.'
1939     print ''
1940     raise
1941
1942 # Parse the xml header
1943 module = Module(args[0], output)
1944
1945 # Build type-registry and resolve type dependencies
1946 module.register()
1947 module.resolve()
1948
1949 # Output the code
1950 module.generate()