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
28 # switch data types due to weird dependencies
29 finished_serializers = []
35 Writes the given line to the header file.
37 _hlines[_hlevel].append(fmt % args)
41 Writes the given line to the source file.
43 _clines[_clevel].append(fmt % args)
47 Writes the given line to both the header and source files.
52 # XXX See if this level thing is really necessary.
55 Changes the array that header lines are written to.
56 Supports writing different sections of the header file.
59 while len(_hlines) <= idx:
65 Changes the array that source lines are written to.
66 Supports writing to different sections of the source file.
69 while len(_clines) <= idx:
75 Does C-name conversion on a single string fragment.
76 Uses a regexp with some hard-coded special cases.
78 if str in _cname_special_cases:
79 return _cname_special_cases[str]
81 split = _cname_re.finditer(str)
82 name_parts = [match.group(0) for match in split]
83 return '_'.join(name_parts)
87 Checks for certain C++ reserved words and fixes them.
89 if str in _cplusplus_annoyances:
90 return _cplusplus_annoyances[str]
91 elif str in _c_keywords:
92 return _c_keywords[str]
98 Does C-name conversion on an extension name.
99 Has some additional special cases on top of _n_item.
101 if str in _extension_special_cases:
102 return _n_item(str).lower()
108 Does C-name conversion on a tuple of strings.
109 Different behavior depending on length of tuple, extension/not extension, etc.
110 Basically C-name converts the individual pieces, then joins with underscores.
115 parts = [list[0], _n_item(list[1])]
117 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
119 parts = [list[0]] + [_n_item(i) for i in list[1:]]
120 return '_'.join(parts).lower()
124 Does C-name conversion on a tuple of strings representing a type.
125 Same as _n but adds a "_t" on the end.
130 parts = [list[0], _n_item(list[1]), 't']
132 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
134 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
135 return '_'.join(parts).lower()
140 Exported function that handles module open.
141 Opens the files and writes out the auto-generated comment, header file includes, etc.
145 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
147 # Build the type-name collision avoidance table used by c_enum
148 build_collision_table()
154 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
155 _hc(' * Edit at your peril.')
160 _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
161 _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
165 _h('#ifndef __%s_H', _ns.header.upper())
166 _h('#define __%s_H', _ns.header.upper())
168 _h('#include "xcb.h"')
170 _c('#include <stdlib.h>')
171 _c('#include <string.h>')
172 _c('#include <assert.h>')
173 _c('#include "xcbext.h"')
174 _c('#include "%s.h"', _ns.header)
177 for (n, h) in self.imports:
178 _hc('#include "%s.h"', h)
181 _h('#ifdef __cplusplus')
187 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
188 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
190 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
193 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
197 Exported function that handles module close.
198 Writes out all the stored content lines, then closes the files.
205 _h('#ifdef __cplusplus')
217 hfile = open('%s.h' % _ns.header, 'w')
225 cfile = open('%s.c' % _ns.header, 'w')
232 def build_collision_table():
236 for v in module.types.values():
238 namecount[name] = (namecount.get(name) or 0) + 1
240 def c_enum(self, name):
242 Exported function that handles enum declarations.
246 if namecount[tname] > 1:
247 tname = _t(name + ('enum',))
251 _h('typedef enum %s {', tname)
253 count = len(self.values)
255 for (enam, eval) in self.values:
257 equals = ' = ' if eval != '' else ''
258 comma = ',' if count > 0 else ''
259 _h(' %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
263 def _c_type_setup(self, name, postfix):
265 Sets up all the C-related state by adding additional data fields to
266 all Field and Type objects. Here is where we figure out most of our
267 variable and function names.
269 Recurses into child fields and list member types.
271 # Do all the various names in advance
272 self.c_type = _t(name + postfix)
273 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
275 self.c_iterator_type = _t(name + ('iterator',))
276 self.c_next_name = _n(name + ('next',))
277 self.c_end_name = _n(name + ('end',))
279 self.c_request_name = _n(name)
280 self.c_checked_name = _n(name + ('checked',))
281 self.c_unchecked_name = _n(name + ('unchecked',))
282 self.c_reply_name = _n(name + ('reply',))
283 self.c_reply_type = _t(name + ('reply',))
284 self.c_cookie_type = _t(name + ('cookie',))
286 self.need_aux = False
287 self.need_serialize = False
288 self.need_sizeof = False
290 self.c_aux_name = _n(name + ('aux',))
291 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
292 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
293 self.c_serialize_name = _n(name + ('serialize',))
294 self.c_unserialize_name = _n(name + ('unserialize',))
295 self.c_unpack_name = _n(name + ('unpack',))
296 self.c_sizeof_name = _n(name + ('sizeof',))
298 # special case: structs where variable size fields are followed by fixed size fields
299 self.var_followed_by_fixed_fields = False
302 self.need_serialize = True
303 self.c_container = 'struct'
304 for bitcase in self.bitcases:
305 bitcase.c_field_name = _cpp(bitcase.field_name)
306 bitcase_name = bitcase.field_type if bitcase.type.has_name else name
307 _c_type_setup(bitcase.type, bitcase_name, ())
309 elif self.is_container:
311 self.c_container = 'union' if self.is_union else 'struct'
312 prev_varsized_field = None
313 prev_varsized_offset = 0
314 first_field_after_varsized = None
316 for field in self.fields:
317 _c_type_setup(field.type, field.field_type, ())
318 if field.type.is_list:
319 _c_type_setup(field.type.member, field.field_type, ())
320 if (field.type.nmemb is None):
321 self.need_sizeof = True
323 field.c_field_type = _t(field.field_type)
324 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
325 field.c_field_name = _cpp(field.field_name)
326 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
327 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
329 # correct the c_pointer field for variable size non-list types
330 if not field.type.fixed_size() and field.c_pointer == ' ':
331 field.c_pointer = '*'
332 if field.type.is_list and not field.type.member.fixed_size():
333 field.c_pointer = '*'
335 if field.type.is_switch:
336 field.c_pointer = '*'
337 field.c_field_const_type = 'const ' + field.c_field_type
339 elif not field.type.fixed_size() and not field.type.is_bitcase:
340 self.need_sizeof = True
342 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
343 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
344 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
345 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
346 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
348 field.prev_varsized_field = prev_varsized_field
349 field.prev_varsized_offset = prev_varsized_offset
351 if prev_varsized_offset == 0:
352 first_field_after_varsized = field
353 field.first_field_after_varsized = first_field_after_varsized
355 if field.type.fixed_size():
356 prev_varsized_offset += field.type.size
357 # special case: intermixed fixed and variable size fields
358 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
359 if not self.is_union:
360 self.need_serialize = True
361 self.var_followed_by_fixed_fields = True
363 self.last_varsized_field = field
364 prev_varsized_field = field
365 prev_varsized_offset = 0
367 if self.var_followed_by_fixed_fields:
368 if field.type.fixed_size():
369 field.prev_varsized_field = None
371 if self.need_serialize:
372 # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
373 self.need_sizeof = True
375 # as switch does never appear at toplevel,
376 # continue here with type construction
378 if self.c_type not in finished_switch:
379 finished_switch.append(self.c_type)
380 # special: switch C structs get pointer fields for variable-sized members
382 for bitcase in self.bitcases:
383 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
384 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
385 # no list with switch as element, so no call to
386 # _c_iterator(field.type, field_name) necessary
388 if not self.is_bitcase:
389 if self.need_serialize:
390 if self.c_serialize_name not in finished_serializers:
391 finished_serializers.append(self.c_serialize_name)
392 _c_serialize('serialize', self)
394 # _unpack() and _unserialize() are only needed for special cases:
396 # special cases -> unserialize
397 if self.is_switch or self.var_followed_by_fixed_fields:
398 _c_serialize('unserialize', self)
401 if self.c_sizeof_name not in finished_sizeof:
402 if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
403 finished_sizeof.append(self.c_sizeof_name)
404 _c_serialize('sizeof', self)
407 def _c_helper_absolute_name(prefix, field=None):
409 turn prefix, which is a list of tuples (name, separator, Type obj) into a string
410 representing a valid name in C (based on the context)
411 if field is not None, append the field name as well
414 for name, sep, obj in prefix:
418 if ((obj.is_bitcase and obj.has_name) or # named bitcase
419 (obj.is_switch and len(obj.parents)>1)):
422 if field is not None:
423 prefix_str += _cpp(field.field_name)
427 def _c_helper_field_mapping(complex_type, prefix, flat=False):
429 generate absolute names, based on prefix, for all fields starting from complex_type
430 if flat == True, nested complex types are not taken into account
433 if complex_type.is_switch:
434 for b in complex_type.bitcases:
436 switch_name, switch_sep, switch_type = prefix[-1]
437 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
439 bitcase_prefix = prefix
441 if (True==flat and not b.type.has_name) or False==flat:
442 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
444 for f in complex_type.fields:
445 fname = _c_helper_absolute_name(prefix, f)
446 if all_fields.has_key(f.field_name):
447 raise Exception("field name %s has been registered before" % f.field_name)
449 all_fields[f.field_name] = (fname, f)
450 if f.type.is_container and flat==False:
451 if f.type.is_bitcase and not f.type.has_name:
453 elif f.type.is_switch and len(f.type.parents)>1:
454 # nested switch gets another separator
455 new_prefix = prefix+[(f.c_field_name, '.', f.type)]
457 new_prefix = prefix+[(f.c_field_name, '->', f.type)]
458 all_fields.update(_c_helper_field_mapping(f.type, new_prefix, flat))
463 def _c_helper_resolve_field_names (prefix):
465 get field names for all objects in the prefix array
469 # look for fields in the remaining containers
470 for idx, p in enumerate(prefix):
473 # sep can be preset in prefix, if not, make a sensible guess
474 sep = '.' if (obj.is_switch or obj.is_bitcase) else '->'
475 # exception: 'toplevel' object (switch as well!) always have sep '->'
476 sep = '->' if idx<1 else sep
477 if not obj.is_bitcase or (obj.is_bitcase and obj.has_name):
478 tmp_prefix.append((name, sep, obj))
479 all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
482 # _c_helper_resolve_field_names
484 def get_expr_fields(self):
486 get the Fields referenced by switch or list expression
488 def get_expr_field_names(expr):
490 if expr.lenfield_name is not None:
491 return [expr.lenfield_name]
493 # constant value expr
497 return get_expr_field_names(expr.rhs)
498 elif expr.op == 'popcount':
499 return get_expr_field_names(expr.rhs)
500 elif expr.op == 'sumof':
501 # sumof expr references another list,
502 # we need that list's length field here
504 for f in expr.lenfield_parent.fields:
505 if f.field_name == expr.lenfield_name:
509 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
510 # referenced list + its length field
511 return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
512 elif expr.op == 'enumref':
515 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
516 # get_expr_field_names()
518 # resolve the field names with the parent structure(s)
519 unresolved_fields_names = get_expr_field_names(self.expr)
521 # construct prefix from self
522 prefix = [('', '', p) for p in self.parents]
523 if self.is_container:
524 prefix.append(('', '', self))
526 all_fields = _c_helper_resolve_field_names (prefix)
527 resolved_fields_names = filter(lambda x: x in all_fields.keys(), unresolved_fields_names)
528 if len(unresolved_fields_names) != len(resolved_fields_names):
529 raise Exception("could not resolve all fields for %s" % self.name)
531 resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
532 return resolved_fields
535 def resolve_expr_fields(complex_obj):
537 find expr fields appearing in complex_obj and descendents that cannot be resolved within complex_obj
538 these are normally fields that need to be given as function parameters
544 for field in complex_obj.fields:
545 all_fields.append(field)
546 if field.type.is_switch or field.type.is_list:
547 expr_fields += get_expr_fields(field.type)
548 if field.type.is_container:
549 expr_fields += resolve_expr_fields(field.type)
551 # try to resolve expr fields
552 for e in expr_fields:
553 if e not in all_fields and e not in unresolved:
556 # resolve_expr_fields()
558 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
560 functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
561 E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch
562 expression. This function tries to resolve all fields within a structure, and returns the
563 unresolved fields as the list of external parameters.
565 def add_param(params, param):
566 if param not in params:
569 # collect all fields into param_fields
573 for field in self.fields:
575 # the field should appear as a parameter in the function call
576 param_fields.append(field)
577 if field.wire and not field.auto:
578 if field.type.fixed_size() and not self.is_switch:
579 # field in the xcb_out structure
580 wire_fields.append(field)
581 # fields like 'pad0' are skipped!
583 # in case of switch, parameters always contain any fields referenced in the switch expr
584 # we do not need any variable size fields here, as the switch data type contains both
585 # fixed and variable size fields
587 param_fields = get_expr_fields(self)
589 # _serialize()/_unserialize()/_unpack() function parameters
590 # note: don't use set() for params, it is unsorted
593 # 1. the parameter for the void * buffer
594 if 'serialize' == context:
595 params.append(('void', '**', buffer_var))
596 elif context in ('unserialize', 'unpack', 'sizeof'):
597 params.append(('const void', '*', buffer_var))
599 # 2. any expr fields that cannot be resolved within self and descendants
600 unresolved_fields = resolve_expr_fields(self)
601 for f in unresolved_fields:
602 add_param(params, (f.c_field_type, '', f.c_field_name))
604 # 3. param_fields contain the fields necessary to evaluate the switch expr or any other fields
605 # that do not appear in the data type struct
606 for p in param_fields:
608 typespec = p.c_field_const_type
609 pointerspec = p.c_pointer
610 add_param(params, (typespec, pointerspec, p.c_field_name))
612 if p.visible and not p.wire and not p.auto:
613 typespec = p.c_field_type
615 add_param(params, (typespec, pointerspec, p.c_field_name))
618 if 'serialize' == context:
619 add_param(params, ('const %s' % self.c_type, '*', aux_var))
620 elif 'unserialize' == context:
621 add_param(params, ('%s' % self.c_type, '**', aux_var))
622 elif 'unpack' == context:
623 add_param(params, ('%s' % self.c_type, '*', aux_var))
625 # 5. switch contains all variable size fields as struct members
626 # for other data types though, these have to be supplied separately
627 # this is important for the special case of intermixed fixed and
628 # variable size fields
629 if not self.is_switch and 'serialize' == context:
630 for p in param_fields:
631 if not p.type.fixed_size():
632 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
634 return (param_fields, wire_fields, params)
635 # get_serialize_params()
637 def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
638 code_lines.append('%s /* insert padding */' % space)
639 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
640 # code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
641 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
644 code_lines.append('%s if (0 != xcb_pad) {' % space)
646 if 'serialize' == context:
647 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
648 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
649 code_lines.append('%s xcb_parts_idx++;' % space)
650 elif context in ('unserialize', 'unpack', 'sizeof'):
651 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
653 code_lines.append('%s xcb_pad = 0;' % space)
654 code_lines.append('%s }' % space)
656 code_lines.append('%s xcb_block_len = 0;' % space)
658 # keep tracking of xcb_parts entries for serialize
660 # _c_serialize_helper_insert_padding()
662 def _c_serialize_helper_switch(context, self, complex_name,
663 code_lines, temp_vars,
666 switch_expr = _c_accessor_get_expr(self.expr, None)
668 for b in self.bitcases:
669 bitcase_expr = _c_accessor_get_expr(b.type.expr, None)
670 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
671 # code_lines.append(' printf("switch %s: entering bitcase section %s (mask=%%%%d)...\\n", %s);' %
672 # (self.name[-1], b.type.name[-1], bitcase_expr))
675 b_prefix = prefix + [(b.c_field_name, '.', b.type)]
677 count += _c_serialize_helper_fields(context, b.type,
678 code_lines, temp_vars,
682 code_lines.append(' }')
684 # if 'serialize' == context:
685 # count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
686 # elif context in ('unserialize', 'unpack', 'sizeof'):
688 # code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
689 # code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
692 # _c_serialize_helper_switch
694 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
696 handle switch by calling _serialize() or _unpack(), depending on context
698 # switch is handled by this function as a special case
699 param_fields, wire_fields, params = get_serialize_params(context, self)
700 field_mapping = _c_helper_field_mapping(self, prefix)
701 prefix_str = _c_helper_absolute_name(prefix)
703 # find the parameters that need to be passed to _serialize()/_unpack():
704 # all switch expr fields must be given as parameters
705 args = get_expr_fields(field.type)
706 # length fields for variable size types in switch, normally only some of need
707 # need to be passed as parameters
708 switch_len_fields = resolve_expr_fields(field.type)
710 # a switch field at this point _must_ be a bitcase field
711 # we require that bitcases are "self-contiguous"
712 bitcase_unresolved = resolve_expr_fields(self)
713 if len(bitcase_unresolved) != 0:
714 raise Exception('unresolved fields within bitcase is not supported at this point')
716 # get the C names for the parameters
718 for a in switch_len_fields:
719 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
721 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
723 # call _serialize()/_unpack() to determine the actual size
724 if 'serialize' == context:
725 length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
726 c_field_names, prefix_str, field.c_field_name)
727 elif context in ('unserialize', 'unpack'):
728 length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
729 c_field_names, prefix_str, field.c_field_name)
732 # _c_serialize_helper_switch_field()
734 def _c_serialize_helper_list_field(context, self, field,
735 code_lines, temp_vars,
738 helper function to cope with lists of variable length
740 expr = field.type.expr
741 prefix_str = _c_helper_absolute_name(prefix)
742 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
743 param_names = [p[2] for p in params]
745 expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
746 resolved = filter(lambda x: x in param_names, expr_fields_names)
747 unresolved = filter(lambda x: x not in param_names, expr_fields_names)
751 field_mapping[r] = (r, None)
753 if len(unresolved)>0:
755 if len(tmp_prefix)==0:
756 raise Exception("found an empty prefix while resolving expr field names for list %s",
759 field_mapping.update(_c_helper_resolve_field_names(prefix))
760 resolved += filter(lambda x: x in field_mapping, unresolved)
761 unresolved = filter(lambda x: x not in field_mapping, unresolved)
762 if len(unresolved)>0:
763 raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
765 list_length = _c_accessor_get_expr(expr, field_mapping)
767 # default: list with fixed size elements
768 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
770 # list with variable-sized elements
771 if not field.type.member.fixed_size():
773 if context in ('unserialize', 'sizeof', 'unpack'):
774 int_i = ' unsigned int i;'
775 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
776 if int_i not in temp_vars:
777 temp_vars.append(int_i)
778 if xcb_tmp_len not in temp_vars:
779 temp_vars.append(xcb_tmp_len)
780 # loop over all list elements and call sizeof repeatedly
781 # this should be a bit faster than using the iterators
782 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
783 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
784 (space, field.type.c_sizeof_name))
785 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
786 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
787 code_lines.append("%s }" % space)
789 elif 'serialize' == context:
790 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
791 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
792 code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length))
793 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
794 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
795 code_lines.append('%s }' % space)
796 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
799 # _c_serialize_helper_list_field()
801 def _c_serialize_helper_fields_fixed_size(context, self, field,
802 code_lines, temp_vars,
804 # keep the C code a bit more readable by giving the field name
805 if not self.is_bitcase:
806 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
808 scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
809 typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
810 code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
812 abs_field_name = _c_helper_absolute_name(prefix, field)
813 # default for simple cases: call sizeof()
814 length = "sizeof(%s)" % field.c_field_type
816 if context in ('unserialize', 'unpack', 'sizeof'):
817 # default: simple cast
818 value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
820 # padding - we could probably just ignore it
821 if field.type.is_pad and field.type.nmemb > 1:
823 for i in range(field.type.nmemb):
824 code_lines.append('%s %s[%d] = *(%s *)xcb_tmp;' %
825 (space, abs_field_name, i, field.c_field_type))
826 # total padding = sizeof(pad0) * nmemb
827 length += " * %d" % field.type.nmemb
829 if field.type.is_list:
830 # no such case in the protocol, cannot be tested and therefore ignored for now
831 raise Exception('list with fixed number of elemens unhandled in _unserialize()')
833 elif 'serialize' == context:
834 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
836 if field.type.is_expr:
837 # need to register a temporary variable for the expression in case we know its type
838 if field.type.c_type is None:
839 raise Exception("type for field '%s' (expression '%s') unkown" %
840 (field.field_name, _c_accessor_get_expr(field.type.expr)))
842 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
843 _c_accessor_get_expr(field.type.expr, prefix)))
844 value += "&xcb_expr_%s;" % _cpp(field.field_name)
846 elif field.type.is_pad:
847 if field.type.nmemb == 1:
850 # we could also set it to 0, see definition of xcb_send_request()
851 value = ' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
852 length += "*%d" % field.type.nmemb
855 # non-list type with fixed size
856 if field.type.nmemb == 1:
857 value += "&%s;" % (abs_field_name)
859 # list with nmemb (fixed size) elements
861 value += '%s;' % (abs_field_name)
862 length = '%d' % field.type.nmemb
864 return (value, length)
865 # _c_serialize_helper_fields_fixed_size()
867 def _c_serialize_helper_fields_variable_size(context, self, field,
868 code_lines, temp_vars,
870 prefix_str = _c_helper_absolute_name(prefix)
872 if context in ('unserialize', 'unpack', 'sizeof'):
874 var_field_name = 'xcb_tmp'
876 # special case: intermixed fixed and variable size fields
877 if self.var_followed_by_fixed_fields and 'unserialize' == context:
878 value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
879 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
880 # special case: switch
881 if 'unpack' == context:
882 value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
884 elif 'serialize' == context:
885 # variable size fields appear as parameters to _serialize() if the
886 # 'toplevel' container is not a switch
887 prefix_string = prefix_str if prefix[0][2].is_switch else ''
888 var_field_name = "%s%s" % (prefix_string, field.c_field_name)
889 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
893 code_lines.append('%s /* %s */' % (space, field.c_field_name))
895 if field.type.is_list:
897 # in any context, list is already a pointer, so the default assignment is ok
898 code_lines.append("%s%s" % (space, value))
900 length = _c_serialize_helper_list_field(context, self, field,
901 code_lines, temp_vars,
904 elif field.type.is_switch:
906 if context == 'serialize':
907 # the _serialize() function allocates the correct amount memory if given a NULL pointer
908 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
909 length = _c_serialize_helper_switch_field(context, self, field,
910 'xcb_parts[xcb_parts_idx].iov_base',
914 # in all remaining special cases - call _sizeof()
915 length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
917 return (value, length)
918 # _c_serialize_helper_fields_variable_size
920 def _c_serialize_helper_fields(context, self,
921 code_lines, temp_vars,
922 space, prefix, is_bitcase):
925 prev_field_was_variable = False
927 for field in self.fields:
928 if not field.visible:
929 if not ((field.wire and not field.auto) or 'unserialize' == context):
932 # switch/bitcase: fixed size fields must be considered explicitly
933 if field.type.fixed_size():
934 if self.is_bitcase or self.var_followed_by_fixed_fields:
935 if prev_field_was_variable and need_padding:
937 # count += _c_serialize_helper_insert_padding(context, code_lines, space,
938 # self.var_followed_by_fixed_fields)
939 prev_field_was_variable = False
941 # prefix for fixed size fields
942 fixed_prefix = prefix
944 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
945 code_lines, temp_vars,
950 # fields with variable size
952 # switch/bitcase: always calculate padding before and after variable sized fields
953 if need_padding or is_bitcase:
954 count += _c_serialize_helper_insert_padding(context, code_lines, space,
955 self.var_followed_by_fixed_fields)
957 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
958 code_lines, temp_vars,
960 prev_field_was_variable = True
962 # save (un)serialization C code
964 code_lines.append('%s%s' % (space, value))
966 if field.type.fixed_size():
967 if is_bitcase or self.var_followed_by_fixed_fields:
968 # keep track of (un)serialized object's size
969 code_lines.append('%s xcb_block_len += %s;' % (space, length))
970 if context in ('unserialize', 'unpack', 'sizeof'):
971 code_lines.append('%s xcb_tmp += %s;' % (space, length))
973 # variable size objects or bitcase:
974 # value & length might have been inserted earlier for special cases
976 # special case: intermixed fixed and variable size fields
977 if (not field.type.fixed_size() and
978 self.var_followed_by_fixed_fields and 'unserialize' == context):
979 temp_vars.append(' int %s_len;' % field.c_field_name)
980 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
981 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
982 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
984 code_lines.append('%s xcb_block_len += %s;' % (space, length))
985 # increase pointer into the byte stream accordingly
986 if context in ('unserialize', 'sizeof', 'unpack'):
987 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
989 if 'serialize' == context:
991 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
992 code_lines.append('%s xcb_parts_idx++;' % space)
996 if self.var_followed_by_fixed_fields:
1000 # _c_serialize_helper_fields()
1002 def _c_serialize_helper(context, complex_type,
1003 code_lines, temp_vars,
1004 space='', prefix=[]):
1005 # count tracks the number of fields to serialize
1008 if hasattr(complex_type, 'type'):
1009 self = complex_type.type
1010 complex_name = complex_type.name
1013 if self.var_followed_by_fixed_fields and 'unserialize' == context:
1014 complex_name = 'xcb_out'
1016 complex_name = '_aux'
1018 # special case: switch is serialized by evaluating each bitcase separately
1020 count += _c_serialize_helper_switch(context, self, complex_name,
1021 code_lines, temp_vars,
1024 # all other data types can be evaluated one field a time
1026 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1027 if context in ('unserialize', 'unpack', 'sizeof') and not self.var_followed_by_fixed_fields:
1028 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1029 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1030 # probably not needed
1031 #_c_serialize_helper_insert_padding(context, code_lines, space, False)
1033 count += _c_serialize_helper_fields(context, self,
1034 code_lines, temp_vars,
1035 space, prefix, False)
1037 count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
1040 # _c_serialize_helper()
1042 def _c_serialize(context, self):
1044 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1045 for the ComplexType variable self
1051 # _serialize() returns the buffer size
1054 if self.is_switch and 'unserialize' == context:
1057 cases = { 'serialize' : self.c_serialize_name,
1058 'unserialize' : self.c_unserialize_name,
1059 'unpack' : self.c_unpack_name,
1060 'sizeof' : self.c_sizeof_name }
1061 func_name = cases[context]
1063 param_fields, wire_fields, params = get_serialize_params(context, self)
1064 variable_size_fields = 0
1065 # maximum space required for type definition of function arguments
1068 # determine N(variable_fields)
1069 for field in param_fields:
1070 # if self.is_switch, treat all fields as if they are variable sized
1071 if not field.type.fixed_size() or self.is_switch:
1072 variable_size_fields += 1
1073 # determine maxtypelen
1075 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1078 indent = ' '*(len(func_name)+2)
1081 typespec, pointerspec, field_name = p
1082 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1083 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1084 # insert function name
1085 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1086 param_str = map(lambda x: "%s," % x, param_str)
1087 for s in param_str[:-1]:
1089 _h("%s);" % param_str[-1].rstrip(','))
1090 _c("%s)" % param_str[-1].rstrip(','))
1097 if 'serialize' == context:
1098 if not self.is_switch and not self.var_followed_by_fixed_fields:
1099 _c(' %s *xcb_out = *_buffer;', self.c_type)
1100 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1101 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1103 _c(' char *xcb_out = *_buffer;')
1104 _c(' unsigned int xcb_buffer_len = 0;')
1105 prefix = [('_aux', '->', self)]
1108 elif context in ('unserialize', 'unpack'):
1109 _c(' char *xcb_tmp = (char *)_buffer;')
1110 if not self.is_switch:
1111 if not self.var_followed_by_fixed_fields:
1112 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1113 prefix = [('_aux', '->', self)]
1115 _c(' %s xcb_out;', self.c_type)
1116 prefix = [('xcb_out', '.', self)]
1118 aux_var = '_aux' # default for unpack: single pointer
1119 # note: unserialize not generated for switch
1120 if 'unserialize' == context:
1121 aux_var = '(*_aux)' # unserialize: double pointer (!)
1122 prefix = [(aux_var, '->', self)]
1124 _c(' unsigned int xcb_buffer_len = 0;')
1125 _c(' unsigned int xcb_block_len = 0;')
1126 _c(' unsigned int xcb_pad = 0;')
1128 elif 'sizeof' == context:
1129 param_names = [p[2] for p in params]
1131 # switch: call _unpack()
1132 _c(' %s _aux;', self.c_type)
1133 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1136 elif self.var_followed_by_fixed_fields:
1137 # special case: call _unserialize()
1138 _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1142 _c(' char *xcb_tmp = (char *)_buffer;')
1143 prefix = [('_aux', '->', self)]
1145 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1146 # update variable size fields (only important for context=='serialize'
1147 variable_size_fields = count
1148 if 'serialize' == context:
1149 temp_vars.append(' unsigned int xcb_pad = 0;')
1150 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1151 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1152 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1153 temp_vars.append(' unsigned int xcb_block_len = 0;')
1154 temp_vars.append(' unsigned int i;')
1155 temp_vars.append(' char *xcb_tmp;')
1156 elif 'sizeof' == context:
1157 # neither switch nor intermixed fixed and variable size fields:
1158 # evaluate parameters directly
1159 if not (self.is_switch or self.var_followed_by_fixed_fields):
1161 # look if we have to declare an '_aux' variable at all
1162 if len(filter(lambda x: x.find('_aux')!=-1, code_lines))>0:
1163 if not self.var_followed_by_fixed_fields:
1164 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1166 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1168 _c(' unsigned int xcb_buffer_len = 0;')
1169 _c(' unsigned int xcb_block_len = 0;')
1170 _c(' unsigned int xcb_pad = 0;')
1176 for l in code_lines:
1179 # variable sized fields have been collected, now
1180 # allocate memory and copy everything into a continuous memory area
1181 # note: this is not necessary in case of unpack
1182 if context in ('serialize', 'unserialize'):
1183 # unserialize: check for sizeof-only invocation
1184 if 'unserialize' == context:
1186 _c(' if (NULL == _aux)')
1187 _c(' return xcb_buffer_len;')
1190 _c(' if (NULL == %s) {', aux_ptr)
1191 _c(' /* allocate memory */')
1192 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1193 if 'serialize' == context:
1194 _c(' *_buffer = xcb_out;')
1198 # serialize: handle variable size fields in a loop
1199 if 'serialize' == context:
1200 if not self.is_switch and not self.var_followed_by_fixed_fields:
1201 if len(wire_fields)>0:
1202 _c(' *xcb_out = *_aux;')
1203 # copy variable size fields into the buffer
1204 if variable_size_fields > 0:
1206 if not self.is_switch and not self.var_followed_by_fixed_fields:
1207 _c(' xcb_tmp = (char*)++xcb_out;')
1208 _c(' xcb_tmp += xcb_out_pad;')
1210 _c(' xcb_tmp = xcb_out;')
1212 # variable sized fields
1213 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1214 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1215 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1216 _c(' if (0 != xcb_parts[i].iov_len)')
1217 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1220 # unserialize: assign variable size fields individually
1221 if 'unserialize' == context:
1222 _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1223 param_fields.reverse()
1224 for field in param_fields:
1225 if not field.type.fixed_size():
1226 _c(' xcb_tmp -= %s_len;', field.c_field_name)
1227 _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1228 _c(' *%s = xcb_out;', aux_ptr)
1231 _c(' return xcb_buffer_len;')
1235 def _c_iterator_get_end(field, accum):
1237 Figures out what C code is needed to find the end of a variable-length structure field.
1238 For nested structures, recurses into its last variable-sized field.
1239 For lists, calls the end function
1241 if field.type.is_container:
1242 accum = field.c_accessor_name + '(' + accum + ')'
1243 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1244 if field.type.is_list:
1245 # XXX we can always use the first way
1246 if field.type.member.is_simple:
1247 return field.c_end_name + '(' + accum + ')'
1249 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1251 def _c_iterator(self, name):
1253 Declares the iterator structure and next/end functions for a given type.
1258 _h(' * @brief %s', self.c_iterator_type)
1260 _h('typedef struct %s {', self.c_iterator_type)
1261 _h(' %s *data; /**< */', self.c_type)
1262 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1263 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1264 _h('} %s;', self.c_iterator_type)
1270 _h(' * Get the next element of the iterator')
1271 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1273 _h(' * Get the next element in the iterator. The member rem is')
1274 _h(' * decreased by one. The member data points to the next')
1275 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1279 _hc('/*****************************************************************************')
1281 _hc(' ** void %s', self.c_next_name)
1283 _hc(' ** @param %s *i', self.c_iterator_type)
1284 _hc(' ** @returns void')
1286 _hc(' *****************************************************************************/')
1289 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1290 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1293 if not self.fixed_size():
1294 _c(' %s *R = i->data;', self.c_type)
1297 # FIXME - how to determine the size of a variable size union??
1298 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1300 if self.need_sizeof:
1301 _c(' xcb_generic_iterator_t child;')
1302 _c(' child.data = (%s *)(((char *)R) + %s(R));',
1303 self.c_type, self.c_sizeof_name)
1304 _c(' i->index = (char *) child.data - (char *) i->data;')
1306 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1307 _c(' i->index = child.index;')
1309 _c(' i->data = (%s *) child.data;', self.c_type)
1314 _c(' i->index += sizeof(%s);', self.c_type)
1320 _h(' * Return the iterator pointing to the last element')
1321 _h(' * @param i An %s', self.c_iterator_type)
1322 _h(' * @return The iterator pointing to the last element')
1324 _h(' * Set the current element in the iterator to the last element.')
1325 _h(' * The member rem is set to 0. The member data points to the')
1326 _h(' * last element.')
1330 _hc('/*****************************************************************************')
1332 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1334 _hc(' ** @param %s i', self.c_iterator_type)
1335 _hc(' ** @returns xcb_generic_iterator_t')
1337 _hc(' *****************************************************************************/')
1339 _hc('xcb_generic_iterator_t')
1340 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1341 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1343 _c(' xcb_generic_iterator_t ret;')
1345 if self.fixed_size():
1346 _c(' ret.data = i.data + i.rem;')
1347 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1350 _c(' while(i.rem > 0)')
1351 _c(' %s(&i);', self.c_next_name)
1352 _c(' ret.data = i.data;')
1353 _c(' ret.rem = i.rem;')
1354 _c(' ret.index = i.index;')
1359 def _c_accessor_get_length(expr, field_mapping=None):
1361 Figures out what C code is needed to get a length field.
1362 The field_mapping parameter can be used to change the absolute name of a length field.
1363 For fields that follow a variable-length field, use the accessor.
1364 Otherwise, just reference the structure field directly.
1367 lenfield_name = expr.lenfield_name
1368 if lenfield_name is not None:
1369 if field_mapping is not None:
1370 lenfield_name = field_mapping[lenfield_name][0]
1372 if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1373 # special case: variable and fixed size fields are intermixed
1374 # if the lenfield is among the fixed size fields, there is no need
1375 # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1376 return field_mapping(expr.lenfield_name)
1377 elif expr.lenfield_name is not None:
1378 return lenfield_name
1380 return str(expr.nmemb)
1382 def _c_accessor_get_expr(expr, field_mapping):
1384 Figures out what C code is needed to get the length of a list field.
1385 The field_mapping parameter can be used to change the absolute name of a length field.
1386 Recurses for math operations.
1387 Returns bitcount for value-mask fields.
1388 Otherwise, uses the value of the length field.
1390 lenexp = _c_accessor_get_length(expr, field_mapping)
1393 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1394 elif expr.op == 'popcount':
1395 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1396 elif expr.op == 'enumref':
1397 enum_name = expr.lenfield_type.name
1398 constant_name = expr.lenfield_name
1399 c_name = _n(enum_name + (constant_name,)).upper()
1401 elif expr.op == 'sumof':
1402 # locate the referenced list object
1403 list_obj = expr.lenfield_type
1405 for f in expr.lenfield_parent.fields:
1406 if f.field_name == expr.lenfield_name:
1411 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1412 list_name = field_mapping[field.c_field_name][0]
1413 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1414 # note: xcb_sumof() has only been defined for integers
1415 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1416 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1417 elif expr.op != None:
1418 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1419 ' ' + expr.op + ' ' +
1420 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1422 return 'xcb_popcount(' + lenexp + ')'
1426 def type_pad_type(type):
1431 def _c_accessors_field(self, field):
1433 Declares the accessor functions for a non-list field that follows a variable-length field.
1435 c_type = self.c_type
1437 # special case: switch
1438 switch_obj = self if self.is_switch else None
1440 switch_obj = self.parents[-1]
1441 if switch_obj is not None:
1442 c_type = switch_obj.c_type
1444 if field.type.is_simple:
1447 _hc('/*****************************************************************************')
1449 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1451 _hc(' ** @param const %s *R', c_type)
1452 _hc(' ** @returns %s', field.c_field_type)
1454 _hc(' *****************************************************************************/')
1456 _hc('%s', field.c_field_type)
1457 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1458 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1460 if field.prev_varsized_field is None:
1461 _c(' return (%s *) (R + 1);', field.c_field_type)
1463 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1464 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1465 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1470 _hc('/*****************************************************************************')
1472 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1474 _hc(' ** @param const %s *R', c_type)
1475 _hc(' ** @returns %s *', field.c_field_type)
1477 _hc(' *****************************************************************************/')
1479 if field.type.is_switch and switch_obj is None:
1480 return_type = 'void *'
1482 return_type = '%s *' % field.c_field_type
1485 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1486 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1488 if field.prev_varsized_field is None:
1489 _c(' return (%s) (R + 1);', return_type)
1490 # note: the special case 'variable fields followed by fixed size fields'
1491 # is not of any consequence here, since the ordering gets
1492 # 'corrected' in the reply function
1494 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1495 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1496 return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1500 def _c_accessors_list(self, field):
1502 Declares the accessor functions for a list field.
1503 Declares a direct-accessor function only if the list members are fixed size.
1504 Declares length and get-iterator functions always.
1507 c_type = self.c_type
1509 # special case: switch
1510 # in case of switch, 2 params have to be supplied to certain accessor functions:
1511 # 1. the anchestor object (request or reply)
1512 # 2. the (anchestor) switch object
1513 # the reason is that switch is either a child of a request/reply or nested in another switch,
1514 # so whenever we need to access a length field, we might need to refer to some anchestor type
1515 switch_obj = self if self.is_switch else None
1517 switch_obj = self.parents[-1]
1518 if switch_obj is not None:
1519 c_type = switch_obj.c_type
1523 parents = self.parents if hasattr(self, 'parents') else [self]
1524 # 'R': parents[0] is always the 'toplevel' container type
1525 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1526 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1527 # auxiliary object for 'R' parameters
1530 if switch_obj is not None:
1531 # now look where the fields are defined that are needed to evaluate
1532 # the switch expr, and store the parent objects in accessor_params and
1533 # the fields in switch_fields
1535 # 'S': name for the 'toplevel' switch
1536 toplevel_switch = parents[1]
1537 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1538 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1540 # initialize prefix for everything "below" S
1541 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1542 prefix = [(prefix_str, '->', toplevel_switch)]
1544 # look for fields in the remaining containers
1545 for p in parents[2:] + [self]:
1546 # the separator between parent and child is always '.' here,
1547 # because of nested switch statements
1548 if not p.is_bitcase or (p.is_bitcase and p.has_name):
1549 prefix.append((p.name[-1], '.', p))
1550 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1552 # auxiliary object for 'S' parameter
1557 if list.member.fixed_size():
1558 idx = 1 if switch_obj is not None else 0
1561 _hc('/*****************************************************************************')
1563 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1565 _hc(' ** @param %s', params[idx][0])
1566 _hc(' ** @returns %s *', field.c_field_type)
1568 _hc(' *****************************************************************************/')
1570 _hc('%s *', field.c_field_type)
1572 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1573 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1576 if switch_obj is not None:
1577 _c(' return %s;', fields[field.c_field_name][0])
1578 elif field.prev_varsized_field is None:
1579 _c(' return (%s *) (R + 1);', field.c_field_type)
1581 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1582 _c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1583 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1588 _hc('/*****************************************************************************')
1590 _hc(' ** int %s', field.c_length_name)
1592 _hc(' ** @param const %s *R', c_type)
1593 _hc(' ** @returns int')
1595 _hc(' *****************************************************************************/')
1598 if switch_obj is not None:
1599 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1600 spacing = ' '*(len(field.c_length_name)+2)
1601 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1602 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1603 length = _c_accessor_get_expr(field.type.expr, fields)
1605 _h('%s (const %s *R /**< */);', field.c_length_name, c_type)
1606 _c('%s (const %s *R /**< */)', field.c_length_name, c_type)
1607 length = _c_accessor_get_expr(field.type.expr, fields)
1609 _c(' return %s;', length)
1612 if field.type.member.is_simple:
1615 _hc('/*****************************************************************************')
1617 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1619 _hc(' ** @param const %s *R', c_type)
1620 _hc(' ** @returns xcb_generic_iterator_t')
1622 _hc(' *****************************************************************************/')
1624 _hc('xcb_generic_iterator_t')
1625 if switch_obj is not None:
1626 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1627 spacing = ' '*(len(field.c_end_name)+2)
1628 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1629 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1631 _h('%s (const %s *R /**< */);', field.c_end_name, c_type)
1632 _c('%s (const %s *R /**< */)', field.c_end_name, c_type)
1634 _c(' xcb_generic_iterator_t i;')
1636 param = 'R' if switch_obj is None else 'S'
1637 if switch_obj is not None:
1638 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1639 _c_accessor_get_expr(field.type.expr, fields))
1640 elif field.prev_varsized_field == None:
1641 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1642 _c_accessor_get_expr(field.type.expr, fields))
1644 _c(' xcb_generic_iterator_t child = %s;',
1645 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1646 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1647 _c_accessor_get_expr(field.type.expr, fields))
1650 _c(' i.index = (char *) i.data - (char *) %s;', param)
1657 _hc('/*****************************************************************************')
1659 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1661 _hc(' ** @param const %s *R', c_type)
1662 _hc(' ** @returns %s', field.c_iterator_type)
1664 _hc(' *****************************************************************************/')
1667 _hc('%s', field.c_iterator_type)
1668 if switch_obj is not None:
1669 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1670 spacing = ' '*(len(field.c_iterator_name)+2)
1671 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1672 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1674 _h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
1675 _c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
1677 _c(' %s i;', field.c_iterator_type)
1679 if switch_obj is not None:
1680 _c(' i.data = %s;', fields[field.c_field_name][0])
1681 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1682 elif field.prev_varsized_field == None:
1683 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1685 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1686 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));',
1687 field.c_field_type, type_pad_type(field.c_field_type))
1688 if switch_obj is None:
1689 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1690 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1694 def _c_accessors(self, name, base):
1696 Declares the accessor functions for the fields of a structure.
1698 # no accessors for switch itself -
1699 # switch always needs to be unpacked explicitly
1700 # if self.is_switch:
1704 for field in self.fields:
1705 if field.type.is_list and not field.type.fixed_size():
1706 _c_accessors_list(self, field)
1707 elif field.prev_varsized_field is not None or not field.type.fixed_size():
1708 _c_accessors_field(self, field)
1710 def c_simple(self, name):
1712 Exported function that handles cardinal type declarations.
1713 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1715 _c_type_setup(self, name, ())
1717 if (self.name != name):
1722 _h('typedef %s %s;', _t(self.name), my_name)
1725 _c_iterator(self, name)
1727 def _c_complex(self):
1729 Helper function for handling all structure types.
1730 Called for all structs, requests, replies, events, errors.
1735 _h(' * @brief %s', self.c_type)
1737 _h('typedef %s %s {', self.c_container, self.c_type)
1743 for field in self.fields:
1744 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1745 varfield = field.c_field_name
1748 struct_fields.append(field)
1750 for field in struct_fields:
1751 length = len(field.c_field_type)
1752 # account for '*' pointer_spec
1753 if not field.type.fixed_size():
1755 maxtypelen = max(maxtypelen, length)
1757 def _c_complex_field(self, field, space=''):
1758 if (field.type.fixed_size() or
1759 # in case of switch with switch children, don't make the field a pointer
1760 # necessary for unserialize to work
1761 (self.is_switch and field.type.is_switch)):
1762 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1763 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1765 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1766 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1768 if not self.is_switch:
1769 for field in struct_fields:
1770 _c_complex_field(self, field)
1772 for b in self.bitcases:
1775 _h(' struct _%s {', b.c_field_name)
1777 for field in b.type.fields:
1778 _c_complex_field(self, field, space)
1780 _h(' } %s;', b.c_field_name)
1782 _h('} %s;', self.c_type)
1784 def c_struct(self, name):
1786 Exported function that handles structure declarations.
1788 _c_type_setup(self, name, ())
1790 _c_accessors(self, name, name)
1791 _c_iterator(self, name)
1793 def c_union(self, name):
1795 Exported function that handles union declarations.
1797 _c_type_setup(self, name, ())
1799 _c_iterator(self, name)
1801 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1803 Declares a request function.
1806 # Four stunningly confusing possibilities here:
1809 # ------------------------------
1811 # 0 flag CHECKED flag Normal Mode
1812 # void_cookie req_cookie
1813 # ------------------------------
1814 # "req_checked" "req_unchecked"
1815 # CHECKED flag 0 flag Abnormal Mode
1816 # void_cookie req_cookie
1817 # ------------------------------
1820 # Whether we are _checked or _unchecked
1821 checked = void and not regular
1822 unchecked = not void and not regular
1824 # What kind of cookie we return
1825 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1827 # What flag is passed to xcb_request
1828 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1830 # Global extension id variable or NULL for xproto
1831 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1833 # What our function name is
1834 func_name = self.c_request_name if not aux else self.c_aux_name
1836 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1838 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1842 maxtypelen = len('xcb_connection_t')
1844 # special case: list with variable size elements
1845 list_with_var_size_elems = False
1847 for field in self.fields:
1849 # The field should appear as a call parameter
1850 param_fields.append(field)
1851 if field.wire and not field.auto:
1852 # We need to set the field up in the structure
1853 wire_fields.append(field)
1854 if field.type.need_serialize or field.type.need_sizeof:
1855 serial_fields.append(field)
1857 for field in param_fields:
1858 c_field_const_type = field.c_field_const_type
1859 if field.type.need_serialize and not aux:
1860 c_field_const_type = "const void"
1861 if len(c_field_const_type) > maxtypelen:
1862 maxtypelen = len(c_field_const_type)
1863 if field.type.is_list and not field.type.member.fixed_size():
1864 list_with_var_size_elems = True
1870 _h(' * Delivers a request to the X server')
1871 _h(' * @param c The connection')
1872 _h(' * @return A cookie')
1874 _h(' * Delivers a request to the X server.')
1877 _h(' * This form can be used only if the request will not cause')
1878 _h(' * a reply to be generated. Any returned error will be')
1879 _h(' * saved for handling by xcb_request_check().')
1881 _h(' * This form can be used only if the request will cause')
1882 _h(' * a reply to be generated. Any returned error will be')
1883 _h(' * placed in the event queue.')
1887 _hc('/*****************************************************************************')
1889 _hc(' ** %s %s', cookie_type, func_name)
1892 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1893 _hc(' ** @param xcb_connection_t%s *c', spacing)
1895 for field in param_fields:
1896 c_field_const_type = field.c_field_const_type
1897 if field.type.need_serialize and not aux:
1898 c_field_const_type = "const void"
1899 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1900 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1902 _hc(' ** @returns %s', cookie_type)
1904 _hc(' *****************************************************************************/')
1906 _hc('%s', cookie_type)
1908 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1909 comma = ',' if len(param_fields) else ');'
1910 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1911 comma = ',' if len(param_fields) else ')'
1912 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1914 func_spacing = ' ' * (len(func_name) + 2)
1915 count = len(param_fields)
1916 for field in param_fields:
1918 c_field_const_type = field.c_field_const_type
1919 c_pointer = field.c_pointer
1920 if field.type.need_serialize and not aux:
1921 c_field_const_type = "const void"
1923 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1924 comma = ',' if count else ');'
1925 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1926 spacing, c_pointer, field.c_field_name, comma)
1927 comma = ',' if count else ')'
1928 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1929 spacing, c_pointer, field.c_field_name, comma)
1932 if not self.var_followed_by_fixed_fields:
1933 for field in param_fields:
1934 if not field.type.fixed_size():
1936 if field.type.need_serialize:
1937 # _serialize() keeps track of padding automatically
1939 dimension = count + 2
1942 _c(' static const xcb_protocol_request_t xcb_req = {')
1943 _c(' /* count */ %d,', count)
1944 _c(' /* ext */ %s,', func_ext_global)
1945 _c(' /* opcode */ %s,', self.c_request_name.upper())
1946 _c(' /* isvoid */ %d', 1 if void else 0)
1950 _c(' struct iovec xcb_parts[%d];', dimension)
1951 _c(' %s xcb_ret;', func_cookie)
1952 _c(' %s xcb_out;', self.c_type)
1953 if self.var_followed_by_fixed_fields:
1954 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
1955 _c(' void *xcb_aux = 0;')
1958 for idx, f in enumerate(serial_fields):
1960 _c(' void *xcb_aux%d = 0;' % (idx))
1961 if list_with_var_size_elems:
1962 _c(' unsigned int i;')
1963 _c(' unsigned int xcb_tmp_len;')
1964 _c(' char *xcb_tmp;')
1966 # simple request call tracing
1967 # _c(' printf("in function %s\\n");' % func_name)
1970 for field in wire_fields:
1971 if field.type.fixed_size():
1972 if field.type.is_expr:
1973 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
1974 elif field.type.is_pad:
1975 if field.type.nmemb == 1:
1976 _c(' xcb_out.%s = 0;', field.c_field_name)
1978 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
1980 if field.type.nmemb == 1:
1981 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
1983 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
1985 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
1986 serialize_args = get_serialize_params(context, type_obj,
1989 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
1991 # calls in order to free dyn. all. memory
1995 if not self.var_followed_by_fixed_fields:
1996 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
1997 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
1998 _c(' xcb_parts[3].iov_base = 0;')
1999 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2003 for field in param_fields:
2004 if not field.type.fixed_size():
2005 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
2006 # default: simple cast to char *
2007 if not field.type.need_serialize and not field.type.need_sizeof:
2008 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2009 if field.type.is_list:
2010 if field.type.member.fixed_size():
2011 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
2012 _c_accessor_get_expr(field.type.expr, None),
2013 field.type.member.c_wiretype)
2015 list_length = _c_accessor_get_expr(field.type.expr, None)
2018 _c(" xcb_parts[%d].iov_len = 0;" % count)
2019 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2020 _c(" for(i=0; i<%s; i++) {" % list_length)
2021 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2022 (field.type.c_sizeof_name))
2023 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2024 _c(" xcb_tmp += xcb_tmp_len;")
2027 # not supposed to happen
2028 raise Exception("unhandled variable size field %s" % field.c_field_name)
2031 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2032 idx = serial_fields.index(field)
2033 aux_var = '&xcb_aux%d' % idx
2034 context = 'serialize' if aux else 'sizeof'
2035 _c(' xcb_parts[%d].iov_len = ', count)
2037 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2038 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2039 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2040 free_calls.append(' free(xcb_aux%d);' % idx)
2042 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2043 func_name = field.type.c_sizeof_name
2044 _c(' %s (%s);', func_name, serialize_args)
2047 if not (field.type.need_serialize or field.type.need_sizeof):
2048 # the _serialize() function keeps track of padding automatically
2049 _c(' xcb_parts[%d].iov_base = 0;', count)
2050 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2053 # elif self.var_followed_by_fixed_fields:
2055 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2056 # request header: opcodes + length
2057 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2060 buffer_var = '&xcb_aux'
2061 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2062 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2063 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2064 free_calls.append(' free(xcb_aux);')
2065 # no padding necessary - _serialize() keeps track of padding automatically
2068 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2070 # free dyn. all. data, if any
2071 for f in free_calls:
2073 _c(' return xcb_ret;')
2076 def _c_reply(self, name):
2078 Declares the function that returns the reply structure.
2080 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2081 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2082 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2084 # check if _unserialize() has to be called for any field
2085 def look_for_special_cases(complex_obj):
2086 unserialize_fields = []
2087 # no unserialize call in case of switch
2088 if not complex_obj.is_switch:
2089 for field in complex_obj.fields:
2090 # three cases: 1. field with special case
2091 # 2. container that contains special case field
2092 # 3. list with special case elements
2093 if field.type.var_followed_by_fixed_fields:
2094 unserialize_fields.append(field)
2095 elif field.type.is_container:
2096 unserialize_fields += look_for_special_cases(field.type)
2097 elif field.type.is_list:
2098 if field.type.member.var_followed_by_fixed_fields:
2099 unserialize_fields.append(field)
2100 if field.type.member.is_container:
2101 unserialize_fields += look_for_special_cases(field.type.member)
2102 return unserialize_fields
2104 unserialize_fields = look_for_special_cases(self.reply)
2108 _h(' * Return the reply')
2109 _h(' * @param c The connection')
2110 _h(' * @param cookie The cookie')
2111 _h(' * @param e The xcb_generic_error_t supplied')
2113 _h(' * Returns the reply of the request asked by')
2115 _h(' * The parameter @p e supplied to this function must be NULL if')
2116 _h(' * %s(). is used.', self.c_unchecked_name)
2117 _h(' * Otherwise, it stores the error if any.')
2119 _h(' * The returned value must be freed by the caller using free().')
2123 _hc('/*****************************************************************************')
2125 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
2127 _hc(' ** @param xcb_connection_t%s *c', spacing1)
2128 _hc(' ** @param %s cookie', self.c_cookie_type)
2129 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
2130 _hc(' ** @returns %s *', self.c_reply_type)
2132 _hc(' *****************************************************************************/')
2134 _hc('%s *', self.c_reply_type)
2135 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2136 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2137 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2138 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2141 if len(unserialize_fields)>0:
2142 # certain variable size fields need to be unserialized explicitly
2143 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2144 self.c_reply_type, self.c_reply_type)
2146 for field in unserialize_fields:
2147 if field.type.is_list:
2148 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2149 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2150 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2152 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2153 # call _unserialize(), using the reply as source and target buffer
2154 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2155 for field in unserialize_fields:
2156 if field.type.is_list:
2157 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2158 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2159 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2160 field.c_field_name, field.c_field_name)
2161 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2163 # return the transformed reply
2164 _c(' return reply;')
2167 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2171 def _c_opcode(name, opcode):
2173 Declares the opcode define for requests, events, and errors.
2177 _h('/** Opcode for %s. */', _n(name))
2178 _h('#define %s %s', _n(name).upper(), opcode)
2180 def _c_cookie(self, name):
2182 Declares the cookie type for a non-void request.
2187 _h(' * @brief %s', self.c_cookie_type)
2189 _h('typedef struct %s {', self.c_cookie_type)
2190 _h(' unsigned int sequence; /**< */')
2191 _h('} %s;', self.c_cookie_type)
2193 def c_request(self, name):
2195 Exported function that handles request declarations.
2197 _c_type_setup(self, name, ('request',))
2200 # Cookie type declaration
2201 _c_cookie(self, name)
2204 _c_opcode(name, self.opcode)
2206 # Request structure declaration
2210 _c_type_setup(self.reply, name, ('reply',))
2211 # Reply structure definition
2212 _c_complex(self.reply)
2213 # Request prototypes
2214 _c_request_helper(self, name, self.c_cookie_type, False, True)
2215 _c_request_helper(self, name, self.c_cookie_type, False, False)
2217 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
2218 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
2220 _c_accessors(self.reply, name + ('reply',), name)
2221 _c_reply(self, name)
2223 # Request prototypes
2224 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2225 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2227 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2228 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2231 def c_event(self, name):
2233 Exported function that handles event declarations.
2235 _c_type_setup(self, name, ('event',))
2238 _c_opcode(name, self.opcodes[name])
2240 if self.name == name:
2241 # Structure definition
2246 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2248 def c_error(self, name):
2250 Exported function that handles error declarations.
2252 _c_type_setup(self, name, ('error',))
2255 _c_opcode(name, self.opcodes[name])
2257 if self.name == name:
2258 # Structure definition
2263 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2266 # Main routine starts here
2268 # Must create an "output" dictionary before any xcbgen imports.
2269 output = {'open' : c_open,
2271 'simple' : c_simple,
2273 'struct' : c_struct,
2275 'request' : c_request,
2280 # Boilerplate below this point
2282 # Check for the argument that specifies path to the xcbgen python package.
2284 opts, args = getopt.getopt(sys.argv[1:], 'p:')
2285 except getopt.GetoptError, err:
2287 print 'Usage: c_client.py [-p path] file.xml'
2290 for (opt, arg) in opts:
2292 sys.path.append(arg)
2294 # Import the module class
2296 from xcbgen.state import Module
2299 print 'Failed to load the xcbgen Python package!'
2300 print 'Make sure that xcb/proto installed it on your Python path.'
2301 print 'If not, you will need to create a .pth file or define $PYTHONPATH'
2302 print 'to extend the path.'
2303 print 'Refer to the README file in xcb/proto for more info.'
2307 # Parse the xml header
2308 module = Module(args[0], output)
2310 # Build type-registry and resolve type dependencies