Added generation of extern "C" for compatibility with C++
[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('#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 c_enum(self, name):
232     '''
233     Exported function that handles enum declarations.
234     '''
235     _h_setlevel(0)
236     _h('')
237     _h('typedef enum %s {', _t(name))
238
239     count = len(self.values)
240
241     for (enam, eval) in self.values:
242         count = count - 1
243         equals = ' = ' if eval != '' else ''
244         comma = ',' if count > 0 else ''
245         _h('    %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
246
247     _h('} %s;', _t(name))
248
249 def _c_type_setup(self, name, postfix):
250     '''
251     Sets up all the C-related state by adding additional data fields to
252     all Field and Type objects.  Here is where we figure out most of our
253     variable and function names.
254
255     Recurses into child fields and list member types.
256     '''
257     # Do all the various names in advance
258     self.c_type = _t(name + postfix)
259     self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
260
261     self.c_iterator_type = _t(name + ('iterator',))
262     self.c_next_name = _n(name + ('next',))
263     self.c_end_name = _n(name + ('end',))
264
265     self.c_request_name = _n(name)
266     self.c_checked_name = _n(name + ('checked',))
267     self.c_unchecked_name = _n(name + ('unchecked',))
268     self.c_reply_name = _n(name + ('reply',))
269     self.c_reply_type = _t(name + ('reply',))
270     self.c_cookie_type = _t(name + ('cookie',))
271
272     if self.is_container:
273
274         self.c_container = 'union' if self.is_union else 'struct'
275         prev_varsized_field = None
276         prev_varsized_offset = 0
277         first_field_after_varsized = None
278
279         for field in self.fields:
280             _c_type_setup(field.type, field.field_type, ())
281             if field.type.is_list:
282                 _c_type_setup(field.type.member, field.field_type, ())
283
284             field.c_field_type = _t(field.field_type)
285             field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
286             field.c_field_name = _cpp(field.field_name)
287             field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
288             field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
289
290             field.c_iterator_type = _t(field.field_type + ('iterator',))      # xcb_fieldtype_iterator_t
291             field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
292             field.c_accessor_name = _n(name + (field.field_name,))            # xcb_container_field
293             field.c_length_name = _n(name + (field.field_name, 'length'))     # xcb_container_field_length
294             field.c_end_name = _n(name + (field.field_name, 'end'))           # xcb_container_field_end
295
296             field.prev_varsized_field = prev_varsized_field
297             field.prev_varsized_offset = prev_varsized_offset
298
299             if prev_varsized_offset == 0:
300                 first_field_after_varsized = field
301             field.first_field_after_varsized = first_field_after_varsized
302
303             if field.type.fixed_size():
304                 prev_varsized_offset += field.type.size
305             else:
306                 self.last_varsized_field = field
307                 prev_varsized_field = field
308                 prev_varsized_offset = 0
309
310 def _c_iterator_get_end(field, accum):
311     '''
312     Figures out what C code is needed to find the end of a variable-length structure field.
313     For nested structures, recurses into its last variable-sized field.
314     For lists, calls the end function
315     '''
316     if field.type.is_container:
317         accum = field.c_accessor_name + '(' + accum + ')'
318         # XXX there could be fixed-length fields at the end
319         return _c_iterator_get_end(field.type.last_varsized_field, accum)
320     if field.type.is_list:
321         # XXX we can always use the first way
322         if field.type.c_type in _cardinal_types:
323             return field.c_end_name + '(' + accum + ')'
324         else:
325             return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
326
327 def _c_iterator(self, name):
328     '''
329     Declares the iterator structure and next/end functions for a given type.
330     '''
331     _h_setlevel(0)
332     _h('')
333     _h('/**')
334     _h(' * @brief %s', self.c_iterator_type)
335     _h(' **/')
336     _h('typedef struct %s {', self.c_iterator_type)
337     _h('    %s *data; /**<  */', self.c_type)
338     _h('    int%s rem; /**<  */', ' ' * (len(self.c_type) - 2))
339     _h('    int%s index; /**<  */', ' ' * (len(self.c_type) - 2))
340     _h('} %s;', self.c_iterator_type)
341
342     _h_setlevel(1)
343     _c_setlevel(1)
344     _h('')
345     _h('/**')
346     _h(' * Get the next element of the iterator')
347     _h(' * @param i Pointer to a %s', self.c_iterator_type)
348     _h(' *')
349     _h(' * Get the next element in the iterator. The member rem is')
350     _h(' * decreased by one. The member data points to the next')
351     _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
352     _h(' */')
353     _c('')
354     _hc('')
355     _hc('/*****************************************************************************')
356     _hc(' **')
357     _hc(' ** void %s', self.c_next_name)
358     _hc(' ** ')
359     _hc(' ** @param %s *i', self.c_iterator_type)
360     _hc(' ** @returns void')
361     _hc(' **')
362     _hc(' *****************************************************************************/')
363     _hc(' ')
364     _hc('void')
365     _h('%s (%s *i  /**< */);', self.c_next_name, self.c_iterator_type)
366     _c('%s (%s *i  /**< */)', self.c_next_name, self.c_iterator_type)
367     _c('{')
368
369     if not self.fixed_size():
370         _c('    %s *R = i->data;', self.c_type)
371         _c('    xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
372         _c('    --i->rem;')
373         _c('    i->data = (%s *) child.data;', self.c_type)
374         _c('    i->index = child.index;')
375     else:
376         _c('    --i->rem;')
377         _c('    ++i->data;')
378         _c('    i->index += sizeof(%s);', self.c_type)
379
380     _c('}')
381
382     _h('')
383     _h('/**')
384     _h(' * Return the iterator pointing to the last element')
385     _h(' * @param i An %s', self.c_iterator_type)
386     _h(' * @return  The iterator pointing to the last element')
387     _h(' *')
388     _h(' * Set the current element in the iterator to the last element.')
389     _h(' * The member rem is set to 0. The member data points to the')
390     _h(' * last element.')
391     _h(' */')
392     _c('')
393     _hc('')
394     _hc('/*****************************************************************************')
395     _hc(' **')
396     _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
397     _hc(' ** ')
398     _hc(' ** @param %s i', self.c_iterator_type)
399     _hc(' ** @returns xcb_generic_iterator_t')
400     _hc(' **')
401     _hc(' *****************************************************************************/')
402     _hc(' ')
403     _hc('xcb_generic_iterator_t')
404     _h('%s (%s i  /**< */);', self.c_end_name, self.c_iterator_type)
405     _c('%s (%s i  /**< */)', self.c_end_name, self.c_iterator_type)
406     _c('{')
407     _c('    xcb_generic_iterator_t ret;')
408
409     if self.fixed_size():
410         _c('    ret.data = i.data + i.rem;')
411         _c('    ret.index = i.index + ((char *) ret.data - (char *) i.data);')
412         _c('    ret.rem = 0;')
413     else:
414         _c('    while(i.rem > 0)')
415         _c('        %s(&i);', self.c_next_name)
416         _c('    ret.data = i.data;')
417         _c('    ret.rem = i.rem;')
418         _c('    ret.index = i.index;')
419
420     _c('    return ret;')
421     _c('}')
422
423 def _c_accessor_get_length(expr, prefix=''):
424     '''
425     Figures out what C code is needed to get a length field.
426     For fields that follow a variable-length field, use the accessor.
427     Otherwise, just reference the structure field directly.
428     '''
429     prefarrow = '' if prefix == '' else prefix + '->'
430
431     if expr.lenfield != None and expr.lenfield.prev_varsized_field != None:
432         return expr.lenfield.c_accessor_name + '(' + prefix + ')'
433     elif expr.lenfield_name != None:
434         return prefarrow + expr.lenfield_name
435     else:
436         return str(expr.nmemb)
437
438 def _c_accessor_get_expr(expr, prefix=''):
439     '''
440     Figures out what C code is needed to get the length of a list field.
441     Recurses for math operations.
442     Returns bitcount for value-mask fields.
443     Otherwise, uses the value of the length field.
444     '''
445     lenexp = _c_accessor_get_length(expr, prefix)
446
447     if expr.op != None:
448         return '(' + _c_accessor_get_expr(expr.lhs, prefix) + ' ' + expr.op + ' ' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
449     elif expr.bitfield:
450         return 'xcb_popcount(' + lenexp + ')'
451     else:
452         return lenexp
453
454 def _c_accessors_field(self, field):
455     '''
456     Declares the accessor functions for a non-list field that follows a variable-length field.
457     '''
458     if field.field_type[0] in _cardinal_types:
459         _hc('')
460         _hc('')
461         _hc('/*****************************************************************************')
462         _hc(' **')
463         _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
464         _hc(' ** ')
465         _hc(' ** @param const %s *R', self.c_type)
466         _hc(' ** @returns %s', field.c_field_type)
467         _hc(' **')
468         _hc(' *****************************************************************************/')
469         _hc(' ')
470         _hc('%s', field.c_field_type)
471         _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
472         _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
473         _c('{')
474         _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
475         _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)
476         _c('}')
477     else:
478         _hc('')
479         _hc('')
480         _hc('/*****************************************************************************')
481         _hc(' **')
482         _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
483         _hc(' ** ')
484         _hc(' ** @param const %s *R', self.c_type)
485         _hc(' ** @returns %s *', field.c_field_type)
486         _hc(' **')
487         _hc(' *****************************************************************************/')
488         _hc(' ')
489         _hc('%s *', field.c_field_type)
490         _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
491         _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
492         _c('{')
493         _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
494         _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)
495         _c('}')
496     
497 def _c_accessors_list(self, field):
498     '''
499     Declares the accessor functions for a list field.
500     Declares a direct-accessor function only if the list members are fixed size.
501     Declares length and get-iterator functions always.
502     '''
503     list = field.type
504
505     _h_setlevel(1)
506     _c_setlevel(1)
507     if list.member.fixed_size():
508         _hc('')
509         _hc('')
510         _hc('/*****************************************************************************')
511         _hc(' **')
512         _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
513         _hc(' ** ')
514         _hc(' ** @param const %s *R', self.c_type)
515         _hc(' ** @returns %s *', field.c_field_type)
516         _hc(' **')
517         _hc(' *****************************************************************************/')
518         _hc(' ')
519         _hc('%s *', field.c_field_type)
520         _h('%s (const %s *R  /**< */);', field.c_accessor_name, self.c_type)
521         _c('%s (const %s *R  /**< */)', field.c_accessor_name, self.c_type)
522         _c('{')
523
524         if field.prev_varsized_field == None:
525             _c('    return (%s *) (R + 1);', field.c_field_type)
526         else:
527             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
528             _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)
529
530         _c('}')
531
532     _hc('')
533     _hc('')
534     _hc('/*****************************************************************************')
535     _hc(' **')
536     _hc(' ** int %s', field.c_length_name)
537     _hc(' ** ')
538     _hc(' ** @param const %s *R', self.c_type)
539     _hc(' ** @returns int')
540     _hc(' **')
541     _hc(' *****************************************************************************/')
542     _hc(' ')
543     _hc('int')
544     _h('%s (const %s *R  /**< */);', field.c_length_name, self.c_type)
545     _c('%s (const %s *R  /**< */)', field.c_length_name, self.c_type)
546     _c('{')
547     _c('    return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
548     _c('}')
549
550     if field.field_type[0] in _cardinal_types:
551         _hc('')
552         _hc('')
553         _hc('/*****************************************************************************')
554         _hc(' **')
555         _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
556         _hc(' ** ')
557         _hc(' ** @param const %s *R', self.c_type)
558         _hc(' ** @returns xcb_generic_iterator_t')
559         _hc(' **')
560         _hc(' *****************************************************************************/')
561         _hc(' ')
562         _hc('xcb_generic_iterator_t')
563         _h('%s (const %s *R  /**< */);', field.c_end_name, self.c_type)
564         _c('%s (const %s *R  /**< */)', field.c_end_name, self.c_type)
565         _c('{')
566         _c('    xcb_generic_iterator_t i;')
567
568         if field.prev_varsized_field == None:
569             _c('    i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
570         else:
571             _c('    xcb_generic_iterator_t child = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
572             _c('    i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
573
574         _c('    i.rem = 0;')
575         _c('    i.index = (char *) i.data - (char *) R;')
576         _c('    return i;')
577         _c('}')
578
579     else:
580         _hc('')
581         _hc('')
582         _hc('/*****************************************************************************')
583         _hc(' **')
584         _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
585         _hc(' ** ')
586         _hc(' ** @param const %s *R', self.c_type)
587         _hc(' ** @returns %s', field.c_iterator_type)
588         _hc(' **')
589         _hc(' *****************************************************************************/')
590         _hc(' ')
591         _hc('%s', field.c_iterator_type)
592         _h('%s (const %s *R  /**< */);', field.c_iterator_name, self.c_type)
593         _c('%s (const %s *R  /**< */)', field.c_iterator_name, self.c_type)
594         _c('{')
595         _c('    %s i;', field.c_iterator_type)
596
597         if field.prev_varsized_field == None:
598             _c('    i.data = (%s *) (R + 1);', field.c_field_type)
599         else:
600             _c('    xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
601             _c('    i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', field.c_field_type, field.c_field_type)
602
603         _c('    i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
604         _c('    i.index = (char *) i.data - (char *) R;')
605         _c('    return i;')
606         _c('}')
607
608 def _c_accessors(self, name, base):
609     '''
610     Declares the accessor functions for the fields of a structure.
611     '''
612     for field in self.fields:
613         if field.type.is_list and not field.type.fixed_size():
614             _c_accessors_list(self, field)
615         elif field.prev_varsized_field != None:
616             _c_accessors_field(self, field)
617
618 def c_simple(self, name):
619     '''
620     Exported function that handles cardinal type declarations.
621     These are types which are typedef'd to one of the CARDx's, char, float, etc.
622     '''
623     _c_type_setup(self, name, ())
624
625     if (self.name != name):
626         # Typedef
627         _h_setlevel(0)
628         my_name = _t(name)
629         _h('')
630         _h('typedef %s %s;', _t(self.name), my_name)
631
632         # Iterator
633         _c_iterator(self, name)
634
635 def _c_complex(self):
636     '''
637     Helper function for handling all structure types.
638     Called for all structs, requests, replies, events, errors.
639     '''
640     _h_setlevel(0)
641     _h('')
642     _h('/**')
643     _h(' * @brief %s', self.c_type)
644     _h(' **/')
645     _h('typedef %s %s {', self.c_container, self.c_type)
646
647     struct_fields = []
648     maxtypelen = 0
649
650     varfield = None
651     for field in self.fields:
652         if not field.type.fixed_size():
653             varfield = field.c_field_name
654             continue
655         if varfield != None and not field.type.is_pad and field.wire:
656             errmsg = '%s: warning: variable field %s followed by fixed field %s\n' % (self.c_type, varfield, field.c_field_name)
657             sys.stderr.write(errmsg)
658             # sys.exit(1)
659         if field.wire:
660             struct_fields.append(field)
661         
662     for field in struct_fields:
663         if len(field.c_field_type) > maxtypelen:
664             maxtypelen = len(field.c_field_type)
665
666     for field in struct_fields:
667         spacing = ' ' * (maxtypelen - len(field.c_field_type))
668         _h('    %s%s %s%s; /**<  */', field.c_field_type, spacing, field.c_field_name, field.c_subscript)
669
670     _h('} %s;', self.c_type)
671
672 def c_struct(self, name):
673     '''
674     Exported function that handles structure declarations.
675     '''
676     _c_type_setup(self, name, ())
677     _c_complex(self)
678     _c_accessors(self, name, name)
679     _c_iterator(self, name)
680
681 def c_union(self, name):
682     '''
683     Exported function that handles union declarations.
684     '''
685     _c_type_setup(self, name, ())
686     _c_complex(self)
687     _c_iterator(self, name)
688
689 def _c_request_helper(self, name, cookie_type, void, regular):
690     '''
691     Declares a request function.
692     '''
693
694     # Four stunningly confusing possibilities here:
695     #
696     #   Void            Non-void
697     # ------------------------------
698     # "req"            "req"
699     # 0 flag           CHECKED flag   Normal Mode
700     # void_cookie      req_cookie
701     # ------------------------------
702     # "req_checked"    "req_unchecked"
703     # CHECKED flag     0 flag         Abnormal Mode
704     # void_cookie      req_cookie
705     # ------------------------------
706
707
708     # Whether we are _checked or _unchecked
709     checked = void and not regular
710     unchecked = not void and not regular
711
712     # What kind of cookie we return
713     func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
714
715     # What flag is passed to xcb_request
716     func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
717
718     # Global extension id variable or NULL for xproto
719     func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
720
721     # What our function name is
722     func_name = self.c_request_name
723     if checked:
724         func_name = self.c_checked_name
725     if unchecked:
726         func_name = self.c_unchecked_name
727
728     param_fields = []
729     wire_fields = []
730     maxtypelen = len('xcb_connection_t')
731
732     for field in self.fields:
733         if field.visible:
734             # The field should appear as a call parameter
735             param_fields.append(field)
736         if field.wire and not field.auto:
737             # We need to set the field up in the structure
738             wire_fields.append(field)
739         
740     for field in param_fields:
741         if len(field.c_field_const_type) > maxtypelen:
742             maxtypelen = len(field.c_field_const_type)
743
744     _h_setlevel(1)
745     _c_setlevel(1)
746     _h('')
747     _h('/**')
748     _h(' * Delivers a request to the X server')
749     _h(' * @param c The connection')
750     _h(' * @return A cookie')
751     _h(' *')
752     _h(' * Delivers a request to the X server.')
753     _h(' * ')
754     if checked:
755         _h(' * This form can be used only if the request will not cause')
756         _h(' * a reply to be generated. Any returned error will be')
757         _h(' * saved for handling by xcb_request_check().')
758     if unchecked:
759         _h(' * This form can be used only if the request will cause')
760         _h(' * a reply to be generated. Any returned error will be')
761         _h(' * placed in the event queue.')
762     _h(' */')
763     _c('')
764     _hc('')
765     _hc('/*****************************************************************************')
766     _hc(' **')
767     _hc(' ** %s %s', cookie_type, func_name)
768     _hc(' ** ')
769
770     spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
771     _hc(' ** @param xcb_connection_t%s *c', spacing)
772
773     for field in param_fields:
774         spacing = ' ' * (maxtypelen - len(field.c_field_const_type))
775         _hc(' ** @param %s%s %s%s', field.c_field_const_type, spacing, field.c_pointer, field.c_field_name)
776
777     _hc(' ** @returns %s', cookie_type)
778     _hc(' **')
779     _hc(' *****************************************************************************/')
780     _hc(' ')
781     _hc('%s', cookie_type)
782
783     spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
784     comma = ',' if len(param_fields) else ');'
785     _h('%s (xcb_connection_t%s *c  /**< */%s', func_name, spacing, comma)
786     comma = ',' if len(param_fields) else ')'
787     _c('%s (xcb_connection_t%s *c  /**< */%s', func_name, spacing, comma)
788
789     func_spacing = ' ' * (len(func_name) + 2)
790     count = len(param_fields)
791     for field in param_fields:
792         count = count - 1
793         spacing = ' ' * (maxtypelen - len(field.c_field_const_type))
794         comma = ',' if count else ');'
795         _h('%s%s%s %s%s  /**< */%s', func_spacing, field.c_field_const_type, spacing, field.c_pointer, field.c_field_name, comma)
796         comma = ',' if count else ')'
797         _c('%s%s%s %s%s  /**< */%s', func_spacing, field.c_field_const_type, spacing, field.c_pointer, field.c_field_name, comma)
798
799     count = 2
800     for field in param_fields:
801         if not field.type.fixed_size():
802             count = count + 2
803
804     _c('{')
805     _c('    static const xcb_protocol_request_t xcb_req = {')
806     _c('        /* count */ %d,', count)
807     _c('        /* ext */ %s,', func_ext_global)
808     _c('        /* opcode */ %s,', self.c_request_name.upper())
809     _c('        /* isvoid */ %d', 1 if void else 0)
810     _c('    };')
811     _c('    ')
812     _c('    struct iovec xcb_parts[%d];', count + 2)
813     _c('    %s xcb_ret;', func_cookie)
814     _c('    %s xcb_out;', self.c_type)
815     _c('    ')
816
817     for field in wire_fields:
818         if field.type.fixed_size():
819             if field.type.is_expr:
820                 _c('    xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr))
821
822             elif field.type.is_pad:
823                 if field.type.nmemb == 1:
824                     _c('    xcb_out.%s = 0;', field.c_field_name)
825                 else:
826                     _c('    memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
827             else:
828                 if field.type.nmemb == 1:
829                     _c('    xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
830                 else:
831                     _c('    memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
832
833     _c('    ')
834     _c('    xcb_parts[2].iov_base = (char *) &xcb_out;')
835     _c('    xcb_parts[2].iov_len = sizeof(xcb_out);')
836     _c('    xcb_parts[3].iov_base = 0;')
837     _c('    xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
838
839     count = 4
840     for field in param_fields:
841         if not field.type.fixed_size():
842             _c('    xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
843             if field.type.is_list:
844                 _c('    xcb_parts[%d].iov_len = %s * sizeof(%s);', count, _c_accessor_get_expr(field.type.expr), field.type.member.c_wiretype)
845             else:
846                 _c('    xcb_parts[%d].iov_len = %s * sizeof(%s);', count, 'Uh oh', field.type.c_wiretype)
847             _c('    xcb_parts[%d].iov_base = 0;', count + 1)
848             _c('    xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count + 1, count)
849             count = count + 2
850
851     _c('    xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
852     _c('    return xcb_ret;')
853     _c('}')
854
855 def _c_reply(self, name):
856     '''
857     Declares the function that returns the reply structure.
858     '''
859     spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
860     spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
861     spacing3 = ' ' * (len(self.c_reply_name) + 2)
862
863     _h('')
864     _h('/**')
865     _h(' * Return the reply')
866     _h(' * @param c      The connection')
867     _h(' * @param cookie The cookie')
868     _h(' * @param e      The xcb_generic_error_t supplied')
869     _h(' *')
870     _h(' * Returns the reply of the request asked by')
871     _h(' * ')
872     _h(' * The parameter @p e supplied to this function must be NULL if')
873     _h(' * %s(). is used.', self.c_unchecked_name)
874     _h(' * Otherwise, it stores the error if any.')
875     _h(' *')
876     _h(' * The returned value must be freed by the caller using free().')
877     _h(' */')
878     _c('')
879     _hc('')
880     _hc('/*****************************************************************************')
881     _hc(' **')
882     _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
883     _hc(' ** ')
884     _hc(' ** @param xcb_connection_t%s  *c', spacing1)
885     _hc(' ** @param %s   cookie', self.c_cookie_type)
886     _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
887     _hc(' ** @returns %s *', self.c_reply_type)
888     _hc(' **')
889     _hc(' *****************************************************************************/')
890     _hc(' ')
891     _hc('%s *', self.c_reply_type)
892     _hc('%s (xcb_connection_t%s  *c  /**< */,', self.c_reply_name, spacing1)
893     _hc('%s%s   cookie  /**< */,', spacing3, self.c_cookie_type)
894     _h('%sxcb_generic_error_t%s **e  /**< */);', spacing3, spacing2)
895     _c('%sxcb_generic_error_t%s **e  /**< */)', spacing3, spacing2)
896     _c('{')
897     _c('    return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
898     _c('}')
899
900 def _c_opcode(name, opcode):
901     '''
902     Declares the opcode define for requests, events, and errors.
903     '''
904     _h_setlevel(0)
905     _h('')
906     _h('/** Opcode for %s. */', _n(name))
907     _h('#define %s %s', _n(name).upper(), opcode)
908     
909 def _c_cookie(self, name):
910     '''
911     Declares the cookie type for a non-void request.
912     '''
913     _h_setlevel(0)
914     _h('')
915     _h('/**')
916     _h(' * @brief %s', self.c_cookie_type)
917     _h(' **/')
918     _h('typedef struct %s {', self.c_cookie_type)
919     _h('    unsigned int sequence; /**<  */')
920     _h('} %s;', self.c_cookie_type)
921
922 def c_request(self, name):
923     '''
924     Exported function that handles request declarations.
925     '''
926     _c_type_setup(self, name, ('request',))
927
928     if self.reply:
929         # Cookie type declaration
930         _c_cookie(self, name)
931
932     # Opcode define
933     _c_opcode(name, self.opcode)
934
935     # Request structure declaration
936     _c_complex(self)
937
938     if self.reply:
939         _c_type_setup(self.reply, name, ('reply',))
940         # Reply structure definition
941         _c_complex(self.reply)
942         # Request prototypes
943         _c_request_helper(self, name, self.c_cookie_type, False, True)
944         _c_request_helper(self, name, self.c_cookie_type, False, False)
945         # Reply accessors
946         _c_accessors(self.reply, name + ('reply',), name)
947         _c_reply(self, name)
948     else:
949         # Request prototypes
950         _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
951         _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
952
953 def c_event(self, name):
954     '''
955     Exported function that handles event declarations.
956     '''
957     _c_type_setup(self, name, ('event',))
958
959     # Opcode define
960     _c_opcode(name, self.opcodes[name])
961
962     if self.name == name:
963         # Structure definition
964         _c_complex(self)
965     else:
966         # Typedef
967         _h('')
968         _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
969
970 def c_error(self, name):
971     '''
972     Exported function that handles error declarations.
973     '''
974     _c_type_setup(self, name, ('error',))
975
976     # Opcode define
977     _c_opcode(name, self.opcodes[name])
978
979     if self.name == name:
980         # Structure definition
981         _c_complex(self)
982     else:
983         # Typedef
984         _h('')
985         _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
986
987
988 # Main routine starts here
989
990 # Must create an "output" dictionary before any xcbgen imports.
991 output = {'open'    : c_open,
992           'close'   : c_close,
993           'simple'  : c_simple,
994           'enum'    : c_enum,
995           'struct'  : c_struct,
996           'union'   : c_union,
997           'request' : c_request,
998           'event'   : c_event,
999           'error'   : c_error
1000           }
1001
1002 # Boilerplate below this point
1003
1004 # Check for the argument that specifies path to the xcbgen python package.
1005 try:
1006     opts, args = getopt.getopt(sys.argv[1:], 'p:')
1007 except getopt.GetoptError, err:
1008     print str(err)
1009     print 'Usage: c_client.py [-p path] file.xml'
1010     sys.exit(1)
1011
1012 for (opt, arg) in opts:
1013     if opt == '-p':
1014         sys.path.append(arg)
1015
1016 # Import the module class
1017 try:
1018     from xcbgen.state import Module
1019 except ImportError:
1020     print ''
1021     print 'Failed to load the xcbgen Python package!'
1022     print 'Make sure that xcb/proto installed it on your Python path.'
1023     print 'If not, you will need to create a .pth file or define $PYTHONPATH'
1024     print 'to extend the path.'
1025     print 'Refer to the README file in xcb/proto for more info.'
1026     print ''
1027     raise
1028
1029 # Parse the xml header
1030 module = Module(args[0], output)
1031
1032 # Build type-registry and resolve type dependencies
1033 module.register()
1034 module.resolve()
1035
1036 # Output the code
1037 module.generate()