added small fix to support trailing fixed fields; also warning for non-pad fixed...
[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
20 _cardinal_types = ['CARD8', 'uint8_t',
21                    'CARD16','uint16_t',
22                    'CARD32','uint32_t',
23                    'INT8', 'int8_t',
24                    'INT16', 'int16_t',
25                    'INT32', 'int32_t',
26                    'BYTE',
27                    'BOOL',
28                    'char',
29                    'void',
30                    'float',
31                    'double']
32 _hlines = []
33 _hlevel = 0
34 _clines = []
35 _clevel = 0
36 _ns = None
37
38 def _h(fmt, *args):
39     '''
40     Writes the given line to the header file.
41     '''
42     _hlines[_hlevel].append(fmt % args)
43     
44 def _c(fmt, *args):
45     '''
46     Writes the given line to the source file.
47     '''
48     _clines[_clevel].append(fmt % args)
49     
50 def _hc(fmt, *args):
51     '''
52     Writes the given line to both the header and source files.
53     '''
54     _h(fmt, *args)
55     _c(fmt, *args)
56
57 # XXX See if this level thing is really necessary.
58 def _h_setlevel(idx):
59     '''
60     Changes the array that header lines are written to.
61     Supports writing different sections of the header file.
62     '''
63     global _hlevel
64     while len(_hlines) <= idx:
65         _hlines.append([])
66     _hlevel = idx
67     
68 def _c_setlevel(idx):
69     '''
70     Changes the array that source lines are written to.
71     Supports writing to different sections of the source file.
72     '''
73     global _clevel
74     while len(_clines) <= idx:
75         _clines.append([])
76     _clevel = idx
77     
78 def _n_item(str):
79     '''
80     Does C-name conversion on a single string fragment.
81     Uses a regexp with some hard-coded special cases.
82     '''
83     if str in _cname_special_cases:
84         return _cname_special_cases[str]
85     else:
86         split = _cname_re.finditer(str)
87         name_parts = [match.group(0) for match in split]
88         return '_'.join(name_parts)
89     
90 def _cpp(str):
91     '''
92     Checks for certain C++ reserved words and fixes them.
93     '''
94     if str in _cplusplus_annoyances:
95         return _cplusplus_annoyances[str]
96     else:
97         return str
98
99 def _ext(str):
100     '''
101     Does C-name conversion on an extension name.
102     Has some additional special cases on top of _n_item.
103     '''
104     if str in _extension_special_cases:
105         return _n_item(str).lower()
106     else:
107         return str.lower()
108     
109 def _n(list):
110     '''
111     Does C-name conversion on a tuple of strings.
112     Different behavior depending on length of tuple, extension/not extension, etc.
113     Basically C-name converts the individual pieces, then joins with underscores.
114     '''
115     if len(list) == 1:
116         parts = list
117     elif len(list) == 2:
118         parts = [list[0], _n_item(list[1])]
119     elif _ns.is_ext:
120         parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
121     else:
122         parts = [list[0]] + [_n_item(i) for i in list[1:]]
123     return '_'.join(parts).lower()
124
125 def _t(list):
126     '''
127     Does C-name conversion on a tuple of strings representing a type.
128     Same as _n but adds a "_t" on the end.
129     '''
130     if len(list) == 1:
131         parts = list
132     elif len(list) == 2:
133         parts = [list[0], _n_item(list[1]), 't']
134     elif _ns.is_ext:
135         parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
136     else:
137         parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
138     return '_'.join(parts).lower()
139         
140
141 def c_open(self):
142     '''
143     Exported function that handles module open.
144     Opens the files and writes out the auto-generated comment, header file includes, etc.
145     '''
146     global _ns
147     _ns = self.namespace
148     _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
149
150     _h_setlevel(0)
151     _c_setlevel(0)
152
153     _hc('/*')
154     _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
155     _hc(' * Edit at your peril.')
156     _hc(' */')
157     _hc('')
158
159     _h('/**')
160     _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
161     _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
162     _h(' * @{')
163     _h(' **/')
164     _h('')
165     _h('#ifndef __%s_H', _ns.header.upper())
166     _h('#define __%s_H', _ns.header.upper())
167     _h('')
168     _h('#include "xcb.h"')
169
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('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
181         _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
182         _h('  ') #XXX
183         _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
184
185         _c('')
186         _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
187
188 def c_close(self):
189     '''
190     Exported function that handles module close.
191     Writes out all the stored content lines, then closes the files.
192     '''
193     _h_setlevel(2)
194     _c_setlevel(2)
195     _hc('')
196     _h('')
197     _h('#endif')
198     _h('')
199     _h('/**')
200     _h(' * @}')
201     _h(' */')
202
203     # Write header file
204     hfile = open('%s.h' % _ns.header, 'w')
205     for list in _hlines:
206         for line in list:
207             hfile.write(line)
208             hfile.write('\n')
209     hfile.close()
210
211     # Write source file
212     cfile = open('%s.c' % _ns.header, 'w')
213     for list in _clines:
214         for line in list:
215             cfile.write(line)
216             cfile.write('\n')
217     cfile.close()
218
219 def c_enum(self, name):
220     '''
221     Exported function that handles enum declarations.
222     '''
223     _h_setlevel(0)
224     _h('')
225     _h('typedef enum %s {', _t(name))
226
227     count = len(self.values)
228
229     for (enam, eval) in self.values:
230         count = count - 1
231         equals = ' = ' if eval != '' else ''
232         comma = ',' if count > 0 else ''
233         _h('    %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
234
235     _h('} %s;', _t(name))
236
237 def _c_type_setup(self, name, postfix):
238     '''
239     Sets up all the C-related state by adding additional data fields to
240     all Field and Type objects.  Here is where we figure out most of our
241     variable and function names.
242
243     Recurses into child fields and list member types.
244     '''
245     # Do all the various names in advance
246     self.c_type = _t(name + postfix)
247     self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
248
249     self.c_iterator_type = _t(name + ('iterator',))
250     self.c_next_name = _n(name + ('next',))
251     self.c_end_name = _n(name + ('end',))
252
253     self.c_request_name = _n(name)
254     self.c_checked_name = _n(name + ('checked',))
255     self.c_unchecked_name = _n(name + ('unchecked',))
256     self.c_reply_name = _n(name + ('reply',))
257     self.c_reply_type = _t(name + ('reply',))
258     self.c_cookie_type = _t(name + ('cookie',))
259
260     if self.is_container:
261
262         self.c_container = 'union' if self.is_union else 'struct'
263         prev_varsized_field = None
264         prev_varsized_offset = 0
265         first_field_after_varsized = None
266
267         for field in self.fields:
268             _c_type_setup(field.type, field.field_type, ())
269             if field.type.is_list:
270                 _c_type_setup(field.type.member, field.field_type, ())
271
272             field.c_field_type = _t(field.field_type)
273             field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
274             field.c_field_name = _cpp(field.field_name)
275             field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
276             field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
277
278             field.c_iterator_type = _t(field.field_type + ('iterator',))      # xcb_fieldtype_iterator_t
279             field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
280             field.c_accessor_name = _n(name + (field.field_name,))            # xcb_container_field
281             field.c_length_name = _n(name + (field.field_name, 'length'))     # xcb_container_field_length
282             field.c_end_name = _n(name + (field.field_name, 'end'))           # xcb_container_field_end
283
284             field.prev_varsized_field = prev_varsized_field
285             field.prev_varsized_offset = prev_varsized_offset
286
287             if prev_varsized_offset == 0:
288                 first_field_after_varsized = field
289             field.first_field_after_varsized = first_field_after_varsized
290
291             if field.type.fixed_size():
292                 prev_varsized_offset += field.type.size
293             else:
294                 self.last_varsized_field = field
295                 prev_varsized_field = field
296                 prev_varsized_offset = 0
297
298 def _c_iterator_get_end(field, accum):
299     '''
300     Figures out what C code is needed to find the end of a variable-length structure field.
301     For nested structures, recurses into its last variable-sized field.
302     For lists, calls the end function
303     '''
304     if field.type.is_container:
305         accum = field.c_accessor_name + '(' + accum + ')'
306         # XXX there could be fixed-length fields at the end
307         return _c_iterator_get_end(field.type.last_varsized_field, accum)
308     if field.type.is_list:
309         # XXX we can always use the first way
310         if field.type.c_type in _cardinal_types:
311             return field.c_end_name + '(' + accum + ')'
312         else:
313             return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
314
315 def _c_iterator(self, name):
316     '''
317     Declares the iterator structure and next/end functions for a given type.
318     '''
319     _h_setlevel(0)
320     _h('')
321     _h('/**')
322     _h(' * @brief %s', self.c_iterator_type)
323     _h(' **/')
324     _h('typedef struct %s {', self.c_iterator_type)
325     _h('    %s *data; /**<  */', self.c_type)
326     _h('    int%s rem; /**<  */', ' ' * (len(self.c_type) - 2))
327     _h('    int%s index; /**<  */', ' ' * (len(self.c_type) - 2))
328     _h('} %s;', self.c_iterator_type)
329
330     _h_setlevel(1)
331     _c_setlevel(1)
332     _h('')
333     _h('/**')
334     _h(' * Get the next element of the iterator')
335     _h(' * @param i Pointer to a %s', self.c_iterator_type)
336     _h(' *')
337     _h(' * Get the next element in the iterator. The member rem is')
338     _h(' * decreased by one. The member data points to the next')
339     _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
340     _h(' */')
341     _c('')
342     _hc('')
343     _hc('/*****************************************************************************')
344     _hc(' **')
345     _hc(' ** void %s', self.c_next_name)
346     _hc(' ** ')
347     _hc(' ** @param %s *i', self.c_iterator_type)
348     _hc(' ** @returns void')
349     _hc(' **')
350     _hc(' *****************************************************************************/')
351     _hc(' ')
352     _hc('void')
353     _h('%s (%s *i  /**< */);', self.c_next_name, self.c_iterator_type)
354     _c('%s (%s *i  /**< */)', self.c_next_name, self.c_iterator_type)
355     _c('{')
356
357     if not self.fixed_size():
358         _c('    %s *R = i->data;', self.c_type)
359         _c('    xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
360         _c('    --i->rem;')
361         _c('    i->data = (%s *) child.data;', self.c_type)
362         _c('    i->index = child.index;')
363     else:
364         _c('    --i->rem;')
365         _c('    ++i->data;')
366         _c('    i->index += sizeof(%s);', self.c_type)
367
368     _c('}')
369
370     _h('')
371     _h('/**')
372     _h(' * Return the iterator pointing to the last element')
373     _h(' * @param i An %s', self.c_iterator_type)
374     _h(' * @return  The iterator pointing to the last element')
375     _h(' *')
376     _h(' * Set the current element in the iterator to the last element.')
377     _h(' * The member rem is set to 0. The member data points to the')
378     _h(' * last element.')
379     _h(' */')
380     _c('')
381     _hc('')
382     _hc('/*****************************************************************************')
383     _hc(' **')
384     _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
385     _hc(' ** ')
386     _hc(' ** @param %s i', self.c_iterator_type)
387     _hc(' ** @returns xcb_generic_iterator_t')
388     _hc(' **')
389     _hc(' *****************************************************************************/')
390     _hc(' ')
391     _hc('xcb_generic_iterator_t')
392     _h('%s (%s i  /**< */);', self.c_end_name, self.c_iterator_type)
393     _c('%s (%s i  /**< */)', self.c_end_name, self.c_iterator_type)
394     _c('{')
395     _c('    xcb_generic_iterator_t ret;')
396
397     if self.fixed_size():
398         _c('    ret.data = i.data + i.rem;')
399         _c('    ret.index = i.index + ((char *) ret.data - (char *) i.data);')
400         _c('    ret.rem = 0;')
401     else:
402         _c('    while(i.rem > 0)')
403         _c('        %s(&i);', self.c_next_name)
404         _c('    ret.data = i.data;')
405         _c('    ret.rem = i.rem;')
406         _c('    ret.index = i.index;')
407
408     _c('    return ret;')
409     _c('}')
410
411 def _c_accessor_get_length(expr, prefix=''):
412     '''
413     Figures out what C code is needed to get a length field.
414     For fields that follow a variable-length field, use the accessor.
415     Otherwise, just reference the structure field directly.
416     '''
417     prefarrow = '' if prefix == '' else prefix + '->'
418
419     if expr.lenfield != None and expr.lenfield.prev_varsized_field != None:
420         return expr.lenfield.c_accessor_name + '(' + prefix + ')'
421     elif expr.lenfield_name != None:
422         return prefarrow + expr.lenfield_name
423     else:
424         return str(expr.nmemb)
425
426 def _c_accessor_get_expr(expr, prefix=''):
427     '''
428     Figures out what C code is needed to get the length of a list field.
429     Recurses for math operations.
430     Returns bitcount for value-mask fields.
431     Otherwise, uses the value of the length field.
432     '''
433     lenexp = _c_accessor_get_length(expr, prefix)
434
435     if expr.op != None:
436         return '(' + _c_accessor_get_expr(expr.lhs, prefix) + ' ' + expr.op + ' ' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
437     elif expr.bitfield:
438         return 'xcb_popcount(' + lenexp + ')'
439     else:
440         return lenexp
441
442 def _c_accessors_field(self, field):
443     '''
444     Declares the accessor functions for a non-list field that follows a variable-length field.
445     '''
446     if field.field_type[0] in _cardinal_types:
447         _hc('')
448         _hc('')
449         _hc('/*****************************************************************************')
450         _hc(' **')
451         _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
452         _hc(' ** ')
453         _hc(' ** @param const %s *R', self.c_type)
454         _hc(' ** @returns %s', field.c_field_type)
455         _hc(' **')
456         _hc(' *****************************************************************************/')
457         _hc(' ')
458         _hc('%s', field.c_field_type)
459         _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
460         _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
461         _c('{')
462         _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
463         _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)
464         _c('}')
465     else:
466         _hc('')
467         _hc('')
468         _hc('/*****************************************************************************')
469         _hc(' **')
470         _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
471         _hc(' ** ')
472         _hc(' ** @param const %s *R', self.c_type)
473         _hc(' ** @returns %s *', field.c_field_type)
474         _hc(' **')
475         _hc(' *****************************************************************************/')
476         _hc(' ')
477         _hc('%s *', field.c_field_type)
478         _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
479         _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
480         _c('{')
481         _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
482         _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)
483         _c('}')
484     
485 def _c_accessors_list(self, field):
486     '''
487     Declares the accessor functions for a list field.
488     Declares a direct-accessor function only if the list members are fixed size.
489     Declares length and get-iterator functions always.
490     '''
491     list = field.type
492
493     _h_setlevel(1)
494     _c_setlevel(1)
495     if list.member.fixed_size():
496         _hc('')
497         _hc('')
498         _hc('/*****************************************************************************')
499         _hc(' **')
500         _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
501         _hc(' ** ')
502         _hc(' ** @param const %s *R', self.c_type)
503         _hc(' ** @returns %s *', field.c_field_type)
504         _hc(' **')
505         _hc(' *****************************************************************************/')
506         _hc(' ')
507         _hc('%s *', field.c_field_type)
508         _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
509         _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
510         _c('{')
511
512         if field.prev_varsized_field == None:
513             _c('    return (%s *) (R + 1);', field.c_field_type)
514         else:
515             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
516             _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)
517
518         _c('}')
519
520     _hc('')
521     _hc('')
522     _hc('/*****************************************************************************')
523     _hc(' **')
524     _hc(' ** int %s', field.c_length_name)
525     _hc(' ** ')
526     _hc(' ** @param const %s *R', self.c_type)
527     _hc(' ** @returns int')
528     _hc(' **')
529     _hc(' *****************************************************************************/')
530     _hc(' ')
531     _hc('int')
532     _h('%s (const %s *R  /**< */);', field.c_length_name, self.c_type)
533     _c('%s (const %s *R  /**< */)', field.c_length_name, self.c_type)
534     _c('{')
535     _c('    return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
536     _c('}')
537
538     if field.field_type[0] in _cardinal_types:
539         _hc('')
540         _hc('')
541         _hc('/*****************************************************************************')
542         _hc(' **')
543         _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
544         _hc(' ** ')
545         _hc(' ** @param const %s *R', self.c_type)
546         _hc(' ** @returns xcb_generic_iterator_t')
547         _hc(' **')
548         _hc(' *****************************************************************************/')
549         _hc(' ')
550         _hc('xcb_generic_iterator_t')
551         _h('%s (const %s *R  /**< */);', field.c_end_name, self.c_type)
552         _c('%s (const %s *R  /**< */)', field.c_end_name, self.c_type)
553         _c('{')
554         _c('    xcb_generic_iterator_t i;')
555
556         if field.prev_varsized_field == None:
557             _c('    i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
558         else:
559             _c('    xcb_generic_iterator_t child = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
560             _c('    i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
561
562         _c('    i.rem = 0;')
563         _c('    i.index = (char *) i.data - (char *) R;')
564         _c('    return i;')
565         _c('}')
566
567     else:
568         _hc('')
569         _hc('')
570         _hc('/*****************************************************************************')
571         _hc(' **')
572         _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
573         _hc(' ** ')
574         _hc(' ** @param const %s *R', self.c_type)
575         _hc(' ** @returns %s', field.c_iterator_type)
576         _hc(' **')
577         _hc(' *****************************************************************************/')
578         _hc(' ')
579         _hc('%s', field.c_iterator_type)
580         _h('%s (const %s *R  /**< */);', field.c_iterator_name, self.c_type)
581         _c('%s (const %s *R  /**< */)', field.c_iterator_name, self.c_type)
582         _c('{')
583         _c('    %s i;', field.c_iterator_type)
584
585         if field.prev_varsized_field == None:
586             _c('    i.data = (%s *) (R + 1);', field.c_field_type)
587         else:
588             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
589             _c('    i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', field.c_field_type, field.c_field_type)
590
591         _c('    i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
592         _c('    i.index = (char *) i.data - (char *) R;')
593         _c('    return i;')
594         _c('}')
595
596 def _c_accessors(self, name, base):
597     '''
598     Declares the accessor functions for the fields of a structure.
599     '''
600     for field in self.fields:
601         if field.type.is_list and not field.type.fixed_size():
602             _c_accessors_list(self, field)
603         elif field.prev_varsized_field != None:
604             _c_accessors_field(self, field)
605
606 def c_simple(self, name):
607     '''
608     Exported function that handles cardinal type declarations.
609     These are types which are typedef'd to one of the CARDx's, char, float, etc.
610     '''
611     _c_type_setup(self, name, ())
612
613     if (self.name != name):
614         # Typedef
615         _h_setlevel(0)
616         my_name = _t(name)
617         _h('')
618         _h('typedef %s %s;', _t(self.name), my_name)
619
620         # Iterator
621         _c_iterator(self, name)
622
623 def _c_complex(self):
624     '''
625     Helper function for handling all structure types.
626     Called for all structs, requests, replies, events, errors.
627     '''
628     _h_setlevel(0)
629     _h('')
630     _h('/**')
631     _h(' * @brief %s', self.c_type)
632     _h(' **/')
633     _h('typedef %s %s {', self.c_container, self.c_type)
634
635     struct_fields = []
636     maxtypelen = 0
637
638     varfield = None
639     for field in self.fields:
640         if not field.type.fixed_size():
641             varfield = field.c_field_name
642             continue
643         if varfield != None and not field.type.is_pad:
644             errmsg = '%s: warning: variable field %s followed by fixed field %s\n' % (self.c_type, varfield, field.c_field_name)
645             sys.stderr.write(errmsg)
646             # sys.exit(1)
647         if field.wire:
648             struct_fields.append(field)
649         
650     for field in struct_fields:
651         if len(field.c_field_type) > maxtypelen:
652             maxtypelen = len(field.c_field_type)
653
654     for field in struct_fields:
655         spacing = ' ' * (maxtypelen - len(field.c_field_type))
656         _h('    %s%s %s%s; /**<  */', field.c_field_type, spacing, field.c_field_name, field.c_subscript)
657
658     _h('} %s;', self.c_type)
659
660 def c_struct(self, name):
661     '''
662     Exported function that handles structure declarations.
663     '''
664     _c_type_setup(self, name, ())
665     _c_complex(self)
666     _c_accessors(self, name, name)
667     _c_iterator(self, name)
668
669 def c_union(self, name):
670     '''
671     Exported function that handles union declarations.
672     '''
673     _c_type_setup(self, name, ())
674     _c_complex(self)
675     _c_iterator(self, name)
676
677 def _c_request_helper(self, name, cookie_type, void, regular):
678     '''
679     Declares a request function.
680     '''
681
682     # Four stunningly confusing possibilities here:
683     #
684     #   Void            Non-void
685     # ------------------------------
686     # "req"            "req"
687     # 0 flag           CHECKED flag   Normal Mode
688     # void_cookie      req_cookie
689     # ------------------------------
690     # "req_checked"    "req_unchecked"
691     # CHECKED flag     0 flag         Abnormal Mode
692     # void_cookie      req_cookie
693     # ------------------------------
694
695
696     # Whether we are _checked or _unchecked
697     checked = void and not regular
698     unchecked = not void and not regular
699
700     # What kind of cookie we return
701     func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
702
703     # What flag is passed to xcb_request
704     func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
705
706     # Global extension id variable or NULL for xproto
707     func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
708
709     # What our function name is
710     func_name = self.c_request_name
711     if checked:
712         func_name = self.c_checked_name
713     if unchecked:
714         func_name = self.c_unchecked_name
715
716     param_fields = []
717     wire_fields = []
718     maxtypelen = len('xcb_connection_t')
719
720     for field in self.fields:
721         if field.visible:
722             # The field should appear as a call parameter
723             param_fields.append(field)
724         if field.wire and not field.auto:
725             # We need to set the field up in the structure
726             wire_fields.append(field)
727         
728     for field in param_fields:
729         if len(field.c_field_const_type) > maxtypelen:
730             maxtypelen = len(field.c_field_const_type)
731
732     _h_setlevel(1)
733     _c_setlevel(1)
734     _h('')
735     _h('/**')
736     _h(' * Delivers a request to the X server')
737     _h(' * @param c The connection')
738     _h(' * @return A cookie')
739     _h(' *')
740     _h(' * Delivers a request to the X server.')
741     _h(' * ')
742     if checked:
743         _h(' * This form can be used only if the request will not cause')
744         _h(' * a reply to be generated. Any returned error will be')
745         _h(' * saved for handling by xcb_request_check().')
746     if unchecked:
747         _h(' * This form can be used only if the request will cause')
748         _h(' * a reply to be generated. Any returned error will be')
749         _h(' * placed in the event queue.')
750     _h(' */')
751     _c('')
752     _hc('')
753     _hc('/*****************************************************************************')
754     _hc(' **')
755     _hc(' ** %s %s', cookie_type, func_name)
756     _hc(' ** ')
757
758     spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
759     _hc(' ** @param xcb_connection_t%s *c', spacing)
760
761     for field in param_fields:
762         spacing = ' ' * (maxtypelen - len(field.c_field_const_type))
763         _hc(' ** @param %s%s %s%s', field.c_field_const_type, spacing, field.c_pointer, field.c_field_name)
764
765     _hc(' ** @returns %s', cookie_type)
766     _hc(' **')
767     _hc(' *****************************************************************************/')
768     _hc(' ')
769     _hc('%s', cookie_type)
770
771     spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
772     comma = ',' if len(param_fields) else ');'
773     _h('%s (xcb_connection_t%s *c  /**< */%s', func_name, spacing, comma)
774     comma = ',' if len(param_fields) else ')'
775     _c('%s (xcb_connection_t%s *c  /**< */%s', func_name, spacing, comma)
776
777     func_spacing = ' ' * (len(func_name) + 2)
778     count = len(param_fields)
779     for field in param_fields:
780         count = count - 1
781         spacing = ' ' * (maxtypelen - len(field.c_field_const_type))
782         comma = ',' if count else ');'
783         _h('%s%s%s %s%s  /**< */%s', func_spacing, field.c_field_const_type, spacing, field.c_pointer, field.c_field_name, comma)
784         comma = ',' if count else ')'
785         _c('%s%s%s %s%s  /**< */%s', func_spacing, field.c_field_const_type, spacing, field.c_pointer, field.c_field_name, comma)
786
787     count = 2
788     for field in param_fields:
789         if not field.type.fixed_size():
790             count = count + 2
791
792     _c('{')
793     _c('    static const xcb_protocol_request_t xcb_req = {')
794     _c('        /* count */ %d,', count)
795     _c('        /* ext */ %s,', func_ext_global)
796     _c('        /* opcode */ %s,', self.c_request_name.upper())
797     _c('        /* isvoid */ %d', 1 if void else 0)
798     _c('    };')
799     _c('    ')
800     _c('    struct iovec xcb_parts[%d];', count + 2)
801     _c('    %s xcb_ret;', func_cookie)
802     _c('    %s xcb_out;', self.c_type)
803     _c('    ')
804
805     for field in wire_fields:
806         if field.type.fixed_size():
807             if field.type.is_expr:
808                 _c('    xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr))
809
810             elif field.type.is_pad:
811                 if field.type.nmemb == 1:
812                     _c('    xcb_out.%s = 0;', field.c_field_name)
813                 else:
814                     _c('    memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
815             else:
816                 if field.type.nmemb == 1:
817                     _c('    xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
818                 else:
819                     _c('    memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
820
821     _c('    ')
822     _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
823     _c('    xcb_parts[2].iov_len = sizeof(xcb_out);')
824     _c('    xcb_parts[3].iov_base = 0;')
825     _c('    xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
826
827     count = 4
828     for field in param_fields:
829         if not field.type.fixed_size():
830             _c('    xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
831             if field.type.is_list:
832                 _c('    xcb_parts[%d].iov_len = %s * sizeof(%s);', count, _c_accessor_get_expr(field.type.expr), field.type.member.c_wiretype)
833             else:
834                 _c('    xcb_parts[%d].iov_len = %s * sizeof(%s);', count, 'Uh oh', field.type.c_wiretype)
835             _c('    xcb_parts[%d].iov_base = 0;', count + 1)
836             _c('    xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count + 1, count)
837             count = count + 2
838
839     _c('    xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
840     _c('    return xcb_ret;')
841     _c('}')
842
843 def _c_reply(self, name):
844     '''
845     Declares the function that returns the reply structure.
846     '''
847     spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
848     spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
849     spacing3 = ' ' * (len(self.c_reply_name) + 2)
850
851     _h('')
852     _h('/**')
853     _h(' * Return the reply')
854     _h(' * @param c      The connection')
855     _h(' * @param cookie The cookie')
856     _h(' * @param e      The xcb_generic_error_t supplied')
857     _h(' *')
858     _h(' * Returns the reply of the request asked by')
859     _h(' * ')
860     _h(' * The parameter @p e supplied to this function must be NULL if')
861     _h(' * %s(). is used.', self.c_unchecked_name)
862     _h(' * Otherwise, it stores the error if any.')
863     _h(' *')
864     _h(' * The returned value must be freed by the caller using free().')
865     _h(' */')
866     _c('')
867     _hc('')
868     _hc('/*****************************************************************************')
869     _hc(' **')
870     _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
871     _hc(' ** ')
872     _hc(' ** @param xcb_connection_t%s  *c', spacing1)
873     _hc(' ** @param %s   cookie', self.c_cookie_type)
874     _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
875     _hc(' ** @returns %s *', self.c_reply_type)
876     _hc(' **')
877     _hc(' *****************************************************************************/')
878     _hc(' ')
879     _hc('%s *', self.c_reply_type)
880     _hc('%s (xcb_connection_t%s  *c  /**< */,', self.c_reply_name, spacing1)
881     _hc('%s%s   cookie  /**< */,', spacing3, self.c_cookie_type)
882     _h('%sxcb_generic_error_t%s **e  /**< */);', spacing3, spacing2)
883     _c('%sxcb_generic_error_t%s **e  /**< */)', spacing3, spacing2)
884     _c('{')
885     _c('    return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
886     _c('}')
887
888 def _c_opcode(name, opcode):
889     '''
890     Declares the opcode define for requests, events, and errors.
891     '''
892     _h_setlevel(0)
893     _h('')
894     _h('/** Opcode for %s. */', _n(name))
895     _h('#define %s %s', _n(name).upper(), opcode)
896     
897 def _c_cookie(self, name):
898     '''
899     Declares the cookie type for a non-void request.
900     '''
901     _h_setlevel(0)
902     _h('')
903     _h('/**')
904     _h(' * @brief %s', self.c_cookie_type)
905     _h(' **/')
906     _h('typedef struct %s {', self.c_cookie_type)
907     _h('    unsigned int sequence; /**<  */')
908     _h('} %s;', self.c_cookie_type)
909
910 def c_request(self, name):
911     '''
912     Exported function that handles request declarations.
913     '''
914     _c_type_setup(self, name, ('request',))
915
916     if self.reply:
917         # Cookie type declaration
918         _c_cookie(self, name)
919
920     # Opcode define
921     _c_opcode(name, self.opcode)
922
923     # Request structure declaration
924     _c_complex(self)
925
926     if self.reply:
927         _c_type_setup(self.reply, name, ('reply',))
928         # Reply structure definition
929         _c_complex(self.reply)
930         # Request prototypes
931         _c_request_helper(self, name, self.c_cookie_type, False, True)
932         _c_request_helper(self, name, self.c_cookie_type, False, False)
933         # Reply accessors
934         _c_accessors(self.reply, name + ('reply',), name)
935         _c_reply(self, name)
936     else:
937         # Request prototypes
938         _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
939         _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
940
941 def c_event(self, name):
942     '''
943     Exported function that handles event declarations.
944     '''
945     _c_type_setup(self, name, ('event',))
946
947     # Opcode define
948     _c_opcode(name, self.opcodes[name])
949
950     if self.name == name:
951         # Structure definition
952         _c_complex(self)
953     else:
954         # Typedef
955         _h('')
956         _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
957
958 def c_error(self, name):
959     '''
960     Exported function that handles error declarations.
961     '''
962     _c_type_setup(self, name, ('error',))
963
964     # Opcode define
965     _c_opcode(name, self.opcodes[name])
966
967     if self.name == name:
968         # Structure definition
969         _c_complex(self)
970     else:
971         # Typedef
972         _h('')
973         _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
974
975
976 # Main routine starts here
977
978 # Must create an "output" dictionary before any xcbgen imports.
979 output = {'open'    : c_open,
980           'close'   : c_close,
981           'simple'  : c_simple,
982           'enum'    : c_enum,
983           'struct'  : c_struct,
984           'union'   : c_union,
985           'request' : c_request,
986           'event'   : c_event,
987           'error'   : c_error
988           }
989
990 # Boilerplate below this point
991
992 # Check for the argument that specifies path to the xcbgen python package.
993 try:
994     opts, args = getopt.getopt(sys.argv[1:], 'p:')
995 except getopt.GetoptError, err:
996     print str(err)
997     print 'Usage: c_client.py [-p path] file.xml'
998     sys.exit(1)
999
1000 for (opt, arg) in opts:
1001     if opt == '-p':
1002         sys.path.append(arg)
1003
1004 # Import the module class
1005 try:
1006     from xcbgen.state import Module
1007 except ImportError:
1008     print ''
1009     print 'Failed to load the xcbgen Python package!'
1010     print 'Make sure that xcb/proto installed it on your Python path.'
1011     print 'If not, you will need to create a .pth file or define $PYTHONPATH'
1012     print 'to extend the path.'
1013     print 'Refer to the README file in xcb/proto for more info.'
1014     print ''
1015     raise
1016
1017 # Parse the xml header
1018 module = Module(args[0], output)
1019
1020 # Build type-registry and resolve type dependencies
1021 module.register()
1022 module.resolve()
1023
1024 # Output the code
1025 module.generate()