2 from xml.etree.cElementTree import *
3 from os.path import basename
8 # Jump to the bottom of this file for the main routine
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'}
14 _extension_special_cases = ['XPrint', 'XCMisc', 'BigRequests']
16 _cplusplus_annoyances = {'class' : '_class',
28 Writes the given line to the header file.
30 _hlines[_hlevel].append(fmt % args)
34 Writes the given line to the source file.
36 _clines[_clevel].append(fmt % args)
40 Writes the given line to both the header and source files.
45 # XXX See if this level thing is really necessary.
48 Changes the array that header lines are written to.
49 Supports writing different sections of the header file.
52 while len(_hlines) <= idx:
58 Changes the array that source lines are written to.
59 Supports writing to different sections of the source file.
62 while len(_clines) <= idx:
68 Does C-name conversion on a single string fragment.
69 Uses a regexp with some hard-coded special cases.
71 if str in _cname_special_cases:
72 return _cname_special_cases[str]
74 split = _cname_re.finditer(str)
75 name_parts = [match.group(0) for match in split]
76 return '_'.join(name_parts)
80 Checks for certain C++ reserved words and fixes them.
82 if str in _cplusplus_annoyances:
83 return _cplusplus_annoyances[str]
89 Does C-name conversion on an extension name.
90 Has some additional special cases on top of _n_item.
92 if str in _extension_special_cases:
93 return _n_item(str).lower()
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.
106 parts = [list[0], _n_item(list[1])]
108 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
110 parts = [list[0]] + [_n_item(i) for i in list[1:]]
111 return '_'.join(parts).lower()
115 Does C-name conversion on a tuple of strings representing a type.
116 Same as _n but adds a "_t" on the end.
121 parts = [list[0], _n_item(list[1]), 't']
123 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
125 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
126 return '_'.join(parts).lower()
131 Exported function that handles module open.
132 Opens the files and writes out the auto-generated comment, header file includes, etc.
136 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
138 # Build the type-name collision avoidance table used by c_enum
139 build_collision_table()
145 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
146 _hc(' * Edit at your peril.')
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)
156 _h('#ifndef __%s_H', _ns.header.upper())
157 _h('#define __%s_H', _ns.header.upper())
159 _h('#include "xcb.h"')
161 _c('#include <string.h>')
162 _c('#include <assert.h>')
163 _c('#include "xcbext.h"')
164 _c('#include "%s.h"', _ns.header)
167 for (n, h) in self.imports:
168 _hc('#include "%s.h"', h)
171 _h('#ifdef __cplusplus')
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)
180 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
183 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
187 Exported function that handles module close.
188 Writes out all the stored content lines, then closes the files.
195 _h('#ifdef __cplusplus')
207 hfile = open('%s.h' % _ns.header, 'w')
215 cfile = open('%s.c' % _ns.header, 'w')
222 def build_collision_table():
226 for v in module.types.values():
228 namecount[name] = (namecount.get(name) or 0) + 1
230 def c_enum(self, name):
232 Exported function that handles enum declarations.
236 if namecount[tname] > 1:
237 tname = _t(name + ('enum',))
241 _h('typedef enum %s {', tname)
243 count = len(self.values)
245 for (enam, eval) in self.values:
247 equals = ' = ' if eval != '' else ''
248 comma = ',' if count > 0 else ''
249 _h(' %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
253 def _c_type_setup(self, name, postfix):
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.
259 Recurses into child fields and list member types.
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
265 self.c_iterator_type = _t(name + ('iterator',))
266 self.c_next_name = _n(name + ('next',))
267 self.c_end_name = _n(name + ('end',))
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',))
276 if self.is_container:
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
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, ())
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 '*'
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
300 field.prev_varsized_field = prev_varsized_field
301 field.prev_varsized_offset = prev_varsized_offset
303 if prev_varsized_offset == 0:
304 first_field_after_varsized = field
305 field.first_field_after_varsized = first_field_after_varsized
307 if field.type.fixed_size():
308 prev_varsized_offset += field.type.size
310 self.last_varsized_field = field
311 prev_varsized_field = field
312 prev_varsized_offset = 0
314 def _c_iterator_get_end(field, accum):
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
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 + ')'
329 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
331 def _c_iterator(self, name):
333 Declares the iterator structure and next/end functions for a given type.
338 _h(' * @brief %s', self.c_iterator_type)
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)
350 _h(' * Get the next element of the iterator')
351 _h(' * @param i Pointer to a %s', self.c_iterator_type)
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)
359 _hc('/*****************************************************************************')
361 _hc(' ** void %s', self.c_next_name)
363 _hc(' ** @param %s *i', self.c_iterator_type)
364 _hc(' ** @returns void')
366 _hc(' *****************************************************************************/')
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)
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'))
377 _c(' i->data = (%s *) child.data;', self.c_type)
378 _c(' i->index = child.index;')
382 _c(' i->index += sizeof(%s);', self.c_type)
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')
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.')
398 _hc('/*****************************************************************************')
400 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
402 _hc(' ** @param %s i', self.c_iterator_type)
403 _hc(' ** @returns xcb_generic_iterator_t')
405 _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)
411 _c(' xcb_generic_iterator_t ret;')
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);')
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;')
427 def _c_accessor_get_length(expr, prefix=''):
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.
433 prefarrow = '' if prefix == '' else prefix + '->'
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
440 return str(expr.nmemb)
442 def _c_accessor_get_expr(expr, prefix=''):
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.
449 lenexp = _c_accessor_get_length(expr, prefix)
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) + ')'
456 return 'xcb_popcount(' + lenexp + ')'
460 def _c_accessors_field(self, field):
462 Declares the accessor functions for a non-list field that follows a variable-length field.
464 if field.type.is_simple:
467 _hc('/*****************************************************************************')
469 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
471 _hc(' ** @param const %s *R', self.c_type)
472 _hc(' ** @returns %s', field.c_field_type)
474 _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)
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)
486 _hc('/*****************************************************************************')
488 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
490 _hc(' ** @param const %s *R', self.c_type)
491 _hc(' ** @returns %s *', field.c_field_type)
493 _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)
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)
503 def _c_accessors_list(self, field):
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.
513 if list.member.fixed_size():
516 _hc('/*****************************************************************************')
518 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
520 _hc(' ** @param const %s *R', self.c_type)
521 _hc(' ** @returns %s *', field.c_field_type)
523 _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)
530 if field.prev_varsized_field == None:
531 _c(' return (%s *) (R + 1);', field.c_field_type)
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)
540 _hc('/*****************************************************************************')
542 _hc(' ** int %s', field.c_length_name)
544 _hc(' ** @param const %s *R', self.c_type)
545 _hc(' ** @returns int')
547 _hc(' *****************************************************************************/')
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)
553 _c(' return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
556 if field.type.member.is_simple:
559 _hc('/*****************************************************************************')
561 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
563 _hc(' ** @param const %s *R', self.c_type)
564 _hc(' ** @returns xcb_generic_iterator_t')
566 _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)
572 _c(' xcb_generic_iterator_t i;')
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'))
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'))
581 _c(' i.index = (char *) i.data - (char *) R;')
588 _hc('/*****************************************************************************')
590 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
592 _hc(' ** @param const %s *R', self.c_type)
593 _hc(' ** @returns %s', field.c_iterator_type)
595 _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)
601 _c(' %s i;', field.c_iterator_type)
603 if field.prev_varsized_field == None:
604 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
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)
609 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
610 _c(' i.index = (char *) i.data - (char *) R;')
614 def _c_accessors(self, name, base):
616 Declares the accessor functions for the fields of a structure.
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)
624 def c_simple(self, name):
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.
629 _c_type_setup(self, name, ())
631 if (self.name != name):
636 _h('typedef %s %s;', _t(self.name), my_name)
639 _c_iterator(self, name)
641 def _c_complex(self):
643 Helper function for handling all structure types.
644 Called for all structs, requests, replies, events, errors.
649 _h(' * @brief %s', self.c_type)
651 _h('typedef %s %s {', self.c_container, self.c_type)
657 for field in self.fields:
658 if not field.type.fixed_size():
659 varfield = field.c_field_name
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)
666 struct_fields.append(field)
668 for field in struct_fields:
669 if len(field.c_field_type) > maxtypelen:
670 maxtypelen = len(field.c_field_type)
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)
676 _h('} %s;', self.c_type)
678 def c_struct(self, name):
680 Exported function that handles structure declarations.
682 _c_type_setup(self, name, ())
684 _c_accessors(self, name, name)
685 _c_iterator(self, name)
687 def c_union(self, name):
689 Exported function that handles union declarations.
691 _c_type_setup(self, name, ())
693 _c_iterator(self, name)
695 def _c_request_helper(self, name, cookie_type, void, regular):
697 Declares a request function.
700 # Four stunningly confusing possibilities here:
703 # ------------------------------
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 # ------------------------------
714 # Whether we are _checked or _unchecked
715 checked = void and not regular
716 unchecked = not void and not regular
718 # What kind of cookie we return
719 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
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'
724 # Global extension id variable or NULL for xproto
725 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
727 # What our function name is
728 func_name = self.c_request_name
730 func_name = self.c_checked_name
732 func_name = self.c_unchecked_name
736 maxtypelen = len('xcb_connection_t')
738 for field in self.fields:
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)
746 for field in param_fields:
747 if len(field.c_field_const_type) > maxtypelen:
748 maxtypelen = len(field.c_field_const_type)
754 _h(' * Delivers a request to the X server')
755 _h(' * @param c The connection')
756 _h(' * @return A cookie')
758 _h(' * Delivers a request to the X server.')
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().')
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.')
771 _hc('/*****************************************************************************')
773 _hc(' ** %s %s', cookie_type, func_name)
776 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
777 _hc(' ** @param xcb_connection_t%s *c', spacing)
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)
783 _hc(' ** @returns %s', cookie_type)
785 _hc(' *****************************************************************************/')
787 _hc('%s', cookie_type)
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)
795 func_spacing = ' ' * (len(func_name) + 2)
796 count = len(param_fields)
797 for field in param_fields:
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)
806 for field in param_fields:
807 if not field.type.fixed_size():
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)
818 _c(' struct iovec xcb_parts[%d];', count + 2)
819 _c(' %s xcb_ret;', func_cookie)
820 _c(' %s xcb_out;', self.c_type)
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))
828 elif field.type.is_pad:
829 if field.type.nmemb == 1:
830 _c(' xcb_out.%s = 0;', field.c_field_name)
832 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
834 if field.type.nmemb == 1:
835 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
837 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
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;')
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)
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)
857 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
858 _c(' return xcb_ret;')
861 def _c_reply(self, name):
863 Declares the function that returns the reply structure.
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)
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')
876 _h(' * Returns the reply of the request asked by')
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.')
882 _h(' * The returned value must be freed by the caller using free().')
886 _hc('/*****************************************************************************')
888 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
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)
895 _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)
903 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
906 def _c_opcode(name, opcode):
908 Declares the opcode define for requests, events, and errors.
912 _h('/** Opcode for %s. */', _n(name))
913 _h('#define %s %s', _n(name).upper(), opcode)
915 def _c_cookie(self, name):
917 Declares the cookie type for a non-void request.
922 _h(' * @brief %s', self.c_cookie_type)
924 _h('typedef struct %s {', self.c_cookie_type)
925 _h(' unsigned int sequence; /**< */')
926 _h('} %s;', self.c_cookie_type)
928 def c_request(self, name):
930 Exported function that handles request declarations.
932 _c_type_setup(self, name, ('request',))
935 # Cookie type declaration
936 _c_cookie(self, name)
939 _c_opcode(name, self.opcode)
941 # Request structure declaration
945 _c_type_setup(self.reply, name, ('reply',))
946 # Reply structure definition
947 _c_complex(self.reply)
949 _c_request_helper(self, name, self.c_cookie_type, False, True)
950 _c_request_helper(self, name, self.c_cookie_type, False, False)
952 _c_accessors(self.reply, name + ('reply',), name)
956 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
957 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
959 def c_event(self, name):
961 Exported function that handles event declarations.
963 _c_type_setup(self, name, ('event',))
966 _c_opcode(name, self.opcodes[name])
968 if self.name == name:
969 # Structure definition
974 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
976 def c_error(self, name):
978 Exported function that handles error declarations.
980 _c_type_setup(self, name, ('error',))
983 _c_opcode(name, self.opcodes[name])
985 if self.name == name:
986 # Structure definition
991 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
994 # Main routine starts here
996 # Must create an "output" dictionary before any xcbgen imports.
997 output = {'open' : c_open,
1001 'struct' : c_struct,
1003 'request' : c_request,
1008 # Boilerplate below this point
1010 # Check for the argument that specifies path to the xcbgen python package.
1012 opts, args = getopt.getopt(sys.argv[1:], 'p:')
1013 except getopt.GetoptError, err:
1015 print 'Usage: c_client.py [-p path] file.xml'
1018 for (opt, arg) in opts:
1020 sys.path.append(arg)
1022 # Import the module class
1024 from xcbgen.state import Module
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.'
1035 # Parse the xml header
1036 module = Module(args[0], output)
1038 # Build type-registry and resolve type dependencies