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