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