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',
19 _c_keywords = {'default' : '_default'}
27 # global variable to keep track of serializers and switch data types
28 # due to weird dependencies, I see no way to do this more elegant at the moment
29 finished_serializers = []
34 Writes the given line to the header file.
36 _hlines[_hlevel].append(fmt % args)
40 Writes the given line to the source file.
42 _clines[_clevel].append(fmt % args)
46 Writes the given line to both the header and source files.
51 # XXX See if this level thing is really necessary.
54 Changes the array that header lines are written to.
55 Supports writing different sections of the header file.
58 while len(_hlines) <= idx:
64 Changes the array that source lines are written to.
65 Supports writing to different sections of the source file.
68 while len(_clines) <= idx:
74 Does C-name conversion on a single string fragment.
75 Uses a regexp with some hard-coded special cases.
77 if str in _cname_special_cases:
78 return _cname_special_cases[str]
80 split = _cname_re.finditer(str)
81 name_parts = [match.group(0) for match in split]
82 return '_'.join(name_parts)
86 Checks for certain C++ reserved words and fixes them.
88 if str in _cplusplus_annoyances:
89 return _cplusplus_annoyances[str]
90 elif str in _c_keywords:
91 return _c_keywords[str]
97 Does C-name conversion on an extension name.
98 Has some additional special cases on top of _n_item.
100 if str in _extension_special_cases:
101 return _n_item(str).lower()
107 Does C-name conversion on a tuple of strings.
108 Different behavior depending on length of tuple, extension/not extension, etc.
109 Basically C-name converts the individual pieces, then joins with underscores.
114 parts = [list[0], _n_item(list[1])]
116 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
118 parts = [list[0]] + [_n_item(i) for i in list[1:]]
119 return '_'.join(parts).lower()
123 Does C-name conversion on a tuple of strings representing a type.
124 Same as _n but adds a "_t" on the end.
129 parts = [list[0], _n_item(list[1]), 't']
131 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
133 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
134 return '_'.join(parts).lower()
139 Exported function that handles module open.
140 Opens the files and writes out the auto-generated comment, header file includes, etc.
144 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
146 # Build the type-name collision avoidance table used by c_enum
147 build_collision_table()
153 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
154 _hc(' * Edit at your peril.')
159 _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
160 _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
164 _h('#ifndef __%s_H', _ns.header.upper())
165 _h('#define __%s_H', _ns.header.upper())
167 _h('#include "xcb.h"')
169 _c('#include <stdlib.h>')
170 _c('#include <string.h>')
171 _c('#include <assert.h>')
172 _c('#include "xcbext.h"')
173 _c('#include "%s.h"', _ns.header)
176 for (n, h) in self.imports:
177 _hc('#include "%s.h"', h)
180 _h('#ifdef __cplusplus')
186 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
187 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
189 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
192 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
196 Exported function that handles module close.
197 Writes out all the stored content lines, then closes the files.
204 _h('#ifdef __cplusplus')
216 hfile = open('%s.h' % _ns.header, 'w')
224 cfile = open('%s.c' % _ns.header, 'w')
231 def build_collision_table():
235 for v in module.types.values():
237 namecount[name] = (namecount.get(name) or 0) + 1
239 def c_enum(self, name):
241 Exported function that handles enum declarations.
245 if namecount[tname] > 1:
246 tname = _t(name + ('enum',))
250 _h('typedef enum %s {', tname)
252 count = len(self.values)
254 for (enam, eval) in self.values:
256 equals = ' = ' if eval != '' else ''
257 comma = ',' if count > 0 else ''
258 _h(' %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
262 def _c_type_setup(self, name, postfix):
264 Sets up all the C-related state by adding additional data fields to
265 all Field and Type objects. Here is where we figure out most of our
266 variable and function names.
268 Recurses into child fields and list member types.
270 # Do all the various names in advance
271 self.c_type = _t(name + postfix)
272 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
274 self.c_iterator_type = _t(name + ('iterator',))
275 self.c_next_name = _n(name + ('next',))
276 self.c_end_name = _n(name + ('end',))
278 self.c_request_name = _n(name)
279 self.c_checked_name = _n(name + ('checked',))
280 self.c_unchecked_name = _n(name + ('unchecked',))
281 self.c_reply_name = _n(name + ('reply',))
282 self.c_reply_type = _t(name + ('reply',))
283 self.c_cookie_type = _t(name + ('cookie',))
285 self.c_aux_name = _n(name + ('aux',))
286 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
287 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
288 self.c_serialize_name = _n(name + ('serialize',))
289 self.c_unserialize_name = _n(name + ('unserialize',))
290 if hasattr(self, 'reply'):
291 if self.reply is not None:
292 self.c_serialize_name = _n(name + ('reply', 'serialize'))
293 self.c_unserialize_name = _n(name + ('reply', 'unserialize'))
294 # indicates rare structs where variable size fields are followed fixed size fields
295 self.var_followed_by_fixed_fields = False
297 # whether a request or reply has a switch field
298 self.need_aux = False
299 self.need_serialize = False
301 self.need_serialize = True
302 self.c_container = 'struct'
303 for bitcase in self.bitcases:
304 bitcase.c_field_name = _cpp(bitcase.field_name)
305 _c_type_setup(bitcase.type, bitcase.field_type, ())
307 elif self.is_container:
309 self.c_container = 'union' if self.is_union else 'struct'
310 prev_varsized_field = None
311 prev_varsized_offset = 0
312 first_field_after_varsized = None
314 for field in self.fields:
315 _c_type_setup(field.type, field.field_type, ())
316 if field.type.is_list:
317 _c_type_setup(field.type.member, field.field_type, ())
318 # FIXME - structures with variable sized members, sort out when serialize() is needed
319 if (field.type.nmemb is None): # and not field.type.member.fixed_size():
320 self.need_serialize = True
322 field.c_field_type = _t(field.field_type)
323 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
324 field.c_field_name = _cpp(field.field_name)
325 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
326 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
327 if field.type.is_switch:
328 field.c_pointer = '*'
329 field.c_field_const_type = 'const ' + field.c_field_type
331 elif not field.type.fixed_size() and not field.type.is_bitcase:
332 self.need_serialize = True
334 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
335 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
336 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
337 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
338 # special case - c_field_name ends with _length as well
339 #if field.c_field_name.endswith('length'):
340 # c_field_name = field.c_field_name.rsplit('length', 1)
341 # field.c_field_name = c_field_name[0] + "_length"
342 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
344 field.prev_varsized_field = prev_varsized_field
345 field.prev_varsized_offset = prev_varsized_offset
347 if prev_varsized_offset == 0:
348 first_field_after_varsized = field
349 field.first_field_after_varsized = first_field_after_varsized
351 if field.type.fixed_size():
352 prev_varsized_offset += field.type.size
353 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
354 if not self.is_union:
355 self.need_serialize = True
356 self.var_followed_by_fixed_fields = True
357 # print "WARNING (%s): variable size field %s followed by fixed size field %s" % (
358 # self.c_type, prev_varsized_field.field_name, field.field_name)
360 self.last_varsized_field = field
361 prev_varsized_field = field
362 prev_varsized_offset = 0
364 # as switch does never appear at toplevel,
365 # continue here with type construction
367 if self.c_type not in finished_switch:
368 finished_switch.append(self.c_type)
369 # special: switch C structs get pointer fields for variable-sized members
371 # FIXME: declare switch (un)packing functions
372 _c_accessors(self, name, name)
374 # FIXME - in case of request/reply, serialize() is not always needed
375 if self.need_serialize and not self.is_bitcase:
376 if self.c_serialize_name not in finished_serializers:
377 finished_serializers.append(self.c_serialize_name)
382 def get_request_fields(self):
386 for field in self.fields:
388 # the field should appear as a parameter in the function call
389 param_fields.append(field)
390 if field.wire and not field.auto:
391 if field.type.fixed_size() and not self.is_switch:
392 # field in the xcb_out structure
393 wire_fields.append(field)
394 # fields like 'pad0' are skipped!
396 return (param_fields, wire_fields)
397 # get_request_fields()
399 def get_expr_fields(self):
400 # get the fields referenced by switch or list expression
401 def get_expr_field_names(expr):
403 if expr.lenfield_name is not None:
404 return [expr.lenfield_name]
406 # constant value expr
410 return get_expr_field_names(expr.rhs)
411 elif expr.op == 'popcount':
412 return get_expr_field_names(expr.rhs)
413 elif expr.op == 'sumof':
414 return [expr.lenfield_name]
415 elif expr.op == 'enumref':
418 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
419 # get_expr_field_names()
421 # resolve the field names with the parent structure(s)
422 unresolved_fields = get_expr_field_names(self.expr)
423 if unresolved_fields is None:
425 expr_fields = dict.fromkeys(unresolved_fields)
426 for p in reversed(self.parent):
427 parent_fields = dict((f.field_name, f) for f in p.fields)
428 for f in parent_fields.keys():
429 if f in unresolved_fields:
430 expr_fields[f] = parent_fields[f]
431 unresolved_fields.remove(f)
432 if len(unresolved_fields) == 0:
435 if None in expr_fields.values():
436 raise Exception("could not resolve all fields for %s" % self.name)
438 params = expr_fields.values()
442 def resolve_fields(anchestor, complex_obj=None):
443 """find fields referenced by anchestor or descendents with external scope"""
447 if complex_obj is None:
448 complex_obj = anchestor
449 for field in complex_obj.fields:
450 all_fields.append(field)
451 if field.type.is_switch or field.type.is_list:
452 expr_fields += get_expr_fields(field.type)
453 if field.type.is_container:
454 expr_fields += resolve_fields(anchestor, field.type)
455 # try to resolve expr fields
456 for e in expr_fields:
457 if e not in all_fields:
461 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
462 def add_param(params, param):
463 if param not in params:
466 param_fields, wire_fields = get_request_fields(self)
468 param_fields = get_expr_fields(self)
470 # _serialize function parameters
471 # cannot use set() for params, as series is important
473 if 'serialize' == context:
474 params.append(('void', '**', buffer_var))
475 elif 'unserialize' == context:
476 params.append(('const void', '*', buffer_var))
478 # look for special cases
479 unresolved_fields = resolve_fields(self)
480 for f in unresolved_fields:
481 add_param(params, (f.c_field_type, '', f.c_field_name))
483 # make sure all required length fields are present
484 for p in param_fields:
485 if p.visible and not p.wire and not p.auto:
486 typespec = p.c_field_type
488 add_param(params, (typespec, pointerspec, p.c_field_name))
490 # parameter fields if any
492 for p in get_expr_fields(self):
493 typespec = p.c_field_const_type
494 pointerspec = p.c_pointer
495 add_param(params, (typespec, pointerspec, p.c_field_name))
497 # aux argument - structure to be serialized
498 if 'serialize' == context:
499 add_param(params, ('const %s' % self.c_type, '*', aux_var))
500 elif 'unserialize' == context and self.is_switch:
501 add_param(params, ('%s' % self.c_type, '*', aux_var))
502 if not self.is_switch and 'serialize' == context:
503 for p in param_fields:
504 if not p.type.fixed_size():
505 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
506 return (param_fields, wire_fields, params)
507 # get_serialize_params()
509 def _c_serialize_helper_prefix(prefix):
510 # prefix is a list of (field_name, anchestor object) tuples
511 # concatenate field names
513 for name, obj in prefix:
515 prefix_str += '.' if (obj.is_bitcase and obj.has_name) else '->'
516 lenfield_prefix = '' if prefix_str.find('_aux')==0 else "_aux"
518 if lenfield_prefix != '':
519 lenfield_prefix += '->'
520 lenfield_prefix += prefix_str
521 return (prefix_str, lenfield_prefix)
522 # _c_serialize_helper_prefix
524 def _c_field_mapping(context, complex_type, prefix):
525 def get_prefix(field, prefix):
526 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
528 if context in ('serialize', 'unserialize'):
529 if field.type.fixed_size() or complex_type.is_switch:
530 prefix_str = '_aux->'
532 raise Exception("unknown context '%s' in c_field_mapping" % context)
535 def get_field_name(fields, complex_type, prefix):
536 for f in complex_type.fields:
537 prefix_str = get_prefix(f, prefix)
539 fname = "%s%s" % (prefix_str, f.c_field_name)
540 if fields.has_key(f.field_name):
543 raise Exception("field name %s has been registered before" % f.field_name)
544 fields[f.field_name] = (fname, f)
545 if f.type.is_container:
546 get_field_name(fields, f.type, prefix+[(f.c_field_name, f.type)])
549 # dict(field_name : (c_field_name, field))
551 get_field_name(fields, complex_type, prefix)
553 # switch: get the fields referenced by the switch expr as well
554 # these may not belong to any structure
555 if complex_type.is_switch:
557 # FIXME: fields += get_serialize_params(context, complex_type)
562 def _c_serialize_helper_insert_padding(context, code_lines, space):
563 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
564 code_lines.append('%s /* padding */' % space)
565 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
566 code_lines.append('%s if (0 != xcb_pad) {' % space)
568 if 'serialize' == context:
569 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
570 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
571 code_lines.append('%s xcb_parts_idx++;' % space)
572 elif 'unserialize' == context:
573 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
575 code_lines.append('%s xcb_buffer_len += xcb_pad;' % space)
576 code_lines.append('%s xcb_pad = 0;' % space)
577 code_lines.append('%s }' % space)
578 code_lines.append('%s xcb_block_len = 0;' % space)
581 # _c_serialize_helper_insert_padding()
583 def _c_serialize_helper_switch(context, self, complex_name,
584 code_lines, temp_vars,
587 switch_prefix = prefix + [(complex_name, self)]
588 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(switch_prefix)
589 switch_expr = _c_accessor_get_expr(self.expr)
591 for b in self.bitcases:
592 bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix_str)
593 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
594 b_prefix = switch_prefix
596 b_prefix = switch_prefix + [(b.c_field_name, b.type)]
597 _c_serialize_helper_fields(context, b.type,
598 code_lines, temp_vars,
602 code_lines.append(' }')
604 if 'serialize' == context:
605 count = _c_serialize_helper_insert_padding(context, code_lines, space)
606 if 'unserialize' == context:
608 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
609 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
612 # _c_serialize_helper_switch
614 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
615 # switch is handled by this function as a special case
616 param_fields, wire_fields, params = get_serialize_params(context, self)
617 args = get_expr_fields(field.type)
618 field_mapping = _c_field_mapping(context, self, prefix)
620 # determine which params to pass to _unserialize() and their prefixes
621 switch_len_fields = resolve_fields(self, field.type)
622 bitcase_unresolved = resolve_fields(self, self)
623 if len(bitcase_unresolved) != 0:
624 raise Exception('unresolved fields within bitcase is not supported at this point')
626 for a in switch_len_fields:
627 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
629 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
630 # switch_field_name = field_mapping[field.field_name][0]
631 # call _unserialize() to determine the actual size
632 length = "%s(xcb_tmp, %s&%s)" % (field.type.c_unserialize_name,
633 c_field_names, c_switch_variable) #switch_field_name)
635 # _c_serialize_helper_switch_field()
637 def _c_serialize_helper_list_field(context, self, field,
638 code_lines, temp_vars,
641 helper function for (un)serialize to cope with lists of variable length
643 expr = field.type.expr
644 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
645 param_fields, wire_fields, params = get_serialize_params('unserialize', self)
646 param_names = [p[2] for p in params]
648 # look if the list's lenfield is a struct member or a function argument
649 # special case: if the list has a length field, its name will be returned
650 # unchanged by calling c_accessor_get_length(expr)
651 if expr.lenfield_name == _c_accessor_get_length(expr):
652 if expr.lenfield_name in param_names:
653 # the length field appears as separate argument in unserialize,
654 # so no need for a prefix
656 sep = '.' if (self.is_bitcase and self.has_name) else '->'
657 list_length = _c_accessor_get_expr(expr, lenfield_prefix, sep)
659 # default: list with fixed size elements
660 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
661 # list with variable-sized elements
662 if field.type.size is None:
664 if 'unserialize' == context:
665 int_i = ' unsigned int i;'
666 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
667 if int_i not in temp_vars:
668 temp_vars.append(int_i)
669 if xcb_tmp_len not in temp_vars:
670 temp_vars.append(xcb_tmp_len)
671 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
672 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
673 (space, field.type.c_unserialize_name))
674 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
675 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
676 code_lines.append("%s }" % space)
677 elif 'serialize' == context:
678 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
679 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
680 code_lines.append('%s for(i=0; i<%s; i++) { '
681 % (space, _c_accessor_get_expr(expr, lenfield_prefix, sep)))
682 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_unserialize_name))
683 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
684 code_lines.append('%s }' % space)
685 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
688 # _c_serialize_helper_list_field()
690 def _c_serialize_helper_fields_fixed_size(context, self, field,
691 code_lines, temp_vars,
693 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
694 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
696 length = "sizeof(%s)" % field.c_field_type
698 if 'unserialize' == context:
699 value = ' %s%s = *(%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
700 if field.type.is_pad and field.type.nmemb > 1:
702 for i in range(field.type.nmemb):
703 code_lines.append('%s %s%s[%d] = *(%s *)xcb_tmp;' %
704 (space, prefix_str, field.c_field_name, i, field.c_field_type))
705 length += " * %d" % field.type.nmemb
707 if field.type.is_list:
708 raise Exception('list with fixed number of elemens unhandled in _unserialize()')
709 elif 'serialize' == context:
710 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
712 if field.type.is_expr:
713 # need to register a temporary variable for the expression
714 if field.type.c_type is None:
715 raise Exception("type for field '%s' (expression '%s') unkown" %
716 (field.field_name, _c_accessor_get_expr(field.type.expr)))
717 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, field.field_name,
718 _c_accessor_get_expr(field.type.expr, prefix)))
719 value += "&xcb_expr_%s;" % field.field_name
721 elif field.type.is_pad:
722 if field.type.nmemb == 1:
725 # FIXME - possible segmentation fault!!
726 value = ' memset(xcb_parts[xcb_parts_idx].iov_base, 0, %d);' % field.type.nmemb
727 length += "*%d" % field.type.nmemb
730 # non-list type with fixed size
731 if field.type.nmemb == 1:
732 value += "&%s%s;" % (prefix_str, field.c_field_name)
733 # list with nmemb (fixed size) elements
735 value += '%s%s;' % (prefix_str, field.c_field_name)
736 length = '%d' % field.type.nmemb
738 return (value, length)
739 # _c_serialize_helper_fields_fixed_size()
741 def _c_serialize_helper_fields_variable_size(context, self, field,
742 code_lines, temp_vars,
744 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
746 if 'unserialize' == context:
748 elif 'serialize' == context:
749 address_of = '&' if (self.is_bitcase and self.has_name) else ''
750 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s%s%s;' % (address_of, prefix_str, field.c_field_name)
753 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
754 code_lines.append('%s /* %s */' % (space, field.c_field_name))
756 if field.type.is_list:
757 length = _c_serialize_helper_list_field(context, self, field,
758 code_lines, temp_vars,
760 elif field.type.is_switch:
761 prev = filter(lambda x: x.find('xcb_switch_field'), temp_vars)
762 var_name = 'xcb_switch_field%d' % len(prev)
763 temp_vars.append(' %s %s;' % (field.type.c_type, var_name))
764 length = _c_serialize_helper_switch_field(context, self, field, var_name, prefix)
766 length = "%s(xcb_tmp)" % (field.type.c_unserialize_name)
768 return (value, length)
769 # _c_serialize_helper_fields_variable_size
771 def _c_serialize_helper_fields(context, self,
772 code_lines, temp_vars,
773 space, prefix, is_bitcase):
777 for field in self.fields:
778 if not ((field.wire and not field.auto) or field.visible):
781 # switch/bitcase: fixed size fields must be considered explicitly
782 if field.type.fixed_size():
784 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
785 code_lines, temp_vars,
790 # fields with variable size
792 # switch/bitcase: always calculate padding before and after variable sized fields
793 if need_padding or is_bitcase:
794 _c_serialize_helper_insert_padding(context, code_lines, space)
796 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
797 code_lines, temp_vars,
800 # save (un)serialization C code
802 code_lines.append('%s%s' % (space, value))
803 if field.type.fixed_size() and is_bitcase:
804 code_lines.append('%s xcb_block_len += %s;' % (space, length))
805 if 'unserialize' == context:
806 code_lines.append('%s xcb_tmp += %s;' % (space, length))
810 code_lines.append('%s xcb_block_len = %s;' % (space, length))
811 if 'unserialize' == context:
812 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
813 if 'serialize' == context:
815 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_block_len;' % space)
816 code_lines.append('%s xcb_parts_idx++;' % space)
821 # _c_serialize_helper_fields()
823 def _c_serialize_helper(context, complex_type,
824 code_lines, temp_vars,
825 space='', prefix=[]):
827 if hasattr(complex_type, 'type'):
828 self = complex_type.type
829 complex_name = complex_type.name
832 complex_name = '_aux'
834 # special case: switch is serialized by evaluating each bitcase separately
836 count += _c_serialize_helper_switch(context, self, complex_name,
837 code_lines, temp_vars,
840 # all other data types can be evaluated one field a time
842 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
843 if 'unserialize' == context:
844 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
845 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
846 _c_serialize_helper_insert_padding(context, code_lines, space)
848 count += _c_serialize_helper_fields(context, self,
849 code_lines, temp_vars,
850 space, prefix, False)
852 count += _c_serialize_helper_insert_padding(context, code_lines, space)
855 # _c_serialize_helper()
857 def _c_serialize(self):
862 # _serialize() returns the buffer size
865 variable_size_fields = 0
866 # maximum space required for type definition of function arguments
868 param_fields, wire_fields, params = get_serialize_params('serialize', self)
870 # determine N(variable_fields)
871 for field in param_fields:
872 # if self.is_switch, treat all fields as if they are variable sized
873 if not field.type.fixed_size() or self.is_switch:
874 variable_size_fields += 1
875 # determine maxtypelen
877 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
880 for idx, p in enumerate(params):
882 typespec, pointerspec, field_name = p
883 indent = ' '*(len(self.c_serialize_name)+2)
884 # p==0: function declaration
886 line = "%s (" % self.c_serialize_name
888 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
889 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
890 if idx < len(params)-1:
897 if not self.is_switch:
898 _c(' %s *xcb_out = *_buffer;', self.c_type)
899 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
900 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
902 _c(' char *xcb_out = *_buffer;')
903 _c(' unsigned int xcb_buffer_len = 0;')
904 if variable_size_fields > 0:
907 count =_c_serialize_helper('serialize', self,
908 code_lines, temp_vars)
909 # update variable size fields
910 variable_size_fields = count
911 temp_vars.append(' unsigned int xcb_pad = 0;')
912 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
913 temp_vars.append(' struct iovec xcb_parts[%d];' % (count+1))
914 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
915 temp_vars.append(' unsigned int xcb_block_len = 0;')
916 temp_vars.append(' unsigned int i;')
917 temp_vars.append(' char *xcb_tmp;')
923 if variable_size_fields > 0:
928 # variable sized fields have been collected, now
929 # allocate memory and copy everything into a continuous memory area
930 _c(' if (NULL == xcb_out) {')
931 _c(' /* allocate memory */')
932 _c(' *_buffer = malloc(xcb_buffer_len);')
933 _c(' xcb_out = *_buffer;')
937 # fill in struct members
938 if not self.is_switch:
939 if len(wire_fields)>0:
940 _c(' *xcb_out = *_aux;')
942 # copy variable size fields into the buffer
943 if variable_size_fields > 0:
945 if not self.is_switch:
946 _c(' xcb_tmp = (char*)++xcb_out;')
947 _c(' xcb_tmp += xcb_out_pad;')
949 _c(' xcb_tmp = xcb_out;')
951 # variable sized fields
952 _c(' for(i=0; i<xcb_parts_idx; i++) {')
953 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
954 _c(' xcb_tmp += xcb_parts[i].iov_len;')
957 _c(' return xcb_buffer_len;')
961 def _c_unserialize(self):
967 # _unserialize() returns the buffer size as well
971 variable_size_fields = 0
972 # maximum space required for type definition of function arguments
974 param_fields, wire_fields, params = get_serialize_params('unserialize', self)
976 # determine N(variable_fields)
977 for field in param_fields:
978 # if self.is_switch, treat all fields as if they are variable sized
979 if not field.type.fixed_size() or self.is_switch:
980 variable_size_fields += 1
981 # determine maxtypelen
983 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
986 for idx, p in enumerate(params):
988 typespec, pointerspec, field_name = p
989 indent = ' '*(len(self.c_unserialize_name)+2)
990 # p==0: function declaration
992 line = "%s (" % self.c_unserialize_name
994 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
995 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
996 if idx < len(params)-1:
1003 _c(' char *xcb_tmp = (char *)_buffer;')
1004 if not self.is_switch:
1005 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1006 _c(' unsigned int xcb_buffer_len = 0;')
1007 _c(' unsigned int xcb_block_len = 0;')
1008 _c(' unsigned int xcb_pad = 0;')
1012 _c_serialize_helper('unserialize', self,
1013 code_lines, temp_vars)
1018 for l in code_lines:
1021 _c(' return xcb_buffer_len;')
1025 def _c_iterator_get_end(field, accum):
1027 Figures out what C code is needed to find the end of a variable-length structure field.
1028 For nested structures, recurses into its last variable-sized field.
1029 For lists, calls the end function
1031 if field.type.is_container:
1032 accum = field.c_accessor_name + '(' + accum + ')'
1033 if field.type.fixed_size():
1034 print "iterator_get_end()", accum, field.c_field_name
1035 # XXX there could be fixed-length fields at the end
1036 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1037 if field.type.is_list:
1038 # XXX we can always use the first way
1039 if field.type.member.is_simple:
1040 return field.c_end_name + '(' + accum + ')'
1042 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1044 def _c_iterator(self, name):
1046 Declares the iterator structure and next/end functions for a given type.
1051 _h(' * @brief %s', self.c_iterator_type)
1053 _h('typedef struct %s {', self.c_iterator_type)
1054 _h(' %s *data; /**< */', self.c_type)
1055 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1056 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1057 _h('} %s;', self.c_iterator_type)
1063 _h(' * Get the next element of the iterator')
1064 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1066 _h(' * Get the next element in the iterator. The member rem is')
1067 _h(' * decreased by one. The member data points to the next')
1068 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1072 _hc('/*****************************************************************************')
1074 _hc(' ** void %s', self.c_next_name)
1076 _hc(' ** @param %s *i', self.c_iterator_type)
1077 _hc(' ** @returns void')
1079 _hc(' *****************************************************************************/')
1082 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1083 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1086 if not self.fixed_size():
1087 _c(' %s *R = i->data;', self.c_type)
1088 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1090 _c(' i->data = (%s *) child.data;', self.c_type)
1091 _c(' i->index = child.index;')
1095 _c(' i->index += sizeof(%s);', self.c_type)
1101 _h(' * Return the iterator pointing to the last element')
1102 _h(' * @param i An %s', self.c_iterator_type)
1103 _h(' * @return The iterator pointing to the last element')
1105 _h(' * Set the current element in the iterator to the last element.')
1106 _h(' * The member rem is set to 0. The member data points to the')
1107 _h(' * last element.')
1111 _hc('/*****************************************************************************')
1113 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1115 _hc(' ** @param %s i', self.c_iterator_type)
1116 _hc(' ** @returns xcb_generic_iterator_t')
1118 _hc(' *****************************************************************************/')
1120 _hc('xcb_generic_iterator_t')
1121 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1122 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1124 _c(' xcb_generic_iterator_t ret;')
1126 if self.fixed_size():
1127 _c(' ret.data = i.data + i.rem;')
1128 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1131 _c(' while(i.rem > 0)')
1132 _c(' %s(&i);', self.c_next_name)
1133 _c(' ret.data = i.data;')
1134 _c(' ret.rem = i.rem;')
1135 _c(' ret.index = i.index;')
1140 def _c_accessor_get_length(expr, prefix='', sep='->'):
1142 Figures out what C code is needed to get a length field.
1143 For fields that follow a variable-length field, use the accessor.
1144 Otherwise, just reference the structure field directly.
1146 prefarrow = '' if prefix == '' else prefix + sep
1148 if expr.lenfield != None and expr.lenfield.prev_varsized_field != None:
1149 # special case: variable and fixed size fields are intermixed
1150 retval = expr.lenfield.c_accessor_name + '(' + prefix + ')'
1151 if prefix in ('', '_aux'):
1152 prefix_str = '' if prefix=='' else '%s' % (prefarrow)
1153 retval = '%s%s' % (prefix_str, expr.lenfield_name)
1155 elif expr.lenfield_name != None:
1156 if prefix.endswith(sep):
1157 return prefix + expr.lenfield_name
1159 return prefarrow + expr.lenfield_name
1161 return str(expr.nmemb)
1163 def _c_accessor_get_expr(expr, prefix='', sep='->'):
1165 Figures out what C code is needed to get the length of a list field.
1166 Recurses for math operations.
1167 Returns bitcount for value-mask fields.
1168 Otherwise, uses the value of the length field.
1170 lenexp = _c_accessor_get_length(expr, prefix, sep)
1173 return '(' + '~' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1174 elif expr.op == 'popcount':
1175 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1176 elif expr.op == 'enumref':
1177 enum_name = expr.lenfield_type.name
1178 constant_name = expr.lenfield_name
1179 c_name = _n(enum_name + (constant_name,)).upper()
1181 elif expr.op == 'sumof':
1182 # 1. locate the referenced list object
1183 list_obj = expr.lenfield_type
1185 for f in expr.lenfield_parent.fields:
1186 if f.field_name == expr.lenfield_name:
1190 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1191 if prefix != '' and not prefix.endswith(sep):
1193 list_name = "%s%s" % (prefix, field.c_field_name)
1194 c_length_func = "%s(%s%s)" % (field.c_length_name, prefix, field.c_field_name)
1196 c_length_func = _c_accessor_get_expr(field.type.expr, prefix='', sep='')
1197 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1198 elif expr.op != None:
1199 return '(' + _c_accessor_get_expr(expr.lhs, prefix, sep) + ' ' + expr.op + ' ' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1201 return 'xcb_popcount(' + lenexp + ')'
1203 return lenexp + '/* bla */'
1205 def _c_accessors_field(self, field):
1207 Declares the accessor functions for a non-list field that follows a variable-length field.
1209 if field.type.is_simple:
1212 _hc('/*****************************************************************************')
1214 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1216 _hc(' ** @param const %s *R', self.c_type)
1217 _hc(' ** @returns %s', field.c_field_type)
1219 _hc(' *****************************************************************************/')
1221 _hc('%s', field.c_field_type)
1222 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1223 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1225 if field.prev_varsized_field is None:
1226 _c(' return (%s *) (R + 1);', field.c_field_type)
1228 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1229 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1230 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1235 _hc('/*****************************************************************************')
1237 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1239 _hc(' ** @param const %s *R', self.c_type)
1240 _hc(' ** @returns %s *', field.c_field_type)
1242 _hc(' *****************************************************************************/')
1244 _hc('%s *', field.c_field_type)
1245 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1246 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1248 if field.prev_varsized_field is None:
1249 _c(' return (%s *) (R + 1);', field.c_field_type)
1251 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1252 _c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1253 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1256 def _c_accessors_list(self, field):
1258 Declares the accessor functions for a list field.
1259 Declares a direct-accessor function only if the list members are fixed size.
1260 Declares length and get-iterator functions always.
1266 if list.member.fixed_size():
1269 _hc('/*****************************************************************************')
1271 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1273 _hc(' ** @param const %s *R', self.c_type)
1274 _hc(' ** @returns %s *', field.c_field_type)
1276 _hc(' *****************************************************************************/')
1278 _hc('%s *', field.c_field_type)
1279 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1280 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1283 if field.prev_varsized_field is None:
1284 _c(' return (%s *) (R + 1);', field.c_field_type)
1286 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1287 _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)
1293 _hc('/*****************************************************************************')
1295 _hc(' ** int %s', field.c_length_name)
1297 _hc(' ** @param const %s *R', self.c_type)
1298 _hc(' ** @returns int')
1300 _hc(' *****************************************************************************/')
1303 _h('%s (const %s *R /**< */);', field.c_length_name, self.c_type)
1304 _c('%s (const %s *R /**< */)', field.c_length_name, self.c_type)
1306 _c(' return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1309 if field.type.member.is_simple:
1312 _hc('/*****************************************************************************')
1314 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1316 _hc(' ** @param const %s *R', self.c_type)
1317 _hc(' ** @returns xcb_generic_iterator_t')
1319 _hc(' *****************************************************************************/')
1321 _hc('xcb_generic_iterator_t')
1322 _h('%s (const %s *R /**< */);', field.c_end_name, self.c_type)
1323 _c('%s (const %s *R /**< */)', field.c_end_name, self.c_type)
1325 _c(' xcb_generic_iterator_t i;')
1327 if field.prev_varsized_field == None:
1328 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1330 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1331 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1334 _c(' i.index = (char *) i.data - (char *) R;')
1341 _hc('/*****************************************************************************')
1343 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1345 _hc(' ** @param const %s *R', self.c_type)
1346 _hc(' ** @returns %s', field.c_iterator_type)
1348 _hc(' *****************************************************************************/')
1350 _hc('%s', field.c_iterator_type)
1351 _h('%s (const %s *R /**< */);', field.c_iterator_name, self.c_type)
1352 _c('%s (const %s *R /**< */)', field.c_iterator_name, self.c_type)
1354 _c(' %s i;', field.c_iterator_type)
1356 if field.prev_varsized_field == None:
1357 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1359 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1360 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', field.c_field_type, field.c_field_type)
1362 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1363 _c(' i.index = (char *) i.data - (char *) R;')
1367 def _c_accessors(self, name, base):
1369 Declares the accessor functions for the fields of a structure.
1371 for field in self.fields:
1372 # no accessors for switch -
1373 # switch always needs to be unserialized explicitly
1376 if field.type.is_list and not field.type.fixed_size():
1377 _c_accessors_list(self, field)
1378 elif field.prev_varsized_field != None or not field.type.fixed_size():
1379 _c_accessors_field(self, field)
1381 def c_simple(self, name):
1383 Exported function that handles cardinal type declarations.
1384 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1386 _c_type_setup(self, name, ())
1388 if (self.name != name):
1393 _h('typedef %s %s;', _t(self.name), my_name)
1396 _c_iterator(self, name)
1398 def _c_complex(self):
1400 Helper function for handling all structure types.
1401 Called for all structs, requests, replies, events, errors.
1406 _h(' * @brief %s', self.c_type)
1408 _h('typedef %s %s {', self.c_container, self.c_type)
1414 for field in self.fields:
1415 if not field.type.fixed_size() and not self.is_switch:
1416 varfield = field.c_field_name
1418 if varfield != None and not field.type.is_pad and field.wire:
1419 errmsg = '%s: warning: variable field %s followed by fixed field %s\n' % (self.c_type, varfield, field.c_field_name)
1420 sys.stderr.write(errmsg)
1423 struct_fields.append(field)
1425 for field in struct_fields:
1426 length = len(field.c_field_type)
1427 # account for '*' pointer_spec
1428 if not field.type.fixed_size():
1430 maxtypelen = max(maxtypelen, length)
1432 def _c_complex_field(self, field, space=''):
1433 if (field.type.fixed_size() or
1434 # in case of switch with switch children, don't make the field a pointer
1435 # necessary for unserialize to work
1436 (self.is_switch and field.type.is_switch)):
1437 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1438 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1440 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1441 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1443 if not self.is_switch:
1444 for field in struct_fields:
1445 _c_complex_field(self, field)
1447 for b in self.bitcases:
1450 _h(' struct _%s {', b.c_field_name)
1452 for field in b.type.fields:
1453 _c_complex_field(self, field, space)
1455 _h(' } %s;', b.c_field_name)
1457 _h('} %s;', self.c_type)
1459 def c_struct(self, name):
1461 Exported function that handles structure declarations.
1463 _c_type_setup(self, name, ())
1465 _c_accessors(self, name, name)
1466 _c_iterator(self, name)
1468 def c_union(self, name):
1470 Exported function that handles union declarations.
1472 _c_type_setup(self, name, ())
1474 _c_iterator(self, name)
1476 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1478 Declares a request function.
1481 # Four stunningly confusing possibilities here:
1484 # ------------------------------
1486 # 0 flag CHECKED flag Normal Mode
1487 # void_cookie req_cookie
1488 # ------------------------------
1489 # "req_checked" "req_unchecked"
1490 # CHECKED flag 0 flag Abnormal Mode
1491 # void_cookie req_cookie
1492 # ------------------------------
1495 # Whether we are _checked or _unchecked
1496 checked = void and not regular
1497 unchecked = not void and not regular
1499 # What kind of cookie we return
1500 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1502 # What flag is passed to xcb_request
1503 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1505 # Global extension id variable or NULL for xproto
1506 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1508 # What our function name is
1509 func_name = self.c_request_name if not aux else self.c_aux_name
1511 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1513 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1517 maxtypelen = len('xcb_connection_t')
1520 for field in self.fields:
1522 # The field should appear as a call parameter
1523 param_fields.append(field)
1524 if field.wire and not field.auto:
1525 # We need to set the field up in the structure
1526 wire_fields.append(field)
1527 if field.type.need_serialize:
1528 serial_fields.append(field)
1530 for field in param_fields:
1531 c_field_const_type = field.c_field_const_type
1532 if field.type.need_serialize and not aux:
1533 c_field_const_type = "const void"
1534 if len(c_field_const_type) > maxtypelen:
1535 maxtypelen = len(c_field_const_type)
1541 _h(' * Delivers a request to the X server')
1542 _h(' * @param c The connection')
1543 _h(' * @return A cookie')
1545 _h(' * Delivers a request to the X server.')
1548 _h(' * This form can be used only if the request will not cause')
1549 _h(' * a reply to be generated. Any returned error will be')
1550 _h(' * saved for handling by xcb_request_check().')
1552 _h(' * This form can be used only if the request will cause')
1553 _h(' * a reply to be generated. Any returned error will be')
1554 _h(' * placed in the event queue.')
1558 _hc('/*****************************************************************************')
1560 _hc(' ** %s %s', cookie_type, func_name)
1563 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1564 _hc(' ** @param xcb_connection_t%s *c', spacing)
1566 for field in param_fields:
1567 c_field_const_type = field.c_field_const_type
1568 if field.type.need_serialize and not aux:
1569 c_field_const_type = "const void"
1570 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1571 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1573 _hc(' ** @returns %s', cookie_type)
1575 _hc(' *****************************************************************************/')
1577 _hc('%s', cookie_type)
1579 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1580 comma = ',' if len(param_fields) else ');'
1581 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1582 comma = ',' if len(param_fields) else ')'
1583 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1585 func_spacing = ' ' * (len(func_name) + 2)
1586 count = len(param_fields)
1587 for field in param_fields:
1589 c_field_const_type = field.c_field_const_type
1590 c_pointer = field.c_pointer
1591 if field.type.need_serialize and not aux:
1592 c_field_const_type = "const void"
1594 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1595 comma = ',' if count else ');'
1596 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1597 spacing, c_pointer, field.c_field_name, comma)
1598 comma = ',' if count else ')'
1599 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1600 spacing, c_pointer, field.c_field_name, comma)
1603 if self.var_followed_by_fixed_fields:
1604 count += len(wire_fields)*2
1605 for field in param_fields:
1606 if not field.type.fixed_size():
1608 if field.type.need_serialize:
1609 # _serialize() keeps track of padding automatically
1613 _c(' static const xcb_protocol_request_t xcb_req = {')
1614 _c(' /* count */ %d,', count)
1615 _c(' /* ext */ %s,', func_ext_global)
1616 _c(' /* opcode */ %s,', self.c_request_name.upper())
1617 _c(' /* isvoid */ %d', 1 if void else 0)
1621 _c(' struct iovec xcb_parts[%d];', count + 2)
1622 _c(' %s xcb_ret;', func_cookie)
1623 if not self.var_followed_by_fixed_fields:
1624 _c(' %s xcb_out;', self.c_type)
1626 for idx, f in enumerate(serial_fields):
1628 _c(' %s xcb_aux%d;' % (f.type.c_type, idx))
1630 _c(' void *xcb_aux%d = 0;' % (idx))
1632 # _c(' printf("in function %s\\n");' % func_name)
1635 if not self.var_followed_by_fixed_fields:
1636 for field in wire_fields:
1637 if field.type.fixed_size():
1638 if field.type.is_expr:
1639 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr))
1640 elif field.type.is_pad:
1641 if field.type.nmemb == 1:
1642 _c(' xcb_out.%s = 0;', field.c_field_name)
1644 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
1646 if field.type.nmemb == 1:
1647 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
1649 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
1652 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
1653 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
1654 _c(' xcb_parts[3].iov_base = 0;')
1655 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
1657 # calls in order to free dyn. all. memory
1659 if not self.var_followed_by_fixed_fields:
1663 var_size_fields = param_fields
1664 if self.var_followed_by_fixed_fields:
1665 var_size_fields = wire_fields + param_fields
1666 for field in var_size_fields:
1667 if field.type.fixed_size and self.var_followed_by_fixed_fields:
1668 _c(' xcb_parts[%d].iov_base = (char *) &%s;', count, field.c_field_name)
1669 _c(' xcb_parts[%d].iov_len = sizeof(%s);', count, field.type.c_type)
1671 if not field.type.fixed_size():
1672 # default: simple cast to char *
1673 if not field.type.need_serialize:
1674 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1675 if field.type.is_list:
1676 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
1677 _c_accessor_get_expr(field.type.expr), field.type.member.c_wiretype)
1679 # not supposed to happen
1680 raise Exception("unhandled variable size field %s" % field.c_field_name)
1681 #_c('/* eeeeeeeeeee */')
1684 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1685 idx = serial_fields.index(field)
1687 serialize_args = get_serialize_params('unserialize', field.type,
1689 '&xcb_aux%d' % idx)[2]
1691 serialize_args = get_serialize_params('serialize', field.type,
1693 field.c_field_name)[2]
1694 serialize_args = reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
1695 _c(' xcb_parts[%d].iov_len = ', count)
1697 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
1698 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
1699 free_calls.append(' free(xcb_aux%d);' % idx)
1701 _c(' %s (%s);', field.type.c_unserialize_name, serialize_args)
1705 if not field.type.need_serialize:
1706 # the _serialize() function keeps track of padding automatically
1707 _c(' xcb_parts[%d].iov_base = 0;', count)
1708 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
1712 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
1714 # free dyn. all. data, if any
1715 for f in free_calls:
1717 _c(' return xcb_ret;')
1720 def _c_reply(self, name):
1722 Declares the function that returns the reply structure.
1724 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
1725 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
1726 spacing3 = ' ' * (len(self.c_reply_name) + 2)
1730 _h(' * Return the reply')
1731 _h(' * @param c The connection')
1732 _h(' * @param cookie The cookie')
1733 _h(' * @param e The xcb_generic_error_t supplied')
1735 _h(' * Returns the reply of the request asked by')
1737 _h(' * The parameter @p e supplied to this function must be NULL if')
1738 _h(' * %s(). is used.', self.c_unchecked_name)
1739 _h(' * Otherwise, it stores the error if any.')
1741 _h(' * The returned value must be freed by the caller using free().')
1745 _hc('/*****************************************************************************')
1747 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
1749 _hc(' ** @param xcb_connection_t%s *c', spacing1)
1750 _hc(' ** @param %s cookie', self.c_cookie_type)
1751 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
1752 _hc(' ** @returns %s *', self.c_reply_type)
1754 _hc(' *****************************************************************************/')
1756 _hc('%s *', self.c_reply_type)
1757 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
1758 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
1759 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
1760 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
1762 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
1765 def _c_opcode(name, opcode):
1767 Declares the opcode define for requests, events, and errors.
1771 _h('/** Opcode for %s. */', _n(name))
1772 _h('#define %s %s', _n(name).upper(), opcode)
1774 def _c_cookie(self, name):
1776 Declares the cookie type for a non-void request.
1781 _h(' * @brief %s', self.c_cookie_type)
1783 _h('typedef struct %s {', self.c_cookie_type)
1784 _h(' unsigned int sequence; /**< */')
1785 _h('} %s;', self.c_cookie_type)
1787 def c_request(self, name):
1789 Exported function that handles request declarations.
1791 _c_type_setup(self, name, ('request',))
1794 # Cookie type declaration
1795 _c_cookie(self, name)
1798 _c_opcode(name, self.opcode)
1800 # Request structure declaration
1804 _c_type_setup(self.reply, name, ('reply',))
1805 # Reply structure definition
1806 _c_complex(self.reply)
1807 # Request prototypes
1808 _c_request_helper(self, name, self.c_cookie_type, False, True)
1809 _c_request_helper(self, name, self.c_cookie_type, False, False)
1811 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
1812 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
1814 _c_accessors(self.reply, name + ('reply',), name)
1815 _c_reply(self, name)
1817 # Request prototypes
1818 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
1819 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
1821 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
1822 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
1825 def c_event(self, name):
1827 Exported function that handles event declarations.
1829 _c_type_setup(self, name, ('event',))
1832 _c_opcode(name, self.opcodes[name])
1834 if self.name == name:
1835 # Structure definition
1840 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
1842 def c_error(self, name):
1844 Exported function that handles error declarations.
1846 _c_type_setup(self, name, ('error',))
1849 _c_opcode(name, self.opcodes[name])
1851 if self.name == name:
1852 # Structure definition
1857 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
1860 # Main routine starts here
1862 # Must create an "output" dictionary before any xcbgen imports.
1863 output = {'open' : c_open,
1865 'simple' : c_simple,
1867 'struct' : c_struct,
1869 'request' : c_request,
1874 # Boilerplate below this point
1876 # Check for the argument that specifies path to the xcbgen python package.
1878 opts, args = getopt.getopt(sys.argv[1:], 'p:')
1879 except getopt.GetoptError, err:
1881 print 'Usage: c_client.py [-p path] file.xml'
1884 for (opt, arg) in opts:
1886 sys.path.append(arg)
1888 # Import the module class
1890 from xcbgen.state import Module
1893 print 'Failed to load the xcbgen Python package!'
1894 print 'Make sure that xcb/proto installed it on your Python path.'
1895 print 'If not, you will need to create a .pth file or define $PYTHONPATH'
1896 print 'to extend the path.'
1897 print 'Refer to the README file in xcb/proto for more info.'
1901 # Parse the xml header
1902 module = Module(args[0], output)
1904 # Build type-registry and resolve type dependencies