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