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 print "switch", self.name
348 # special: switch C structs get pointer fields for variable-sized members
350 # declare switch (un)packing functions
351 _c_accessors(self, name, name)
353 # FIXME - in case of request/reply, serialize() is not always needed
354 if self.need_serialize and not self.is_bitcase:
355 if self.c_serialize_name not in finished_serializers:
356 # if not hasattr(self, 'in_reply'):
359 finished_serializers.append(self.c_serialize_name)
362 def get_request_fields(self):
366 for field in self.fields:
368 # the field should appear as a parameter in the function call
369 param_fields.append(field)
370 if field.wire and not field.auto:
371 if field.type.fixed_size() and not self.is_switch:
372 # need to set the field up in the xcb_out structure
373 wire_fields.append(field)
374 # fields like 'pad0' are skipped!
376 return (param_fields, wire_fields)
377 # get_request_fields()
379 def get_switch_expr_fields(self):
380 # get the fields referenced by the switch expression
381 def get_expr_fields(expr):
383 if expr.lenfield_name is not None:
384 return [expr.lenfield_name]
387 return get_expr_fields(expr.rhs)
388 elif expr.op == 'popcount':
389 return get_expr_fields(expr.rhs)
390 elif expr.op == 'sumof':
391 return [expr.lenfield_name]
392 elif expr.op == 'enumref':
395 return get_expr_fields(expr.lhs) + get_expr_fields(expr.rhs)
398 # resolve the field names with the parent structure(s)
399 unresolved_fields = get_expr_fields(self.expr)
400 expr_fields = dict.fromkeys(unresolved_fields)
401 for p in reversed(self.parent):
402 parent_fields = dict((f.field_name, f) for f in p.fields)
403 for f in parent_fields.keys():
404 if f in unresolved_fields:
405 expr_fields[f] = parent_fields[f]
406 unresolved_fields.remove(f)
407 if len(unresolved_fields) == 0:
410 if None in expr_fields.values():
411 raise Exception("could not resolve all fields for <switch> %s" % self.name)
413 params = expr_fields.values()
415 # get_switch_expr_fields()
417 def get_serialize_params(self, buffer_var='_buffer', aux_var='_aux', unserialize=False):
418 param_fields, wire_fields = get_request_fields(self)
420 param_fields = get_switch_expr_fields(self)
422 # _serialize function parameters
424 params = [('void', '**', buffer_var)]
426 params = [('const void', '*', buffer_var)]
428 # make sure all required length fields are present
429 for p in param_fields:
430 if p.visible and not p.wire and not p.auto:
431 typespec = p.c_field_type
433 params.append((typespec, pointerspec, p.c_field_name))
435 # parameter fields if any
437 for p in get_switch_expr_fields(self):
438 typespec = p.c_field_const_type
439 pointerspec = p.c_pointer
440 params.append((typespec, pointerspec, p.c_field_name))
442 # aux argument - structure to be serialized
444 params.append(('const %s' % self.c_type, '*', aux_var))
446 params.append(('%s' % self.c_type, '*', aux_var))
447 if not self.is_switch and not unserialize:
448 for p in param_fields:
449 if not p.type.fixed_size():
450 params.append((p.c_field_const_type, p.c_pointer, p.c_field_name))
451 return (param_fields, wire_fields, params)
452 # get_serialize_params()
454 def _c_field_mapping(complex_type, context):
455 def get_prefix(field):
457 if context in ('serialize', 'unserialize'):
458 if field.type.fixed_size() or complex_type.is_switch:
461 raise Exception("unknown context '%s' in c_field_mapping" % context)
464 def get_field_name(fields, complex_type, prefix=''):
465 for f in complex_type.fields:
467 prefix = get_prefix(f)
469 fname = "%s%s" % (prefix, f.c_field_name)
470 if fields.has_key(f.field_name):
471 raise Exception("field name %s has been registered before" % f.field_name)
472 fields[f.field_name] = (fname, f)
473 if f.type.is_container:
474 new_prefix = "%s%s" % (prefix, f.c_field_name)
475 new_prefix += "." if f.type.is_switch else "->"
476 get_field_name(fields, f.type, new_prefix)
479 # dict(field_name : (c_field_name, field))
481 get_field_name(fields, complex_type)
483 # switch: get the fields referenced by the switch expr as well
484 # these may not belong to any structure
485 if complex_type.is_switch:
486 fields += get_serialize_params()
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, count=0):
501 code_lines.append('%s /* padding */' % space)
502 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
503 code_lines.append('%s if (0 != xcb_pad) {' % space)
505 if 'serialize' == context:
506 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
507 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
508 code_lines.append('%s xcb_parts_idx++;' % space)
509 elif 'unserialize' == context:
510 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
511 code_lines.append('%s xcb_buffer_len += xcb_pad;' % space)
513 code_lines.append('%s xcb_pad = 0;' % space)
514 code_lines.append('%s }' % space)
515 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
516 code_lines.append('%s xcb_block_len = 0;' % space)
518 # _c_serialize_helper_insert_padding()
520 def _c_serialize_helper_switch(self, context, complex_name, code_lines, temp_vars, space, prefix, prefix_str):
521 switch_expr = _c_accessor_get_expr(self.expr)
522 for b in self.bitcases:
523 bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix)
524 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
525 # FIXME: change function call depending on context
526 if 'unserialize' == context:
527 unserialize_fields(b.type, code_lines, temp_vars, space="%s " % space,
528 prefix="%s%s" % (prefix_str, complex_name), bitcase=True)
529 elif 'serialize' == context:
530 count += serialize_fields(b.type, code_lines, temp_vars, '%s ' % space,
531 prefix="%s%s" % (prefix_str, complex_name),
532 serialize_fixed_size_fields=True, bitcase=True)
533 code_lines.append(' }')
535 if 'serialize' == context:
536 count = insert_padding(count)
538 if 'unserialize' == context:
540 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
541 #code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
542 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
543 # _c_serialize_helper_switch
545 def _c_serialize_helper_switch_field(self, field):
546 # switch is handled by this function as a special case
547 args = get_switch_expr_fields(field.type)
548 field_mapping = _c_field_mapping(self, 'unserialize')
551 c_field_names += "%s, " % field_mapping[a.field_name][0]
552 switch_field_name = field_mapping[field.field_name][0]
553 length = "%s(xcb_tmp, %s&%s)" % (field.type.c_unserialize_name,
554 c_field_names, switch_field_name)
556 # _c_serialize_helper_switch_field()
558 def _c_serialize_helper_list_field(context, self, field, lenfield_prefix, code_lines, temp_vars, space):
559 expr = field.type.expr
560 param_fields, wire_fields, params = get_serialize_params(self, unserialize=True)
561 param_names = [p[2] for p in params]
563 # look if the list's lenfield is a struct member or a function argument
564 # special case: if the list has a length field, its name will returned
565 # unchanged by calling c_accessor_get_length(expr)
566 if expr.lenfield_name == _c_accessor_get_length(expr):
567 if expr.lenfield_name in param_names:
568 # the length field appears as separate argument in unserialize,
569 # so no need for a prefix
571 list_length = _c_accessor_get_expr(field.type.expr, lenfield_prefix)
573 if 'unserialize' == context:
574 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
575 # FIXME? - list with variable-sized elements
576 if field.type.size is None:
578 temp_vars.add(' unsigned int i, xcb_tmp_len;')
579 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
580 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
581 (space, field.type.c_unserialize_name))
582 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
583 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
584 code_lines.append("%s }" % space)
585 # errmsg = '%s: warning: list object with variable-sized members not supported for field %s\n'
586 # raise Exception(errmsg % (self.c_type, field.c_field_name))
589 # _c_serialize_helper_list_field()
591 def unserialize_fields(complex_type, code_lines=[], temp_vars=set(), space='', prefix='', bitcase=False):
594 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
596 if hasattr(complex_type, 'type'):
597 self = complex_type.type
598 complex_name = complex_type.name
601 complex_name = '_aux'
603 # special case: switch is serialized by evaluating each bitcase separately
606 _c_serialize_helper_switch(self, 'unserialize', complex_name, code_lines, temp_vars, space, prefix, prefix_str)
608 # all other data types can be evaluated one field a time
610 # fixed sized fields: simply cast the buffer to the respective xcb_out type
611 # this would of course not work for switch/bitcase
613 _c_serialize_helper_insert_padding('unserialize', code_lines, space)
615 for field in self.fields:
616 if not ((field.wire and not field.auto) or field.visible):
619 # generic length statement
620 length = "sizeof(%s)" % field.c_field_type
622 # switch/bitcase: fixed size fields must be considered explicitly
623 if field.type.fixed_size():
626 value = ' _aux->%s = (%s) *xcb_tmp;' % (field.c_field_name, field.type.c_type)
631 # fields with variable size
632 elif not field.type.fixed_size():
633 # switch/bitcase: always calculate padding before and after variable sized fields
635 if need_padding or bitcase:
636 _c_serialize_helper_insert_padding('unserialize', code_lines, space)
638 # value = ' *%s = (%s *) xcb_tmp;' % (field.c_field_name, field.type.c_type)
641 if field.type.is_list:
642 length = _c_serialize_helper_list_field('unserialize',
643 self, field, lenfield_prefix,
644 code_lines, temp_vars, space)
646 elif field.type.is_switch:
647 length = _c_serialize_helper_switch_field(self, field)
650 length = "%s(xcb_tmp)" % (field.type.c_unserialize_name)
651 # errmsg = '%s: warning: non-list object of variable size not supported for field %s\n'
652 # raise Exception(errmsg % (self.c_type, field.c_field_name))
654 # save unserialization C code
655 if value is not None:
656 if field.type.fixed_size():
657 # field appears in the request structure
658 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
660 code_lines.append('%s /* %s */' % (space, field.c_field_name))
664 code_lines.append('%s%s' % (space, value))
665 if field.type.fixed_size():
666 code_lines.append('%s xcb_block_len += %s;' % (space, length))
667 code_lines.append('%s xcb_tmp += %s;' % (space, length))
671 code_lines.append('%s xcb_block_len = %s;' % (space, length))
672 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
673 code_lines.append('%s xcb_tmp += xcb_block_len + xcb_pad;' % space)
674 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
675 code_lines.append('%s xcb_block_len = 0;' % space)
676 code_lines.append('%s xcb_pad = 0;' % space)
678 # unserialize_fields()
680 def serialize_fields(complex_type, code_lines=[], temp_vars=set(),
681 space='', prefix='', serialize_fixed_size_fields=False,
684 helper routine to build up iovec arrays that will later be copied into a single buffer
686 complex_type - encapsulating Type/Field
687 code_lines, temp_vars - containers for generated code & variable declarations
688 space - extra space to be inserted before any statement
689 prefix - prefix to be used for struct members, needed for switch/bitcase mapping
690 bitcase - flags whether fields are bitcase members
693 # count -> no. of entries in xcb_parts array
695 # flag to mark wether explicit padding needs to be inserted
697 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
699 if hasattr(complex_type, 'type'):
700 self = complex_type.type
701 complex_name = complex_type.name
704 complex_name = '_aux'
706 param_fields, wire_fields, params = get_serialize_params(self, unserialize=True)
707 param_names = [p[2] for p in params]
709 def insert_padding(count):
710 code_lines.append('%s /* padding */' % space)
711 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
712 code_lines.append('%s if (0 != xcb_pad) {' % space)
713 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
714 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
715 code_lines.append('%s xcb_parts_idx++;' % space)
716 code_lines.append('%s }' % space)
717 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
718 code_lines.append('%s xcb_pad = 0;' % space)
719 code_lines.append('%s xcb_block_len = 0;' % space)
724 # special case - if self.is_switch, all fields need to be serialized conditionally
726 switch_expr = _c_accessor_get_expr(self.expr)
729 for b in self.bitcases:
730 bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix)
731 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
733 count += serialize_fields(b.type, code_lines, temp_vars, '%s ' % space,
734 prefix="%s%s" % (prefix_str, complex_name),
735 serialize_fixed_size_fields=True, bitcase=True)
736 code_lines.append(' }')
737 count = insert_padding(count)
740 for field in self.fields:
743 # sort out invisible fields
744 if not ((field.wire and not field.auto) or field.visible):
747 length = "sizeof(%s)" % field.c_field_type
749 # switch/bitcase: fixed size fields are serialized explicitly
750 if field.type.fixed_size() and bitcase:
751 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
754 if field.type.is_expr:
755 # need to register a temporary variable for the expression
756 if field.type.c_type is None:
757 raise Exception("type for field '%s' (expression '%s') unkown" %
758 (field.field_name, _c_accessor_get_expr(field.type.expr)))
759 temp_vars.add(' %s xcb_expr_%s = %s;' % (field.type.c_type, field.field_name,
760 _c_accessor_get_expr(field.type.expr, prefix)))
761 value += "&xcb_expr_%s;" % field.field_name
763 elif field.type.is_pad:
764 if field.type.nmemb == 1:
767 value = ' memset(xcb_parts[xcb_parts_idx].iov_base, 0, %d);' % field.type.nmemb
768 length += "*%d" % field.type.nmemb
771 # non-list type with fixed size
772 if field.type.nmemb == 1:
773 value += "&%s%s;" % (prefix_str, field.c_field_name)
774 # list with nmemb (fixed size) elements
776 value += '%s%s;' % (prefix_str, field.c_field_name)
777 length = '%d' % field.type.nmemb
779 # fields with variable size
780 elif not field.type.fixed_size():
781 # calculate padding before variable sized fields only if necessary
782 if bitcase or need_padding:
783 count = insert_padding(count)
784 code_lines.append('%s xcb_block_len = 0;' % space)
787 code_lines.append('%s /* %s */' % (space, field.c_field_name))
788 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s%s;' % (prefix_str, field.c_field_name)
790 code_lines.append('%s%s' % (space, value))
792 if field.type.is_list:
793 # list of variable length with variable size elements
794 if field.type.size is None:
795 errmsg = '%s: warning: list object with variable-sized members not supported for field %s\n'
796 sys.stderr.write(errmsg % (self.c_type, field.c_field_name))
797 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
798 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
799 code_lines.append('%s for(i=0; i<%s; i++) {'
800 % (space, _c_accessor_get_expr(field.type.expr, lenfield_prefix)))
801 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_unserialize_name))
802 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
803 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
804 code_lines.append('%s }' % space)
805 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
807 # list of variable length with fixed size elements
809 # look if the list's lenfield is a struct member or a function argument
810 lf_prefix = lenfield_prefix
811 # special case: if the list has a length field, its name will returned
812 # unchanged by calling c_accessor_get_length(expr)
813 expr = field.type.expr
814 if expr.lenfield_name == _c_accessor_get_length(expr):
815 if expr.lenfield_name in param_names:
816 # the length field appears as separate argument in unserialize,
817 # so no need for a prefix
820 length = '%s * sizeof(%s)' % (_c_accessor_get_expr(field.type.expr, lf_prefix),
821 field.type.member.c_wiretype)
823 elif field.type.is_switch:
824 # switch is handled at the beginning of this function as a special case
825 # count += serialize_fields(field.type, code_lines, temp_vars, space,
826 # prefix="%s%s" % (prefix_str, field.c_field_name))
827 # FIXME - call another serialize
829 sys.stderr.write("FIXME: call %s" % field.type.c_serialize_name)
832 # FIXME - variable sized field that is not a list
833 errmsg = '%s: warning: non-list object of variable size not supported for field %s\n'
834 sys.stderr.write(errmsg % (self.c_type, field.c_field_name))
835 length = '%s * sizeof(%s)' % ('undefined', field.type.c_wiretype)
837 # save serialization C code using xcb_parts[].iov_base and xcb_parts[].iov_len
838 if value is not None:
839 if field.type.fixed_size():
840 # field belongs to some anchestor structure
841 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
842 code_lines.append('%s%s' % (space, value))
844 code_lines.append('%s xcb_block_len += %s;' % (space, length))
846 if not field.type.fixed_size():
847 code_lines.append('%s xcb_block_len = %s;' % (space, length))
848 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_block_len;' % space)
849 # increase xcb_parts index
850 code_lines.append('%s xcb_parts_idx++;' % space)
853 if not field.type.fixed_size():
855 count = insert_padding(count)
857 # raise Exception("obsolete - should not be reached")
858 # code_lines.append('%s xcb_unpadded = xcb_parts[xcb_parts_idx].iov_len;' % space)
863 def _c_serialize(self):
868 # _serialize() returns the buffer size
871 variable_size_fields = 0
872 # maximum space required for type definition of function arguments
874 param_fields, wire_fields, params = get_serialize_params(self)
876 # determine N(variable_fields)
877 for field in param_fields:
878 # if self.is_switch, treat all fields as if they are variable sized
879 if not field.type.fixed_size() or self.is_switch:
880 variable_size_fields += 1
881 # determine maxtypelen
883 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
886 for p in range(len(params)):
888 typespec, pointerspec, field_name = params[p]
889 indent = ' '*(len(self.c_serialize_name)+2)
890 # p==0: function declaration
892 line = "%s (" % self.c_serialize_name
894 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
895 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
896 if p < len(params)-1:
903 if not self.is_switch:
904 _c(' %s *xcb_out = *_buffer;', self.c_type)
905 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
906 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
908 _c(' char *xcb_out = *_buffer;')
909 _c(' unsigned int xcb_buffer_len = 0;')
910 if variable_size_fields > 0:
913 count = serialize_fields(self, code_lines, temp_vars,
914 serialize_fixed_size_fields=False)
915 # update variable size fields
916 variable_size_fields = count
917 _c(' unsigned int xcb_pad = 0;')
918 _c(' char xcb_pad0[3] = {0, 0, 0};')
919 _c(' struct iovec xcb_parts[%d];', count+1)
920 _c(' unsigned int xcb_parts_idx = 0;')
921 _c(' unsigned int xcb_block_len = 0;')
924 _c(' char *xcb_tmp;')
925 _c(' unsigned int i;')
929 if variable_size_fields > 0:
933 # _c(' /* padding */')
934 # _c(' xcb_pad = -xcb_block_len & 3;')
935 # _c(' if (0 != xcb_pad) {')
936 # _c(' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;')
937 # _c(' xcb_parts[xcb_parts_idx].iov_len = xcb_pad;')
938 # _c(' xcb_parts_idx++;')
940 # _c(' xcb_buffer_len += xcb_block_len + xcb_pad;')
943 # variable sized fields have been collected, now
944 # allocate memory and copy everything into a continuous memory area
945 _c(' if (NULL == xcb_out) {')
946 _c(' /* allocate memory */')
947 _c(' *_buffer = malloc(xcb_buffer_len);')
948 _c(' xcb_out = *_buffer;')
952 # fill in struct members
953 if not self.is_switch:
954 if len(wire_fields)>0:
955 _c(' *xcb_out = *_aux;')
957 # copy variable size fields into the buffer
958 if variable_size_fields > 0:
960 if not self.is_switch:
961 _c(' xcb_tmp = (char*)++xcb_out;')
962 _c(' xcb_tmp += xcb_out_pad;')
964 _c(' xcb_tmp = xcb_out;')
966 # variable sized fields
967 _c(' for(i=0; i<xcb_parts_idx; i++) {')
968 # _c(' if (0 != xcb_parts[i].iov_base) {')
969 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
971 _c(' xcb_tmp += xcb_parts[i].iov_len;')
974 _c(' return xcb_buffer_len;')
978 def _c_unserialize(self):
984 # _unserialize() returns the buffer size as well
988 variable_size_fields = 0
989 # maximum space required for type definition of function arguments
991 param_fields, wire_fields, params = get_serialize_params(self, unserialize=True)
993 # determine N(variable_fields)
994 for field in param_fields:
995 # if self.is_switch, treat all fields as if they are variable sized
996 if not field.type.fixed_size() or self.is_switch:
997 variable_size_fields += 1
998 # determine maxtypelen
1000 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1003 for p in range(len(params)):
1005 typespec, pointerspec, field_name = params[p]
1006 indent = ' '*(len(self.c_unserialize_name)+2)
1007 # p==0: function declaration
1009 line = "%s (" % self.c_unserialize_name
1011 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1012 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
1013 if p < len(params)-1:
1020 _c(' char *xcb_tmp = (char *)_buffer;')
1021 if not self.is_switch:
1022 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1023 _c(' unsigned int xcb_buffer_len = 0;')
1024 _c(' unsigned int xcb_block_len = 0;')
1025 _c(' unsigned int xcb_pad = 0;')
1029 unserialize_fields(self, code_lines, temp_vars)
1034 for l in code_lines:
1037 _c(' return xcb_buffer_len;')
1041 def _c_iterator_get_end(field, accum):
1043 Figures out what C code is needed to find the end of a variable-length structure field.
1044 For nested structures, recurses into its last variable-sized field.
1045 For lists, calls the end function
1047 if field.type.is_container:
1048 accum = field.c_accessor_name + '(' + accum + ')'
1049 # XXX there could be fixed-length fields at the end
1050 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1051 if field.type.is_list:
1052 # XXX we can always use the first way
1053 if field.type.member.is_simple:
1054 return field.c_end_name + '(' + accum + ')'
1056 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1058 def _c_iterator(self, name):
1060 Declares the iterator structure and next/end functions for a given type.
1065 _h(' * @brief %s', self.c_iterator_type)
1067 _h('typedef struct %s {', self.c_iterator_type)
1068 _h(' %s *data; /**< */', self.c_type)
1069 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1070 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1071 _h('} %s;', self.c_iterator_type)
1077 _h(' * Get the next element of the iterator')
1078 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1080 _h(' * Get the next element in the iterator. The member rem is')
1081 _h(' * decreased by one. The member data points to the next')
1082 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1086 _hc('/*****************************************************************************')
1088 _hc(' ** void %s', self.c_next_name)
1090 _hc(' ** @param %s *i', self.c_iterator_type)
1091 _hc(' ** @returns void')
1093 _hc(' *****************************************************************************/')
1096 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1097 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1100 if not self.fixed_size():
1101 _c(' %s *R = i->data;', self.c_type)
1102 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1104 _c(' i->data = (%s *) child.data;', self.c_type)
1105 _c(' i->index = child.index;')
1109 _c(' i->index += sizeof(%s);', self.c_type)
1115 _h(' * Return the iterator pointing to the last element')
1116 _h(' * @param i An %s', self.c_iterator_type)
1117 _h(' * @return The iterator pointing to the last element')
1119 _h(' * Set the current element in the iterator to the last element.')
1120 _h(' * The member rem is set to 0. The member data points to the')
1121 _h(' * last element.')
1125 _hc('/*****************************************************************************')
1127 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1129 _hc(' ** @param %s i', self.c_iterator_type)
1130 _hc(' ** @returns xcb_generic_iterator_t')
1132 _hc(' *****************************************************************************/')
1134 _hc('xcb_generic_iterator_t')
1135 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1136 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1138 _c(' xcb_generic_iterator_t ret;')
1140 if self.fixed_size():
1141 _c(' ret.data = i.data + i.rem;')
1142 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1145 _c(' while(i.rem > 0)')
1146 _c(' %s(&i);', self.c_next_name)
1147 _c(' ret.data = i.data;')
1148 _c(' ret.rem = i.rem;')
1149 _c(' ret.index = i.index;')
1154 def _c_accessor_get_length(expr, prefix=''):
1156 Figures out what C code is needed to get a length field.
1157 For fields that follow a variable-length field, use the accessor.
1158 Otherwise, just reference the structure field directly.
1160 prefarrow = '' if prefix == '' else prefix + '->'
1162 if expr.lenfield != None and expr.lenfield.prev_varsized_field != None:
1163 return expr.lenfield.c_accessor_name + '(' + prefix + ')'
1164 elif expr.lenfield_name != None:
1165 return prefarrow + expr.lenfield_name
1167 return str(expr.nmemb)
1169 def _c_accessor_get_expr(expr, prefix=''):
1171 Figures out what C code is needed to get the length of a list field.
1172 Recurses for math operations.
1173 Returns bitcount for value-mask fields.
1174 Otherwise, uses the value of the length field.
1176 lenexp = _c_accessor_get_length(expr, prefix)
1179 return '(' + '~' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1180 elif expr.op == 'popcount':
1181 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1182 elif expr.op == 'enumref':
1183 enum_name = expr.lenfield_type.name
1184 constant_name = expr.lenfield_name
1185 c_name = _n(enum_name + (constant_name,)).upper()
1187 elif expr.op == 'sumof':
1188 # 1. locate the referenced list object
1189 list_obj = expr.lenfield_type
1191 for f in expr.lenfield_parent.fields:
1192 if f.field_name == expr.lenfield_name:
1196 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1198 prefix = "%s->" % prefix
1199 list_name = "%s%s" % (prefix, field.c_field_name)
1200 c_length_func = "%s(%s%s)" % (field.c_length_name, prefix, field.c_field_name)
1201 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1202 elif expr.op != None:
1203 return '(' + _c_accessor_get_expr(expr.lhs, prefix) + ' ' + expr.op + ' ' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1205 return 'xcb_popcount(' + lenexp + ')'
1209 def _c_accessors_field(self, field):
1211 Declares the accessor functions for a non-list field that follows a variable-length field.
1213 if field.type.is_simple:
1216 _hc('/*****************************************************************************')
1218 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1220 _hc(' ** @param const %s *R', self.c_type)
1221 _hc(' ** @returns %s', field.c_field_type)
1223 _hc(' *****************************************************************************/')
1225 _hc('%s', field.c_field_type)
1226 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1227 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1229 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1230 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1231 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1236 _hc('/*****************************************************************************')
1238 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1240 _hc(' ** @param const %s *R', self.c_type)
1241 _hc(' ** @returns %s *', field.c_field_type)
1243 _hc(' *****************************************************************************/')
1245 _hc('%s *', field.c_field_type)
1246 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1247 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1249 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1250 _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)
1253 def _c_accessors_list(self, field):
1255 Declares the accessor functions for a list field.
1256 Declares a direct-accessor function only if the list members are fixed size.
1257 Declares length and get-iterator functions always.
1263 if list.member.fixed_size():
1266 _hc('/*****************************************************************************')
1268 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1270 _hc(' ** @param const %s *R', self.c_type)
1271 _hc(' ** @returns %s *', field.c_field_type)
1273 _hc(' *****************************************************************************/')
1275 _hc('%s *', field.c_field_type)
1276 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1277 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1280 if field.prev_varsized_field == None:
1281 _c(' return (%s *) (R + 1);', field.c_field_type)
1283 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1284 _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)
1290 _hc('/*****************************************************************************')
1292 _hc(' ** int %s', field.c_length_name)
1294 _hc(' ** @param const %s *R', self.c_type)
1295 _hc(' ** @returns int')
1297 _hc(' *****************************************************************************/')
1300 _h('%s (const %s *R /**< */);', field.c_length_name, self.c_type)
1301 _c('%s (const %s *R /**< */)', field.c_length_name, self.c_type)
1303 _c(' return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1306 if field.type.member.is_simple:
1309 _hc('/*****************************************************************************')
1311 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1313 _hc(' ** @param const %s *R', self.c_type)
1314 _hc(' ** @returns xcb_generic_iterator_t')
1316 _hc(' *****************************************************************************/')
1318 _hc('xcb_generic_iterator_t')
1319 _h('%s (const %s *R /**< */);', field.c_end_name, self.c_type)
1320 _c('%s (const %s *R /**< */)', field.c_end_name, self.c_type)
1322 _c(' xcb_generic_iterator_t i;')
1324 if field.prev_varsized_field == None:
1325 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1327 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1328 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1331 _c(' i.index = (char *) i.data - (char *) R;')
1338 _hc('/*****************************************************************************')
1340 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1342 _hc(' ** @param const %s *R', self.c_type)
1343 _hc(' ** @returns %s', field.c_iterator_type)
1345 _hc(' *****************************************************************************/')
1347 _hc('%s', field.c_iterator_type)
1348 _h('%s (const %s *R /**< */);', field.c_iterator_name, self.c_type)
1349 _c('%s (const %s *R /**< */)', field.c_iterator_name, self.c_type)
1351 _c(' %s i;', field.c_iterator_type)
1353 if field.prev_varsized_field == None:
1354 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1356 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1357 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', field.c_field_type, field.c_field_type)
1359 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1360 _c(' i.index = (char *) i.data - (char *) R;')
1364 def _c_accessors(self, name, base):
1366 Declares the accessor functions for the fields of a structure.
1368 for field in self.fields:
1369 if field.type.is_list and not field.type.fixed_size():
1370 _c_accessors_list(self, field)
1371 elif field.prev_varsized_field != None:
1372 _c_accessors_field(self, field)
1374 def c_simple(self, name):
1376 Exported function that handles cardinal type declarations.
1377 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1379 _c_type_setup(self, name, ())
1381 if (self.name != name):
1386 _h('typedef %s %s;', _t(self.name), my_name)
1389 _c_iterator(self, name)
1391 def _c_complex(self):
1393 Helper function for handling all structure types.
1394 Called for all structs, requests, replies, events, errors.
1399 _h(' * @brief %s', self.c_type)
1401 _h('typedef %s %s {', self.c_container, self.c_type)
1407 for field in self.fields:
1408 if not field.type.fixed_size() and not self.is_switch:
1409 varfield = field.c_field_name
1411 if varfield != None and not field.type.is_pad and field.wire:
1412 errmsg = '%s: warning: variable field %s followed by fixed field %s\n' % (self.c_type, varfield, field.c_field_name)
1413 sys.stderr.write(errmsg)
1416 struct_fields.append(field)
1418 for field in struct_fields:
1419 length = len(field.c_field_type)
1420 # account for '*' pointer_spec
1421 if not field.type.fixed_size():
1423 maxtypelen = max(maxtypelen, length)
1425 for field in struct_fields:
1426 if (field.type.fixed_size() or
1427 # in case of switch with switch children, don't make the field a pointer
1428 # necessary for unserialize to work
1429 (self.is_switch and field.type.is_switch)):
1430 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1431 _h(' %s%s %s%s; /**< */', field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1434 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1435 _h(' %s%s *%s%s; /**< */', field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1437 _h('} %s;', self.c_type)
1439 def c_struct(self, name):
1441 Exported function that handles structure declarations.
1443 _c_type_setup(self, name, ())
1445 _c_accessors(self, name, name)
1446 _c_iterator(self, name)
1448 def c_union(self, name):
1450 Exported function that handles union declarations.
1452 _c_type_setup(self, name, ())
1454 _c_iterator(self, name)
1456 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1458 Declares a request function.
1461 # Four stunningly confusing possibilities here:
1464 # ------------------------------
1466 # 0 flag CHECKED flag Normal Mode
1467 # void_cookie req_cookie
1468 # ------------------------------
1469 # "req_checked" "req_unchecked"
1470 # CHECKED flag 0 flag Abnormal Mode
1471 # void_cookie req_cookie
1472 # ------------------------------
1475 # Whether we are _checked or _unchecked
1476 checked = void and not regular
1477 unchecked = not void and not regular
1479 # What kind of cookie we return
1480 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1482 # What flag is passed to xcb_request
1483 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1485 # Global extension id variable or NULL for xproto
1486 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1488 # What our function name is
1489 func_name = self.c_request_name if not aux else self.c_aux_name
1491 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1493 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1497 maxtypelen = len('xcb_connection_t')
1500 for field in self.fields:
1502 # The field should appear as a call parameter
1503 param_fields.append(field)
1504 if field.wire and not field.auto:
1505 # We need to set the field up in the structure
1506 wire_fields.append(field)
1507 if field.type.need_serialize:
1508 serial_fields.append(field)
1510 for field in param_fields:
1511 c_field_const_type = field.c_field_const_type
1512 if field.type.need_serialize and not aux:
1513 c_field_const_type = "const void"
1514 if len(c_field_const_type) > maxtypelen:
1515 maxtypelen = len(c_field_const_type)
1521 _h(' * Delivers a request to the X server')
1522 _h(' * @param c The connection')
1523 _h(' * @return A cookie')
1525 _h(' * Delivers a request to the X server.')
1528 _h(' * This form can be used only if the request will not cause')
1529 _h(' * a reply to be generated. Any returned error will be')
1530 _h(' * saved for handling by xcb_request_check().')
1532 _h(' * This form can be used only if the request will cause')
1533 _h(' * a reply to be generated. Any returned error will be')
1534 _h(' * placed in the event queue.')
1538 _hc('/*****************************************************************************')
1540 _hc(' ** %s %s', cookie_type, func_name)
1543 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1544 _hc(' ** @param xcb_connection_t%s *c', spacing)
1546 for field in param_fields:
1547 c_field_const_type = field.c_field_const_type
1548 if field.type.need_serialize and not aux:
1549 c_field_const_type = "const void"
1550 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1551 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1553 _hc(' ** @returns %s', cookie_type)
1555 _hc(' *****************************************************************************/')
1557 _hc('%s', cookie_type)
1559 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1560 comma = ',' if len(param_fields) else ');'
1561 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1562 comma = ',' if len(param_fields) else ')'
1563 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1565 func_spacing = ' ' * (len(func_name) + 2)
1566 count = len(param_fields)
1567 for field in param_fields:
1569 c_field_const_type = field.c_field_const_type
1570 if field.type.need_serialize and not aux:
1571 c_field_const_type = "const void"
1572 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1573 comma = ',' if count else ');'
1574 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1575 spacing, field.c_pointer, field.c_field_name, comma)
1576 comma = ',' if count else ')'
1577 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1578 spacing, field.c_pointer, field.c_field_name, comma)
1581 for field in param_fields:
1582 if not field.type.fixed_size():
1584 if field.type.need_serialize:
1585 # _serialize() keeps track of padding automatically
1589 _c(' static const xcb_protocol_request_t xcb_req = {')
1590 _c(' /* count */ %d,', count)
1591 _c(' /* ext */ %s,', func_ext_global)
1592 _c(' /* opcode */ %s,', self.c_request_name.upper())
1593 _c(' /* isvoid */ %d', 1 if void else 0)
1597 _c(' struct iovec xcb_parts[%d];', count + 2)
1598 _c(' %s xcb_ret;', func_cookie)
1599 _c(' %s xcb_out;', self.c_type)
1600 for idx, f in enumerate(serial_fields):
1602 _c(' %s xcb_aux%d;' % (f.type.c_type, idx))
1604 _c(' printf("in function %s\\n");' % func_name)
1607 for field in wire_fields:
1608 if field.type.fixed_size():
1609 if field.type.is_expr:
1610 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr))
1611 elif field.type.is_pad:
1612 if field.type.nmemb == 1:
1613 _c(' xcb_out.%s = 0;', field.c_field_name)
1615 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
1617 if field.type.nmemb == 1:
1618 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
1620 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
1623 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
1624 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
1625 _c(' xcb_parts[3].iov_base = 0;')
1626 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
1628 # calls in order to free dyn. all. memory
1631 for field in param_fields:
1632 if not field.type.fixed_size():
1633 if not field.type.need_serialize:
1634 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1637 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1639 _c(' xcb_parts[%d].iov_base = (char *) 0;', count)
1640 idx = serial_fields.index(field)
1642 serialize_args = get_serialize_params(field.type,
1644 '&xcb_aux%d' % idx)[2]
1646 serialize_args = get_serialize_params(field.type,
1647 '&xcb_parts[%d].iov_base' % count,
1648 field.c_field_name)[2]
1650 serialize_args = reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
1651 _c(' xcb_parts[%d].iov_len = ', count)
1653 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
1654 free_calls.append(' free(xcb_parts[%d].iov_base);' % count)
1656 _c(' %s (%s);', field.type.c_unserialize_name, serialize_args)
1657 if field.type.is_list:
1658 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
1659 _c_accessor_get_expr(field.type.expr), field.type.member.c_wiretype)
1660 elif not field.type.need_serialize:
1661 # FIXME - _serialize()
1662 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);',
1663 count, 'Uh oh', field.type.c_wiretype)
1666 if not field.type.need_serialize:
1667 # the _serialize() function keeps track of padding automatically
1668 _c(' xcb_parts[%d].iov_base = 0;', count)
1669 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
1673 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
1675 # free dyn. all. data, if any
1676 for f in free_calls:
1678 _c(' return xcb_ret;')
1681 def _c_reply(self, name):
1683 Declares the function that returns the reply structure.
1685 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
1686 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
1687 spacing3 = ' ' * (len(self.c_reply_name) + 2)
1691 _h(' * Return the reply')
1692 _h(' * @param c The connection')
1693 _h(' * @param cookie The cookie')
1694 _h(' * @param e The xcb_generic_error_t supplied')
1696 _h(' * Returns the reply of the request asked by')
1698 _h(' * The parameter @p e supplied to this function must be NULL if')
1699 _h(' * %s(). is used.', self.c_unchecked_name)
1700 _h(' * Otherwise, it stores the error if any.')
1702 _h(' * The returned value must be freed by the caller using free().')
1706 _hc('/*****************************************************************************')
1708 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
1710 _hc(' ** @param xcb_connection_t%s *c', spacing1)
1711 _hc(' ** @param %s cookie', self.c_cookie_type)
1712 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
1713 _hc(' ** @returns %s *', self.c_reply_type)
1715 _hc(' *****************************************************************************/')
1717 _hc('%s *', self.c_reply_type)
1718 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
1719 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
1720 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
1721 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
1723 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
1726 def _c_opcode(name, opcode):
1728 Declares the opcode define for requests, events, and errors.
1732 _h('/** Opcode for %s. */', _n(name))
1733 _h('#define %s %s', _n(name).upper(), opcode)
1735 def _c_cookie(self, name):
1737 Declares the cookie type for a non-void request.
1742 _h(' * @brief %s', self.c_cookie_type)
1744 _h('typedef struct %s {', self.c_cookie_type)
1745 _h(' unsigned int sequence; /**< */')
1746 _h('} %s;', self.c_cookie_type)
1748 def c_request(self, name):
1750 Exported function that handles request declarations.
1752 _c_type_setup(self, name, ('request',))
1755 # Cookie type declaration
1756 _c_cookie(self, name)
1759 _c_opcode(name, self.opcode)
1761 # Request structure declaration
1765 _c_type_setup(self.reply, name, ('reply',))
1766 # Reply structure definition
1767 _c_complex(self.reply)
1768 # Request prototypes
1769 _c_request_helper(self, name, self.c_cookie_type, False, True)
1770 _c_request_helper(self, name, self.c_cookie_type, False, False)
1772 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
1773 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
1775 _c_accessors(self.reply, name + ('reply',), name)
1776 _c_reply(self, name)
1778 # Request prototypes
1779 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
1780 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
1782 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
1783 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
1786 def c_event(self, name):
1788 Exported function that handles event declarations.
1790 _c_type_setup(self, name, ('event',))
1793 _c_opcode(name, self.opcodes[name])
1795 if self.name == name:
1796 # Structure definition
1801 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
1803 def c_error(self, name):
1805 Exported function that handles error declarations.
1807 _c_type_setup(self, name, ('error',))
1810 _c_opcode(name, self.opcodes[name])
1812 if self.name == name:
1813 # Structure definition
1818 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
1821 # Main routine starts here
1823 # Must create an "output" dictionary before any xcbgen imports.
1824 output = {'open' : c_open,
1826 'simple' : c_simple,
1828 'struct' : c_struct,
1830 'request' : c_request,
1835 # Boilerplate below this point
1837 # Check for the argument that specifies path to the xcbgen python package.
1839 opts, args = getopt.getopt(sys.argv[1:], 'p:')
1840 except getopt.GetoptError, err:
1842 print 'Usage: c_client.py [-p path] file.xml'
1845 for (opt, arg) in opts:
1847 sys.path.append(arg)
1849 # Import the module class
1851 from xcbgen.state import Module
1854 print 'Failed to load the xcbgen Python package!'
1855 print 'Make sure that xcb/proto installed it on your Python path.'
1856 print 'If not, you will need to create a .pth file or define $PYTHONPATH'
1857 print 'to extend the path.'
1858 print 'Refer to the README file in xcb/proto for more info.'
1862 # Parse the xml header
1863 module = Module(args[0], output)
1865 # Build type-registry and resolve type dependencies