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',
26 # global variable to keep track of serializers
27 # due to weird dependencies, I see no way to do this more elegant at the moment
28 finished_serializers = []
32 Writes the given line to the header file.
34 _hlines[_hlevel].append(fmt % args)
38 Writes the given line to the source file.
40 _clines[_clevel].append(fmt % args)
44 Writes the given line to both the header and source files.
49 # XXX See if this level thing is really necessary.
52 Changes the array that header lines are written to.
53 Supports writing different sections of the header file.
56 while len(_hlines) <= idx:
62 Changes the array that source lines are written to.
63 Supports writing to different sections of the source file.
66 while len(_clines) <= idx:
72 Does C-name conversion on a single string fragment.
73 Uses a regexp with some hard-coded special cases.
75 if str in _cname_special_cases:
76 return _cname_special_cases[str]
78 split = _cname_re.finditer(str)
79 name_parts = [match.group(0) for match in split]
80 return '_'.join(name_parts)
84 Checks for certain C++ reserved words and fixes them.
86 if str in _cplusplus_annoyances:
87 return _cplusplus_annoyances[str]
93 Does C-name conversion on an extension name.
94 Has some additional special cases on top of _n_item.
96 if str in _extension_special_cases:
97 return _n_item(str).lower()
103 Does C-name conversion on a tuple of strings.
104 Different behavior depending on length of tuple, extension/not extension, etc.
105 Basically C-name converts the individual pieces, then joins with underscores.
110 parts = [list[0], _n_item(list[1])]
112 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
114 parts = [list[0]] + [_n_item(i) for i in list[1:]]
115 return '_'.join(parts).lower()
119 Does C-name conversion on a tuple of strings representing a type.
120 Same as _n but adds a "_t" on the end.
125 parts = [list[0], _n_item(list[1]), 't']
127 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
129 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
130 return '_'.join(parts).lower()
135 Exported function that handles module open.
136 Opens the files and writes out the auto-generated comment, header file includes, etc.
140 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
142 # Build the type-name collision avoidance table used by c_enum
143 build_collision_table()
149 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
150 _hc(' * Edit at your peril.')
155 _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
156 _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
160 _h('#ifndef __%s_H', _ns.header.upper())
161 _h('#define __%s_H', _ns.header.upper())
163 _h('#include "xcb.h"')
165 _c('#include <stdlib.h>')
166 _c('#include <string.h>')
167 _c('#include <assert.h>')
168 _c('#include "xcbext.h"')
169 _c('#include "%s.h"', _ns.header)
172 for (n, h) in self.imports:
173 _hc('#include "%s.h"', h)
176 _h('#ifdef __cplusplus')
182 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
183 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
185 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
188 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
192 Exported function that handles module close.
193 Writes out all the stored content lines, then closes the files.
200 _h('#ifdef __cplusplus')
212 hfile = open('%s.h' % _ns.header, 'w')
220 cfile = open('%s.c' % _ns.header, 'w')
227 def build_collision_table():
231 for v in module.types.values():
233 namecount[name] = (namecount.get(name) or 0) + 1
235 def c_enum(self, name):
237 Exported function that handles enum declarations.
241 if namecount[tname] > 1:
242 tname = _t(name + ('enum',))
246 _h('typedef enum %s {', tname)
248 count = len(self.values)
250 for (enam, eval) in self.values:
252 equals = ' = ' if eval != '' else ''
253 comma = ',' if count > 0 else ''
254 _h(' %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
258 def _c_type_setup(self, name, postfix):
260 Sets up all the C-related state by adding additional data fields to
261 all Field and Type objects. Here is where we figure out most of our
262 variable and function names.
264 Recurses into child fields and list member types.
266 # Do all the various names in advance
267 self.c_type = _t(name + postfix)
268 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
270 self.c_iterator_type = _t(name + ('iterator',))
271 self.c_next_name = _n(name + ('next',))
272 self.c_end_name = _n(name + ('end',))
274 self.c_request_name = _n(name)
275 self.c_checked_name = _n(name + ('checked',))
276 self.c_unchecked_name = _n(name + ('unchecked',))
277 self.c_reply_name = _n(name + ('reply',))
278 self.c_reply_type = _t(name + ('reply',))
279 self.c_cookie_type = _t(name + ('cookie',))
281 self.c_aux_name = _n(name + ('aux',))
282 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
283 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
284 self.c_serialize_name = _n(name + ('serialize',))
285 self.c_unserialize_name = _n(name + ('unserialize',))
286 if hasattr(self, 'reply'):
287 if self.reply is not None:
288 self.c_serialize_name = _n(name + ('reply', 'serialize'))
289 self.c_unserialize_name = _n(name + ('reply', 'unserialize'))
291 # whether a request or reply has a switch field
292 self.need_aux = False
293 self.need_serialize = False
295 self.need_serialize = True
296 for bitcase in self.bitcases:
297 _c_type_setup(bitcase.type, bitcase.field_type, ())
299 if self.is_container:
301 self.c_container = 'union' if self.is_union else 'struct'
302 prev_varsized_field = None
303 prev_varsized_offset = 0
304 first_field_after_varsized = None
306 for field in self.fields:
307 _c_type_setup(field.type, field.field_type, ())
308 if field.type.is_list:
309 _c_type_setup(field.type.member, field.field_type, ())
310 # FIXME - structures with variable sized members, sort out when serialize() is needed
311 if (field.type.nmemb is None): # and not field.type.member.fixed_size():
312 self.need_serialize = True
314 field.c_field_type = _t(field.field_type)
315 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
316 field.c_field_name = _cpp(field.field_name)
317 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
318 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
319 if field.type.is_switch:
320 field.c_pointer = '*'
321 field.c_field_const_type = 'const ' + field.c_field_type
324 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
325 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
326 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
327 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
328 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
330 field.prev_varsized_field = prev_varsized_field
331 field.prev_varsized_offset = prev_varsized_offset
333 if prev_varsized_offset == 0:
334 first_field_after_varsized = field
335 field.first_field_after_varsized = first_field_after_varsized
337 if field.type.fixed_size():
338 prev_varsized_offset += field.type.size
340 self.last_varsized_field = field
341 prev_varsized_field = field
342 prev_varsized_offset = 0
344 # as switch does never appear at toplevel,
345 # continue here with type construction
347 # special: switch C structs get pointer fields for variable-sized members
349 # FIXME: declare switch (un)packing functions
350 _c_accessors(self, name, name)
352 # FIXME - in case of request/reply, serialize() is not always needed
353 if self.need_serialize and not self.is_bitcase:
354 if self.c_serialize_name not in finished_serializers:
357 finished_serializers.append(self.c_serialize_name)
360 def get_request_fields(self):
364 for field in self.fields:
366 # the field should appear as a parameter in the function call
367 param_fields.append(field)
368 if field.wire and not field.auto:
369 if field.type.fixed_size() and not self.is_switch:
370 # field in the xcb_out structure
371 wire_fields.append(field)
372 # fields like 'pad0' are skipped!
374 return (param_fields, wire_fields)
375 # get_request_fields()
377 def get_switch_expr_fields(self):
378 # get the fields referenced by the switch expression
379 def get_expr_fields(expr):
381 if expr.lenfield_name is not None:
382 return [expr.lenfield_name]
385 return get_expr_fields(expr.rhs)
386 elif expr.op == 'popcount':
387 return get_expr_fields(expr.rhs)
388 elif expr.op == 'sumof':
389 return [expr.lenfield_name]
390 elif expr.op == 'enumref':
393 return get_expr_fields(expr.lhs) + get_expr_fields(expr.rhs)
396 # resolve the field names with the parent structure(s)
397 unresolved_fields = get_expr_fields(self.expr)
398 expr_fields = dict.fromkeys(unresolved_fields)
399 for p in reversed(self.parent):
400 parent_fields = dict((f.field_name, f) for f in p.fields)
401 for f in parent_fields.keys():
402 if f in unresolved_fields:
403 expr_fields[f] = parent_fields[f]
404 unresolved_fields.remove(f)
405 if len(unresolved_fields) == 0:
408 if None in expr_fields.values():
409 raise Exception("could not resolve all fields for <switch> %s" % self.name)
411 params = expr_fields.values()
413 # get_switch_expr_fields()
415 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
416 param_fields, wire_fields = get_request_fields(self)
418 param_fields = get_switch_expr_fields(self)
420 # _serialize function parameters
421 if 'serialize' == context:
422 params = [('void', '**', buffer_var)]
423 elif 'unserialize' == context:
424 params = [('const void', '*', buffer_var)]
426 # make sure all required length fields are present
427 for p in param_fields:
428 if p.visible and not p.wire and not p.auto:
429 typespec = p.c_field_type
431 params.append((typespec, pointerspec, p.c_field_name))
433 # parameter fields if any
435 for p in get_switch_expr_fields(self):
436 typespec = p.c_field_const_type
437 pointerspec = p.c_pointer
438 params.append((typespec, pointerspec, p.c_field_name))
440 # aux argument - structure to be serialized
441 if 'serialize' == context:
442 params.append(('const %s' % self.c_type, '*', aux_var))
443 elif 'unserialize' == context and self.is_switch:
444 params.append(('%s' % self.c_type, '*', aux_var))
445 if not self.is_switch and 'serialize' == context:
446 for p in param_fields:
447 if not p.type.fixed_size():
448 params.append((p.c_field_const_type, p.c_pointer, p.c_field_name))
449 return (param_fields, wire_fields, params)
450 # get_serialize_params()
452 def _c_field_mapping(context, complex_type):
453 def get_prefix(field):
455 if context in ('serialize', 'unserialize'):
456 if field.type.fixed_size() or complex_type.is_switch:
459 raise Exception("unknown context '%s' in c_field_mapping" % context)
462 def get_field_name(fields, complex_type, prefix=''):
463 for f in complex_type.fields:
465 prefix = get_prefix(f)
467 fname = "%s%s" % (prefix, f.c_field_name)
468 if fields.has_key(f.field_name):
470 raise Exception("field name %s has been registered before" % f.field_name)
471 fields[f.field_name] = (fname, f)
472 if f.type.is_container:
473 new_prefix = "%s%s" % (prefix, f.c_field_name)
474 new_prefix += "." if f.type.is_switch else "->"
475 get_field_name(fields, f.type, new_prefix)
478 # dict(field_name : (c_field_name, field))
480 get_field_name(fields, complex_type)
482 # switch: get the fields referenced by the switch expr as well
483 # these may not belong to any structure
484 if complex_type.is_switch:
486 # FIXME: fields += get_serialize_params(context, complex_type)
491 def _c_serialize_helper_prefix(prefix):
493 lenfield_prefix = "_aux"
496 lenfield_prefix += "->%s" % prefix
497 return (prefix_str, lenfield_prefix)
498 # _c_serialize_helper_prefix
500 def _c_serialize_helper_insert_padding(context, code_lines, space):
501 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
502 code_lines.append('%s /* padding */' % space)
503 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
504 code_lines.append('%s if (0 != xcb_pad) {' % space)
506 if 'serialize' == context:
507 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
508 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
509 code_lines.append('%s xcb_parts_idx++;' % space)
510 elif 'unserialize' == context:
511 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
513 code_lines.append('%s xcb_buffer_len += xcb_pad;' % space)
514 code_lines.append('%s xcb_pad = 0;' % space)
515 code_lines.append('%s }' % space)
516 code_lines.append('%s xcb_block_len = 0;' % space)
519 # _c_serialize_helper_insert_padding()
521 def _c_serialize_helper_switch(context, self, complex_name,
522 code_lines, temp_vars,
525 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
526 switch_expr = _c_accessor_get_expr(self.expr)
528 for b in self.bitcases:
529 bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix)
530 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
532 _c_serialize_helper_fields(context, b.type,
533 code_lines, temp_vars,
535 prefix="%s%s" % (prefix_str, complex_name),
537 code_lines.append(' }')
539 if 'serialize' == context:
540 count = _c_serialize_helper_insert_padding(context, code_lines, space)
541 if 'unserialize' == context:
543 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
544 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
547 # _c_serialize_helper_switch
549 def _c_serialize_helper_switch_field(self, field):
550 # switch is handled by this function as a special case
551 args = get_switch_expr_fields(field.type)
552 field_mapping = _c_field_mapping('unserialize', self)
555 c_field_names += "%s, " % field_mapping[a.field_name][0]
556 switch_field_name = field_mapping[field.field_name][0]
557 length = "%s(xcb_tmp, %s&%s)" % (field.type.c_unserialize_name,
558 c_field_names, switch_field_name)
560 # _c_serialize_helper_switch_field()
562 def _c_serialize_helper_list_field(context, self, field,
563 code_lines, temp_vars,
566 helper function for (un)serialize to cope with lists of variable length
568 expr = field.type.expr
569 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
570 param_fields, wire_fields, params = get_serialize_params('unserialize', self)
571 param_names = [p[2] for p in params]
573 # look if the list's lenfield is a struct member or a function argument
574 # special case: if the list has a length field, its name will returned
575 # unchanged by calling c_accessor_get_length(expr)
576 if expr.lenfield_name == _c_accessor_get_length(expr):
577 if expr.lenfield_name in param_names:
578 # the length field appears as separate argument in unserialize,
579 # so no need for a prefix
581 list_length = _c_accessor_get_expr(expr, lenfield_prefix)
583 # default: list with fixed size elements
584 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
585 # list with variable-sized elements
586 if field.type.size is None:
588 if 'unserialize' == context:
589 temp_vars.add(' unsigned int i;')
590 temp_vars.add(' unsigned int xcb_tmp_len;')
591 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
592 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
593 (space, field.type.c_unserialize_name))
594 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
595 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
596 code_lines.append("%s }" % space)
597 elif 'serialize' == context:
598 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
599 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
600 code_lines.append('%s for(i=0; i<%s; i++) {'
601 % (space, _c_accessor_get_expr(expr, lenfield_prefix)))
602 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_unserialize_name))
603 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
604 code_lines.append('%s }' % space)
605 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
608 # _c_serialize_helper_list_field()
610 def _c_serialize_helper_fields_fixed_size(context, self, field,
611 code_lines, temp_vars,
613 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
614 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
616 length = "sizeof(%s)" % field.c_field_type
618 if 'unserialize' == context:
619 value = ' _aux->%s = *(%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
621 if field.type.is_list:
622 raise Exception('list with fixed number of elemens unhandled in _unserialize()')
623 elif 'serialize' == context:
624 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
626 if field.type.is_expr:
627 # need to register a temporary variable for the expression
628 if field.type.c_type is None:
629 raise Exception("type for field '%s' (expression '%s') unkown" %
630 (field.field_name, _c_accessor_get_expr(field.type.expr)))
631 temp_vars.add(' %s xcb_expr_%s = %s;' % (field.type.c_type, field.field_name,
632 _c_accessor_get_expr(field.type.expr, prefix)))
633 value += "&xcb_expr_%s;" % field.field_name
635 elif field.type.is_pad:
636 if field.type.nmemb == 1:
639 value = ' memset(xcb_parts[xcb_parts_idx].iov_base, 0, %d);' % field.type.nmemb
640 length += "*%d" % field.type.nmemb
643 # non-list type with fixed size
644 if field.type.nmemb == 1:
645 value += "&%s%s;" % (prefix_str, field.c_field_name)
646 # list with nmemb (fixed size) elements
648 value += '%s%s;' % (prefix_str, field.c_field_name)
649 length = '%d' % field.type.nmemb
651 return (value, length)
652 # _c_serialize_helper_fields_fixed_size()
654 def _c_serialize_helper_fields_variable_size(context, self, field,
655 code_lines, temp_vars,
657 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
659 if 'unserialize' == context:
661 elif 'serialize' == context:
662 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s%s;' % (prefix_str, field.c_field_name)
665 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
666 code_lines.append('%s /* %s */' % (space, field.c_field_name))
668 if field.type.is_list:
669 length = _c_serialize_helper_list_field(context, self, field,
670 code_lines, temp_vars,
672 elif field.type.is_switch:
673 length = _c_serialize_helper_switch_field(self, field)
675 length = "%s(xcb_tmp)" % (field.type.c_unserialize_name)
677 return (value, length)
678 # _c_serialize_helper_fields_variable_size
680 def _c_serialize_helper_fields(context, self,
681 code_lines, temp_vars,
682 space, prefix, is_bitcase):
685 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
687 for field in self.fields:
688 if not ((field.wire and not field.auto) or field.visible):
691 # switch/bitcase: fixed size fields must be considered explicitly
692 if field.type.fixed_size():
694 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
695 code_lines, temp_vars,
700 # fields with variable size
702 # switch/bitcase: always calculate padding before and after variable sized fields
703 if need_padding or is_bitcase:
704 _c_serialize_helper_insert_padding(context, code_lines, space)
706 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
707 code_lines, temp_vars,
710 # save (un)serialization C code
712 code_lines.append('%s%s' % (space, value))
713 if field.type.fixed_size() and is_bitcase:
714 code_lines.append('%s xcb_block_len += %s;' % (space, length))
715 if 'unserialize' == context:
716 code_lines.append('%s xcb_tmp += %s;' % (space, length))
720 code_lines.append('%s xcb_block_len = %s;' % (space, length))
721 if 'unserialize' == context:
722 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
723 if 'serialize' == context:
725 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_block_len;' % space)
726 code_lines.append('%s xcb_parts_idx++;' % space)
731 # _c_serialize_helper_fields()
733 def _c_serialize_helper(context, complex_type,
734 code_lines, temp_vars,
735 space='', prefix=''):
737 if hasattr(complex_type, 'type'):
738 self = complex_type.type
739 complex_name = complex_type.name
742 complex_name = '_aux'
744 # special case: switch is serialized by evaluating each bitcase separately
746 count += _c_serialize_helper_switch(context, self, complex_name,
747 code_lines, temp_vars,
750 # all other data types can be evaluated one field a time
752 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
753 if 'unserialize' == context:
754 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
755 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
756 _c_serialize_helper_insert_padding(context, code_lines, space)
758 count += _c_serialize_helper_fields(context, self,
759 code_lines, temp_vars,
760 space, prefix, False)
762 count += _c_serialize_helper_insert_padding(context, code_lines, space)
765 # _c_serialize_helper()
767 def _c_serialize(self):
772 # _serialize() returns the buffer size
775 variable_size_fields = 0
776 # maximum space required for type definition of function arguments
778 param_fields, wire_fields, params = get_serialize_params('serialize', self)
780 # determine N(variable_fields)
781 for field in param_fields:
782 # if self.is_switch, treat all fields as if they are variable sized
783 if not field.type.fixed_size() or self.is_switch:
784 variable_size_fields += 1
785 # determine maxtypelen
787 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
790 for p in range(len(params)):
792 typespec, pointerspec, field_name = params[p]
793 indent = ' '*(len(self.c_serialize_name)+2)
794 # p==0: function declaration
796 line = "%s (" % self.c_serialize_name
798 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
799 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
800 if p < len(params)-1:
807 if not self.is_switch:
808 _c(' %s *xcb_out = *_buffer;', self.c_type)
809 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
810 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
812 _c(' char *xcb_out = *_buffer;')
813 _c(' unsigned int xcb_buffer_len = 0;')
814 if variable_size_fields > 0:
817 count =_c_serialize_helper('serialize', self,
818 code_lines, temp_vars)
819 # update variable size fields
820 variable_size_fields = count
821 temp_vars.add(' unsigned int xcb_pad = 0;')
822 temp_vars.add(' char xcb_pad0[3] = {0, 0, 0};')
823 temp_vars.add(' struct iovec xcb_parts[%d];' % (count+1))
824 temp_vars.add(' unsigned int xcb_parts_idx = 0;')
825 temp_vars.add(' unsigned int xcb_block_len = 0;')
826 temp_vars.add(' unsigned int i;')
827 temp_vars.add(' char *xcb_tmp;')
833 if variable_size_fields > 0:
838 # variable sized fields have been collected, now
839 # allocate memory and copy everything into a continuous memory area
840 _c(' if (NULL == xcb_out) {')
841 _c(' /* allocate memory */')
842 _c(' *_buffer = malloc(xcb_buffer_len);')
843 _c(' xcb_out = *_buffer;')
847 # fill in struct members
848 if not self.is_switch:
849 if len(wire_fields)>0:
850 _c(' *xcb_out = *_aux;')
852 # copy variable size fields into the buffer
853 if variable_size_fields > 0:
855 if not self.is_switch:
856 _c(' xcb_tmp = (char*)++xcb_out;')
857 _c(' xcb_tmp += xcb_out_pad;')
859 _c(' xcb_tmp = xcb_out;')
861 # variable sized fields
862 _c(' for(i=0; i<xcb_parts_idx; i++) {')
863 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
864 _c(' xcb_tmp += xcb_parts[i].iov_len;')
867 _c(' return xcb_buffer_len;')
871 def _c_unserialize(self):
877 # _unserialize() returns the buffer size as well
881 variable_size_fields = 0
882 # maximum space required for type definition of function arguments
884 param_fields, wire_fields, params = get_serialize_params('unserialize', self)
886 # determine N(variable_fields)
887 for field in param_fields:
888 # if self.is_switch, treat all fields as if they are variable sized
889 if not field.type.fixed_size() or self.is_switch:
890 variable_size_fields += 1
891 # determine maxtypelen
893 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
896 for p in range(len(params)):
898 typespec, pointerspec, field_name = params[p]
899 indent = ' '*(len(self.c_unserialize_name)+2)
900 # p==0: function declaration
902 line = "%s (" % self.c_unserialize_name
904 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
905 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
906 if p < len(params)-1:
913 _c(' char *xcb_tmp = (char *)_buffer;')
914 if not self.is_switch:
915 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
916 _c(' unsigned int xcb_buffer_len = 0;')
917 _c(' unsigned int xcb_block_len = 0;')
918 _c(' unsigned int xcb_pad = 0;')
922 _c_serialize_helper('unserialize', self,
923 code_lines, temp_vars)
931 _c(' return xcb_buffer_len;')
935 def _c_iterator_get_end(field, accum):
937 Figures out what C code is needed to find the end of a variable-length structure field.
938 For nested structures, recurses into its last variable-sized field.
939 For lists, calls the end function
941 if field.type.is_container:
942 accum = field.c_accessor_name + '(' + accum + ')'
943 # XXX there could be fixed-length fields at the end
944 return _c_iterator_get_end(field.type.last_varsized_field, accum)
945 if field.type.is_list:
946 # XXX we can always use the first way
947 if field.type.member.is_simple:
948 return field.c_end_name + '(' + accum + ')'
950 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
952 def _c_iterator(self, name):
954 Declares the iterator structure and next/end functions for a given type.
959 _h(' * @brief %s', self.c_iterator_type)
961 _h('typedef struct %s {', self.c_iterator_type)
962 _h(' %s *data; /**< */', self.c_type)
963 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
964 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
965 _h('} %s;', self.c_iterator_type)
971 _h(' * Get the next element of the iterator')
972 _h(' * @param i Pointer to a %s', self.c_iterator_type)
974 _h(' * Get the next element in the iterator. The member rem is')
975 _h(' * decreased by one. The member data points to the next')
976 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
980 _hc('/*****************************************************************************')
982 _hc(' ** void %s', self.c_next_name)
984 _hc(' ** @param %s *i', self.c_iterator_type)
985 _hc(' ** @returns void')
987 _hc(' *****************************************************************************/')
990 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
991 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
994 if not self.fixed_size():
995 _c(' %s *R = i->data;', self.c_type)
996 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
998 _c(' i->data = (%s *) child.data;', self.c_type)
999 _c(' i->index = child.index;')
1003 _c(' i->index += sizeof(%s);', self.c_type)
1009 _h(' * Return the iterator pointing to the last element')
1010 _h(' * @param i An %s', self.c_iterator_type)
1011 _h(' * @return The iterator pointing to the last element')
1013 _h(' * Set the current element in the iterator to the last element.')
1014 _h(' * The member rem is set to 0. The member data points to the')
1015 _h(' * last element.')
1019 _hc('/*****************************************************************************')
1021 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1023 _hc(' ** @param %s i', self.c_iterator_type)
1024 _hc(' ** @returns xcb_generic_iterator_t')
1026 _hc(' *****************************************************************************/')
1028 _hc('xcb_generic_iterator_t')
1029 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1030 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1032 _c(' xcb_generic_iterator_t ret;')
1034 if self.fixed_size():
1035 _c(' ret.data = i.data + i.rem;')
1036 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1039 _c(' while(i.rem > 0)')
1040 _c(' %s(&i);', self.c_next_name)
1041 _c(' ret.data = i.data;')
1042 _c(' ret.rem = i.rem;')
1043 _c(' ret.index = i.index;')
1048 def _c_accessor_get_length(expr, prefix=''):
1050 Figures out what C code is needed to get a length field.
1051 For fields that follow a variable-length field, use the accessor.
1052 Otherwise, just reference the structure field directly.
1054 prefarrow = '' if prefix == '' else prefix + '->'
1056 if expr.lenfield != None and expr.lenfield.prev_varsized_field != None:
1057 return expr.lenfield.c_accessor_name + '(' + prefix + ')'
1058 elif expr.lenfield_name != None:
1059 return prefarrow + expr.lenfield_name
1061 return str(expr.nmemb)
1063 def _c_accessor_get_expr(expr, prefix=''):
1065 Figures out what C code is needed to get the length of a list field.
1066 Recurses for math operations.
1067 Returns bitcount for value-mask fields.
1068 Otherwise, uses the value of the length field.
1070 lenexp = _c_accessor_get_length(expr, prefix)
1073 return '(' + '~' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1074 elif expr.op == 'popcount':
1075 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1076 elif expr.op == 'enumref':
1077 enum_name = expr.lenfield_type.name
1078 constant_name = expr.lenfield_name
1079 c_name = _n(enum_name + (constant_name,)).upper()
1081 elif expr.op == 'sumof':
1082 # 1. locate the referenced list object
1083 list_obj = expr.lenfield_type
1085 for f in expr.lenfield_parent.fields:
1086 if f.field_name == expr.lenfield_name:
1090 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1092 prefix = "%s->" % prefix
1093 list_name = "%s%s" % (prefix, field.c_field_name)
1094 c_length_func = "%s(%s%s)" % (field.c_length_name, prefix, field.c_field_name)
1095 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1096 elif expr.op != None:
1097 return '(' + _c_accessor_get_expr(expr.lhs, prefix) + ' ' + expr.op + ' ' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1099 return 'xcb_popcount(' + lenexp + ')'
1103 def _c_accessors_field(self, field):
1105 Declares the accessor functions for a non-list field that follows a variable-length field.
1107 if field.type.is_simple:
1110 _hc('/*****************************************************************************')
1112 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1114 _hc(' ** @param const %s *R', self.c_type)
1115 _hc(' ** @returns %s', field.c_field_type)
1117 _hc(' *****************************************************************************/')
1119 _hc('%s', field.c_field_type)
1120 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1121 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1123 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1124 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1125 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1130 _hc('/*****************************************************************************')
1132 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1134 _hc(' ** @param const %s *R', self.c_type)
1135 _hc(' ** @returns %s *', field.c_field_type)
1137 _hc(' *****************************************************************************/')
1139 _hc('%s *', field.c_field_type)
1140 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1141 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1143 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1144 _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)
1147 def _c_accessors_list(self, field):
1149 Declares the accessor functions for a list field.
1150 Declares a direct-accessor function only if the list members are fixed size.
1151 Declares length and get-iterator functions always.
1157 if list.member.fixed_size():
1160 _hc('/*****************************************************************************')
1162 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1164 _hc(' ** @param const %s *R', self.c_type)
1165 _hc(' ** @returns %s *', field.c_field_type)
1167 _hc(' *****************************************************************************/')
1169 _hc('%s *', field.c_field_type)
1170 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1171 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1174 if field.prev_varsized_field == None:
1175 _c(' return (%s *) (R + 1);', field.c_field_type)
1177 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1178 _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)
1184 _hc('/*****************************************************************************')
1186 _hc(' ** int %s', field.c_length_name)
1188 _hc(' ** @param const %s *R', self.c_type)
1189 _hc(' ** @returns int')
1191 _hc(' *****************************************************************************/')
1194 _h('%s (const %s *R /**< */);', field.c_length_name, self.c_type)
1195 _c('%s (const %s *R /**< */)', field.c_length_name, self.c_type)
1197 _c(' return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1200 if field.type.member.is_simple:
1203 _hc('/*****************************************************************************')
1205 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1207 _hc(' ** @param const %s *R', self.c_type)
1208 _hc(' ** @returns xcb_generic_iterator_t')
1210 _hc(' *****************************************************************************/')
1212 _hc('xcb_generic_iterator_t')
1213 _h('%s (const %s *R /**< */);', field.c_end_name, self.c_type)
1214 _c('%s (const %s *R /**< */)', field.c_end_name, self.c_type)
1216 _c(' xcb_generic_iterator_t i;')
1218 if field.prev_varsized_field == None:
1219 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1221 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1222 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1225 _c(' i.index = (char *) i.data - (char *) R;')
1232 _hc('/*****************************************************************************')
1234 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1236 _hc(' ** @param const %s *R', self.c_type)
1237 _hc(' ** @returns %s', field.c_iterator_type)
1239 _hc(' *****************************************************************************/')
1241 _hc('%s', field.c_iterator_type)
1242 _h('%s (const %s *R /**< */);', field.c_iterator_name, self.c_type)
1243 _c('%s (const %s *R /**< */)', field.c_iterator_name, self.c_type)
1245 _c(' %s i;', field.c_iterator_type)
1247 if field.prev_varsized_field == None:
1248 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1250 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1251 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', field.c_field_type, field.c_field_type)
1253 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1254 _c(' i.index = (char *) i.data - (char *) R;')
1258 def _c_accessors(self, name, base):
1260 Declares the accessor functions for the fields of a structure.
1262 for field in self.fields:
1263 if field.type.is_list and not field.type.fixed_size():
1264 _c_accessors_list(self, field)
1265 elif field.prev_varsized_field != None:
1266 _c_accessors_field(self, field)
1268 def c_simple(self, name):
1270 Exported function that handles cardinal type declarations.
1271 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1273 _c_type_setup(self, name, ())
1275 if (self.name != name):
1280 _h('typedef %s %s;', _t(self.name), my_name)
1283 _c_iterator(self, name)
1285 def _c_complex(self):
1287 Helper function for handling all structure types.
1288 Called for all structs, requests, replies, events, errors.
1293 _h(' * @brief %s', self.c_type)
1295 _h('typedef %s %s {', self.c_container, self.c_type)
1301 for field in self.fields:
1302 if not field.type.fixed_size() and not self.is_switch:
1303 varfield = field.c_field_name
1305 if varfield != None and not field.type.is_pad and field.wire:
1306 errmsg = '%s: warning: variable field %s followed by fixed field %s\n' % (self.c_type, varfield, field.c_field_name)
1307 sys.stderr.write(errmsg)
1310 struct_fields.append(field)
1312 for field in struct_fields:
1313 length = len(field.c_field_type)
1314 # account for '*' pointer_spec
1315 if not field.type.fixed_size():
1317 maxtypelen = max(maxtypelen, length)
1319 for field in struct_fields:
1320 if (field.type.fixed_size() or
1321 # in case of switch with switch children, don't make the field a pointer
1322 # necessary for unserialize to work
1323 (self.is_switch and field.type.is_switch)):
1324 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1325 _h(' %s%s %s%s; /**< */', field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1328 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1329 _h(' %s%s *%s%s; /**< */', field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1331 _h('} %s;', self.c_type)
1333 def c_struct(self, name):
1335 Exported function that handles structure declarations.
1337 _c_type_setup(self, name, ())
1339 _c_accessors(self, name, name)
1340 _c_iterator(self, name)
1342 def c_union(self, name):
1344 Exported function that handles union declarations.
1346 _c_type_setup(self, name, ())
1348 _c_iterator(self, name)
1350 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1352 Declares a request function.
1355 # Four stunningly confusing possibilities here:
1358 # ------------------------------
1360 # 0 flag CHECKED flag Normal Mode
1361 # void_cookie req_cookie
1362 # ------------------------------
1363 # "req_checked" "req_unchecked"
1364 # CHECKED flag 0 flag Abnormal Mode
1365 # void_cookie req_cookie
1366 # ------------------------------
1369 # Whether we are _checked or _unchecked
1370 checked = void and not regular
1371 unchecked = not void and not regular
1373 # What kind of cookie we return
1374 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1376 # What flag is passed to xcb_request
1377 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1379 # Global extension id variable or NULL for xproto
1380 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1382 # What our function name is
1383 func_name = self.c_request_name if not aux else self.c_aux_name
1385 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1387 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1391 maxtypelen = len('xcb_connection_t')
1394 for field in self.fields:
1396 # The field should appear as a call parameter
1397 param_fields.append(field)
1398 if field.wire and not field.auto:
1399 # We need to set the field up in the structure
1400 wire_fields.append(field)
1401 if field.type.need_serialize:
1402 serial_fields.append(field)
1404 for field in param_fields:
1405 c_field_const_type = field.c_field_const_type
1406 if field.type.need_serialize and not aux:
1407 c_field_const_type = "const void"
1408 if len(c_field_const_type) > maxtypelen:
1409 maxtypelen = len(c_field_const_type)
1415 _h(' * Delivers a request to the X server')
1416 _h(' * @param c The connection')
1417 _h(' * @return A cookie')
1419 _h(' * Delivers a request to the X server.')
1422 _h(' * This form can be used only if the request will not cause')
1423 _h(' * a reply to be generated. Any returned error will be')
1424 _h(' * saved for handling by xcb_request_check().')
1426 _h(' * This form can be used only if the request will cause')
1427 _h(' * a reply to be generated. Any returned error will be')
1428 _h(' * placed in the event queue.')
1432 _hc('/*****************************************************************************')
1434 _hc(' ** %s %s', cookie_type, func_name)
1437 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1438 _hc(' ** @param xcb_connection_t%s *c', spacing)
1440 for field in param_fields:
1441 c_field_const_type = field.c_field_const_type
1442 if field.type.need_serialize and not aux:
1443 c_field_const_type = "const void"
1444 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1445 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1447 _hc(' ** @returns %s', cookie_type)
1449 _hc(' *****************************************************************************/')
1451 _hc('%s', cookie_type)
1453 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1454 comma = ',' if len(param_fields) else ');'
1455 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1456 comma = ',' if len(param_fields) else ')'
1457 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1459 func_spacing = ' ' * (len(func_name) + 2)
1460 count = len(param_fields)
1461 for field in param_fields:
1463 c_field_const_type = field.c_field_const_type
1464 if field.type.need_serialize and not aux:
1465 c_field_const_type = "const void"
1466 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1467 comma = ',' if count else ');'
1468 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1469 spacing, field.c_pointer, field.c_field_name, comma)
1470 comma = ',' if count else ')'
1471 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1472 spacing, field.c_pointer, field.c_field_name, comma)
1475 for field in param_fields:
1476 if not field.type.fixed_size():
1478 if field.type.need_serialize:
1479 # _serialize() keeps track of padding automatically
1483 _c(' static const xcb_protocol_request_t xcb_req = {')
1484 _c(' /* count */ %d,', count)
1485 _c(' /* ext */ %s,', func_ext_global)
1486 _c(' /* opcode */ %s,', self.c_request_name.upper())
1487 _c(' /* isvoid */ %d', 1 if void else 0)
1491 _c(' struct iovec xcb_parts[%d];', count + 2)
1492 _c(' %s xcb_ret;', func_cookie)
1493 _c(' %s xcb_out;', self.c_type)
1494 for idx, f in enumerate(serial_fields):
1496 _c(' %s xcb_aux%d;' % (f.type.c_type, idx))
1498 _c(' void *xcb_aux%d = 0;' % (idx))
1500 _c(' printf("in function %s\\n");' % func_name)
1503 for field in wire_fields:
1504 if field.type.fixed_size():
1505 if field.type.is_expr:
1506 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr))
1507 elif field.type.is_pad:
1508 if field.type.nmemb == 1:
1509 _c(' xcb_out.%s = 0;', field.c_field_name)
1511 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
1513 if field.type.nmemb == 1:
1514 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
1516 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
1519 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
1520 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
1521 _c(' xcb_parts[3].iov_base = 0;')
1522 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
1524 # calls in order to free dyn. all. memory
1527 for field in param_fields:
1528 if not field.type.fixed_size():
1529 if not field.type.need_serialize:
1530 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1533 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1534 idx = serial_fields.index(field)
1536 serialize_args = get_serialize_params('unserialize', field.type,
1538 '&xcb_aux%d' % idx)[2]
1540 serialize_args = get_serialize_params('serialize', field.type,
1542 field.c_field_name)[2]
1543 serialize_args = reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
1544 _c(' xcb_parts[%d].iov_len = ', count)
1546 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
1547 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
1548 free_calls.append(' free(xcb_aux%d);' % idx)
1550 _c(' %s (%s);', field.type.c_unserialize_name, serialize_args)
1551 if field.type.is_list:
1552 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
1553 _c_accessor_get_expr(field.type.expr), field.type.member.c_wiretype)
1554 elif not field.type.need_serialize:
1555 # FIXME - _serialize()
1556 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);',
1557 count, 'Uh oh', field.type.c_wiretype)
1560 if not field.type.need_serialize:
1561 # the _serialize() function keeps track of padding automatically
1562 _c(' xcb_parts[%d].iov_base = 0;', count)
1563 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
1567 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
1569 # free dyn. all. data, if any
1570 for f in free_calls:
1572 _c(' return xcb_ret;')
1575 def _c_reply(self, name):
1577 Declares the function that returns the reply structure.
1579 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
1580 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
1581 spacing3 = ' ' * (len(self.c_reply_name) + 2)
1585 _h(' * Return the reply')
1586 _h(' * @param c The connection')
1587 _h(' * @param cookie The cookie')
1588 _h(' * @param e The xcb_generic_error_t supplied')
1590 _h(' * Returns the reply of the request asked by')
1592 _h(' * The parameter @p e supplied to this function must be NULL if')
1593 _h(' * %s(). is used.', self.c_unchecked_name)
1594 _h(' * Otherwise, it stores the error if any.')
1596 _h(' * The returned value must be freed by the caller using free().')
1600 _hc('/*****************************************************************************')
1602 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
1604 _hc(' ** @param xcb_connection_t%s *c', spacing1)
1605 _hc(' ** @param %s cookie', self.c_cookie_type)
1606 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
1607 _hc(' ** @returns %s *', self.c_reply_type)
1609 _hc(' *****************************************************************************/')
1611 _hc('%s *', self.c_reply_type)
1612 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
1613 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
1614 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
1615 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
1617 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
1620 def _c_opcode(name, opcode):
1622 Declares the opcode define for requests, events, and errors.
1626 _h('/** Opcode for %s. */', _n(name))
1627 _h('#define %s %s', _n(name).upper(), opcode)
1629 def _c_cookie(self, name):
1631 Declares the cookie type for a non-void request.
1636 _h(' * @brief %s', self.c_cookie_type)
1638 _h('typedef struct %s {', self.c_cookie_type)
1639 _h(' unsigned int sequence; /**< */')
1640 _h('} %s;', self.c_cookie_type)
1642 def c_request(self, name):
1644 Exported function that handles request declarations.
1646 _c_type_setup(self, name, ('request',))
1649 # Cookie type declaration
1650 _c_cookie(self, name)
1653 _c_opcode(name, self.opcode)
1655 # Request structure declaration
1659 _c_type_setup(self.reply, name, ('reply',))
1660 # Reply structure definition
1661 _c_complex(self.reply)
1662 # Request prototypes
1663 _c_request_helper(self, name, self.c_cookie_type, False, True)
1664 _c_request_helper(self, name, self.c_cookie_type, False, False)
1666 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
1667 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
1669 _c_accessors(self.reply, name + ('reply',), name)
1670 _c_reply(self, name)
1672 # Request prototypes
1673 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
1674 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
1676 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
1677 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
1680 def c_event(self, name):
1682 Exported function that handles event declarations.
1684 _c_type_setup(self, name, ('event',))
1687 _c_opcode(name, self.opcodes[name])
1689 if self.name == name:
1690 # Structure definition
1695 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
1697 def c_error(self, name):
1699 Exported function that handles error declarations.
1701 _c_type_setup(self, name, ('error',))
1704 _c_opcode(name, self.opcodes[name])
1706 if self.name == name:
1707 # Structure definition
1712 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
1715 # Main routine starts here
1717 # Must create an "output" dictionary before any xcbgen imports.
1718 output = {'open' : c_open,
1720 'simple' : c_simple,
1722 'struct' : c_struct,
1724 'request' : c_request,
1729 # Boilerplate below this point
1731 # Check for the argument that specifies path to the xcbgen python package.
1733 opts, args = getopt.getopt(sys.argv[1:], 'p:')
1734 except getopt.GetoptError, err:
1736 print 'Usage: c_client.py [-p path] file.xml'
1739 for (opt, arg) in opts:
1741 sys.path.append(arg)
1743 # Import the module class
1745 from xcbgen.state import Module
1748 print 'Failed to load the xcbgen Python package!'
1749 print 'Make sure that xcb/proto installed it on your Python path.'
1750 print 'If not, you will need to create a .pth file or define $PYTHONPATH'
1751 print 'to extend the path.'
1752 print 'Refer to the README file in xcb/proto for more info.'
1756 # Parse the xml header
1757 module = Module(args[0], output)
1759 # Build type-registry and resolve type dependencies