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