2 from xml.etree.cElementTree import *
3 from os.path import basename
4 from functools import reduce
9 # Jump to the bottom of this file for the main routine
11 # Some hacks to make the API more readable, and to keep backwards compability
12 _cname_re = re.compile('([A-Z0-9][a-z]+|[A-Z0-9]+(?![a-z])|[a-z]+)')
13 _cname_special_cases = {'DECnet':'decnet'}
15 _extension_special_cases = ['XPrint', 'XCMisc', 'BigRequests']
17 _cplusplus_annoyances = {'class' : '_class',
20 _c_keywords = {'default' : '_default'}
28 # global variable to keep track of serializers and
29 # switch data types due to weird dependencies
30 finished_serializers = []
36 Writes the given line to the header file.
38 _hlines[_hlevel].append(fmt % args)
42 Writes the given line to the source file.
44 _clines[_clevel].append(fmt % args)
48 Writes the given line to both the header and source files.
53 # XXX See if this level thing is really necessary.
56 Changes the array that header lines are written to.
57 Supports writing different sections of the header file.
60 while len(_hlines) <= idx:
66 Changes the array that source lines are written to.
67 Supports writing to different sections of the source file.
70 while len(_clines) <= idx:
76 Does C-name conversion on a single string fragment.
77 Uses a regexp with some hard-coded special cases.
79 if str in _cname_special_cases:
80 return _cname_special_cases[str]
82 split = _cname_re.finditer(str)
83 name_parts = [match.group(0) for match in split]
84 return '_'.join(name_parts)
88 Checks for certain C++ reserved words and fixes them.
90 if str in _cplusplus_annoyances:
91 return _cplusplus_annoyances[str]
92 elif str in _c_keywords:
93 return _c_keywords[str]
99 Does C-name conversion on an extension name.
100 Has some additional special cases on top of _n_item.
102 if str in _extension_special_cases:
103 return _n_item(str).lower()
109 Does C-name conversion on a tuple of strings.
110 Different behavior depending on length of tuple, extension/not extension, etc.
111 Basically C-name converts the individual pieces, then joins with underscores.
116 parts = [list[0], _n_item(list[1])]
118 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
120 parts = [list[0]] + [_n_item(i) for i in list[1:]]
121 return '_'.join(parts).lower()
125 Does C-name conversion on a tuple of strings representing a type.
126 Same as _n but adds a "_t" on the end.
131 parts = [list[0], _n_item(list[1]), 't']
133 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
135 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
136 return '_'.join(parts).lower()
141 Exported function that handles module open.
142 Opens the files and writes out the auto-generated comment, header file includes, etc.
146 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
148 # Build the type-name collision avoidance table used by c_enum
149 build_collision_table()
155 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
156 _hc(' * Edit at your peril.')
161 _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
162 _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
166 _h('#ifndef __%s_H', _ns.header.upper())
167 _h('#define __%s_H', _ns.header.upper())
169 _h('#include "xcb.h"')
171 _c('#include <stdlib.h>')
172 _c('#include <string.h>')
173 _c('#include <assert.h>')
174 _c('#include "xcbext.h"')
175 _c('#include "%s.h"', _ns.header)
178 for (n, h) in self.imports:
179 _hc('#include "%s.h"', h)
182 _h('#ifdef __cplusplus')
188 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
189 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
191 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
194 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
198 Exported function that handles module close.
199 Writes out all the stored content lines, then closes the files.
206 _h('#ifdef __cplusplus')
218 hfile = open('%s.h' % _ns.header, 'w')
226 cfile = open('%s.c' % _ns.header, 'w')
233 def build_collision_table():
237 for v in module.types.values():
239 namecount[name] = (namecount.get(name) or 0) + 1
241 def c_enum(self, name):
243 Exported function that handles enum declarations.
247 if namecount[tname] > 1:
248 tname = _t(name + ('enum',))
252 _h('typedef enum %s {', tname)
254 count = len(self.values)
256 for (enam, eval) in self.values:
258 equals = ' = ' if eval != '' else ''
259 comma = ',' if count > 0 else ''
260 _h(' %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
264 def _c_type_setup(self, name, postfix):
266 Sets up all the C-related state by adding additional data fields to
267 all Field and Type objects. Here is where we figure out most of our
268 variable and function names.
270 Recurses into child fields and list member types.
272 # Do all the various names in advance
273 self.c_type = _t(name + postfix)
274 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
276 self.c_iterator_type = _t(name + ('iterator',))
277 self.c_next_name = _n(name + ('next',))
278 self.c_end_name = _n(name + ('end',))
280 self.c_request_name = _n(name)
281 self.c_checked_name = _n(name + ('checked',))
282 self.c_unchecked_name = _n(name + ('unchecked',))
283 self.c_reply_name = _n(name + ('reply',))
284 self.c_reply_type = _t(name + ('reply',))
285 self.c_cookie_type = _t(name + ('cookie',))
287 self.need_aux = False
288 self.need_serialize = False
289 self.need_sizeof = False
291 self.c_aux_name = _n(name + ('aux',))
292 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
293 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
294 self.c_serialize_name = _n(name + ('serialize',))
295 self.c_unserialize_name = _n(name + ('unserialize',))
296 self.c_unpack_name = _n(name + ('unpack',))
297 self.c_sizeof_name = _n(name + ('sizeof',))
299 # special case: structs where variable size fields are followed by fixed size fields
300 self.var_followed_by_fixed_fields = False
303 self.need_serialize = True
304 self.c_container = 'struct'
305 for bitcase in self.bitcases:
306 bitcase.c_field_name = _cpp(bitcase.field_name)
307 bitcase_name = bitcase.field_type if bitcase.type.has_name else name
308 _c_type_setup(bitcase.type, bitcase_name, ())
310 elif self.is_container:
312 self.c_container = 'union' if self.is_union else 'struct'
313 prev_varsized_field = None
314 prev_varsized_offset = 0
315 first_field_after_varsized = None
317 for field in self.fields:
318 _c_type_setup(field.type, field.field_type, ())
319 if field.type.is_list:
320 _c_type_setup(field.type.member, field.field_type, ())
321 if (field.type.nmemb is None):
322 self.need_sizeof = True
324 field.c_field_type = _t(field.field_type)
325 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
326 field.c_field_name = _cpp(field.field_name)
327 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb and field.type.nmemb > 1) else ''
328 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
330 # correct the c_pointer field for variable size non-list types
331 if not field.type.fixed_size() and field.c_pointer == ' ':
332 field.c_pointer = '*'
333 if field.type.is_list and not field.type.member.fixed_size():
334 field.c_pointer = '*'
336 if field.type.is_switch:
337 field.c_pointer = '*'
338 field.c_field_const_type = 'const ' + field.c_field_type
340 elif not field.type.fixed_size() and not field.type.is_bitcase:
341 self.need_sizeof = True
343 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
344 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
345 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
346 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
347 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
349 field.prev_varsized_field = prev_varsized_field
350 field.prev_varsized_offset = prev_varsized_offset
352 if prev_varsized_offset == 0:
353 first_field_after_varsized = field
354 field.first_field_after_varsized = first_field_after_varsized
356 if field.type.fixed_size():
357 prev_varsized_offset += field.type.size
358 # special case: intermixed fixed and variable size fields
359 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
360 if not self.is_union:
361 self.need_serialize = True
362 self.var_followed_by_fixed_fields = True
364 self.last_varsized_field = field
365 prev_varsized_field = field
366 prev_varsized_offset = 0
368 if self.var_followed_by_fixed_fields:
369 if field.type.fixed_size():
370 field.prev_varsized_field = None
372 if self.need_serialize:
373 # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
374 self.need_sizeof = True
376 # as switch does never appear at toplevel,
377 # continue here with type construction
379 if self.c_type not in finished_switch:
380 finished_switch.append(self.c_type)
381 # special: switch C structs get pointer fields for variable-sized members
383 for bitcase in self.bitcases:
384 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
385 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
386 # no list with switch as element, so no call to
387 # _c_iterator(field.type, field_name) necessary
389 if not self.is_bitcase:
390 if self.need_serialize:
391 if self.c_serialize_name not in finished_serializers:
392 finished_serializers.append(self.c_serialize_name)
393 _c_serialize('serialize', self)
395 # _unpack() and _unserialize() are only needed for special cases:
397 # special cases -> unserialize
398 if self.is_switch or self.var_followed_by_fixed_fields:
399 _c_serialize('unserialize', self)
402 if self.c_sizeof_name not in finished_sizeof:
403 if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
404 finished_sizeof.append(self.c_sizeof_name)
405 _c_serialize('sizeof', self)
408 def _c_helper_absolute_name(prefix, field=None):
410 turn prefix, which is a list of tuples (name, separator, Type obj) into a string
411 representing a valid name in C (based on the context)
412 if field is not None, append the field name as well
415 for name, sep, obj in prefix:
419 if ((obj.is_bitcase and obj.has_name) or # named bitcase
420 (obj.is_switch and len(obj.parents)>1)):
423 if field is not None:
424 prefix_str += _cpp(field.field_name)
428 def _c_helper_field_mapping(complex_type, prefix, flat=False):
430 generate absolute names, based on prefix, for all fields starting from complex_type
431 if flat == True, nested complex types are not taken into account
434 if complex_type.is_switch:
435 for b in complex_type.bitcases:
437 switch_name, switch_sep, switch_type = prefix[-1]
438 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
440 bitcase_prefix = prefix
442 if (True==flat and not b.type.has_name) or False==flat:
443 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
445 for f in complex_type.fields:
446 fname = _c_helper_absolute_name(prefix, f)
447 if f.field_name in all_fields:
448 raise Exception("field name %s has been registered before" % f.field_name)
450 all_fields[f.field_name] = (fname, f)
451 if f.type.is_container and flat==False:
452 if f.type.is_bitcase and not f.type.has_name:
454 elif f.type.is_switch and len(f.type.parents)>1:
455 # nested switch gets another separator
456 new_prefix = prefix+[(f.c_field_name, '.', f.type)]
458 new_prefix = prefix+[(f.c_field_name, '->', f.type)]
459 all_fields.update(_c_helper_field_mapping(f.type, new_prefix, flat))
464 def _c_helper_resolve_field_names (prefix):
466 get field names for all objects in the prefix array
470 # look for fields in the remaining containers
471 for idx, p in enumerate(prefix):
474 # sep can be preset in prefix, if not, make a sensible guess
475 sep = '.' if (obj.is_switch or obj.is_bitcase) else '->'
476 # exception: 'toplevel' object (switch as well!) always have sep '->'
477 sep = '->' if idx<1 else sep
478 if not obj.is_bitcase or (obj.is_bitcase and obj.has_name):
479 tmp_prefix.append((name, sep, obj))
480 all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
483 # _c_helper_resolve_field_names
485 def get_expr_fields(self):
487 get the Fields referenced by switch or list expression
489 def get_expr_field_names(expr):
491 if expr.lenfield_name is not None:
492 return [expr.lenfield_name]
494 # constant value expr
498 return get_expr_field_names(expr.rhs)
499 elif expr.op == 'popcount':
500 return get_expr_field_names(expr.rhs)
501 elif expr.op == 'sumof':
502 # sumof expr references another list,
503 # we need that list's length field here
505 for f in expr.lenfield_parent.fields:
506 if f.field_name == expr.lenfield_name:
510 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
511 # referenced list + its length field
512 return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
513 elif expr.op == 'enumref':
516 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
517 # get_expr_field_names()
519 # resolve the field names with the parent structure(s)
520 unresolved_fields_names = get_expr_field_names(self.expr)
522 # construct prefix from self
523 prefix = [('', '', p) for p in self.parents]
524 if self.is_container:
525 prefix.append(('', '', self))
527 all_fields = _c_helper_resolve_field_names (prefix)
528 resolved_fields_names = list(filter(lambda x: x in all_fields.keys(), unresolved_fields_names))
529 if len(unresolved_fields_names) != len(resolved_fields_names):
530 raise Exception("could not resolve all fields for %s" % self.name)
532 resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
533 return resolved_fields
536 def resolve_expr_fields(complex_obj):
538 find expr fields appearing in complex_obj and descendents that cannot be resolved within complex_obj
539 these are normally fields that need to be given as function parameters
545 for field in complex_obj.fields:
546 all_fields.append(field)
547 if field.type.is_switch or field.type.is_list:
548 expr_fields += get_expr_fields(field.type)
549 if field.type.is_container:
550 expr_fields += resolve_expr_fields(field.type)
552 # try to resolve expr fields
553 for e in expr_fields:
554 if e not in all_fields and e not in unresolved:
557 # resolve_expr_fields()
559 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
561 functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
562 E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch
563 expression. This function tries to resolve all fields within a structure, and returns the
564 unresolved fields as the list of external parameters.
566 def add_param(params, param):
567 if param not in params:
570 # collect all fields into param_fields
574 for field in self.fields:
576 # the field should appear as a parameter in the function call
577 param_fields.append(field)
578 if field.wire and not field.auto:
579 if field.type.fixed_size() and not self.is_switch:
580 # field in the xcb_out structure
581 wire_fields.append(field)
582 # fields like 'pad0' are skipped!
584 # in case of switch, parameters always contain any fields referenced in the switch expr
585 # we do not need any variable size fields here, as the switch data type contains both
586 # fixed and variable size fields
588 param_fields = get_expr_fields(self)
590 # _serialize()/_unserialize()/_unpack() function parameters
591 # note: don't use set() for params, it is unsorted
594 # 1. the parameter for the void * buffer
595 if 'serialize' == context:
596 params.append(('void', '**', buffer_var))
597 elif context in ('unserialize', 'unpack', 'sizeof'):
598 params.append(('const void', '*', buffer_var))
600 # 2. any expr fields that cannot be resolved within self and descendants
601 unresolved_fields = resolve_expr_fields(self)
602 for f in unresolved_fields:
603 add_param(params, (f.c_field_type, '', f.c_field_name))
605 # 3. param_fields contain the fields necessary to evaluate the switch expr or any other fields
606 # that do not appear in the data type struct
607 for p in param_fields:
609 typespec = p.c_field_const_type
610 pointerspec = p.c_pointer
611 add_param(params, (typespec, pointerspec, p.c_field_name))
613 if p.visible and not p.wire and not p.auto:
614 typespec = p.c_field_type
616 add_param(params, (typespec, pointerspec, p.c_field_name))
619 if 'serialize' == context:
620 add_param(params, ('const %s' % self.c_type, '*', aux_var))
621 elif 'unserialize' == context:
622 add_param(params, ('%s' % self.c_type, '**', aux_var))
623 elif 'unpack' == context:
624 add_param(params, ('%s' % self.c_type, '*', aux_var))
626 # 5. switch contains all variable size fields as struct members
627 # for other data types though, these have to be supplied separately
628 # this is important for the special case of intermixed fixed and
629 # variable size fields
630 if not self.is_switch and 'serialize' == context:
631 for p in param_fields:
632 if not p.type.fixed_size():
633 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
635 return (param_fields, wire_fields, params)
636 # get_serialize_params()
638 def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
639 code_lines.append('%s /* insert padding */' % space)
640 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
641 # code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
642 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
645 code_lines.append('%s if (0 != xcb_pad) {' % space)
647 if 'serialize' == context:
648 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
649 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
650 code_lines.append('%s xcb_parts_idx++;' % space)
651 elif context in ('unserialize', 'unpack', 'sizeof'):
652 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
654 code_lines.append('%s xcb_pad = 0;' % space)
655 code_lines.append('%s }' % space)
657 code_lines.append('%s xcb_block_len = 0;' % space)
659 # keep tracking of xcb_parts entries for serialize
661 # _c_serialize_helper_insert_padding()
663 def _c_serialize_helper_switch(context, self, complex_name,
664 code_lines, temp_vars,
667 switch_expr = _c_accessor_get_expr(self.expr, None)
669 for b in self.bitcases:
670 bitcase_expr = _c_accessor_get_expr(b.type.expr, None)
671 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
672 # code_lines.append(' printf("switch %s: entering bitcase section %s (mask=%%%%d)...\\n", %s);' %
673 # (self.name[-1], b.type.name[-1], bitcase_expr))
676 b_prefix = prefix + [(b.c_field_name, '.', b.type)]
678 count += _c_serialize_helper_fields(context, b.type,
679 code_lines, temp_vars,
683 code_lines.append(' }')
685 # if 'serialize' == context:
686 # count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
687 # elif context in ('unserialize', 'unpack', 'sizeof'):
689 # code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
690 # code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
693 # _c_serialize_helper_switch
695 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
697 handle switch by calling _serialize() or _unpack(), depending on context
699 # switch is handled by this function as a special case
700 param_fields, wire_fields, params = get_serialize_params(context, self)
701 field_mapping = _c_helper_field_mapping(self, prefix)
702 prefix_str = _c_helper_absolute_name(prefix)
704 # find the parameters that need to be passed to _serialize()/_unpack():
705 # all switch expr fields must be given as parameters
706 args = get_expr_fields(field.type)
707 # length fields for variable size types in switch, normally only some of need
708 # need to be passed as parameters
709 switch_len_fields = resolve_expr_fields(field.type)
711 # a switch field at this point _must_ be a bitcase field
712 # we require that bitcases are "self-contiguous"
713 bitcase_unresolved = resolve_expr_fields(self)
714 if len(bitcase_unresolved) != 0:
715 raise Exception('unresolved fields within bitcase is not supported at this point')
717 # get the C names for the parameters
719 for a in switch_len_fields:
720 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
722 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
724 # call _serialize()/_unpack() to determine the actual size
725 if 'serialize' == context:
726 length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
727 c_field_names, prefix_str, field.c_field_name)
728 elif context in ('unserialize', 'unpack'):
729 length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
730 c_field_names, prefix_str, field.c_field_name)
733 # _c_serialize_helper_switch_field()
735 def _c_serialize_helper_list_field(context, self, field,
736 code_lines, temp_vars,
739 helper function to cope with lists of variable length
741 expr = field.type.expr
742 prefix_str = _c_helper_absolute_name(prefix)
743 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
744 param_names = [p[2] for p in params]
746 expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
747 resolved = list(filter(lambda x: x in param_names, expr_fields_names))
748 unresolved = list(filter(lambda x: x not in param_names, expr_fields_names))
752 field_mapping[r] = (r, None)
754 if len(unresolved)>0:
756 if len(tmp_prefix)==0:
757 raise Exception("found an empty prefix while resolving expr field names for list %s",
760 field_mapping.update(_c_helper_resolve_field_names(prefix))
761 resolved += list(filter(lambda x: x in field_mapping, unresolved))
762 unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
763 if len(unresolved)>0:
764 raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
766 list_length = _c_accessor_get_expr(expr, field_mapping)
768 # default: list with fixed size elements
769 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
771 # list with variable-sized elements
772 if not field.type.member.fixed_size():
774 if context in ('unserialize', 'sizeof', 'unpack'):
775 int_i = ' unsigned int i;'
776 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
777 if int_i not in temp_vars:
778 temp_vars.append(int_i)
779 if xcb_tmp_len not in temp_vars:
780 temp_vars.append(xcb_tmp_len)
781 # loop over all list elements and call sizeof repeatedly
782 # this should be a bit faster than using the iterators
783 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
784 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
785 (space, field.type.c_sizeof_name))
786 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
787 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
788 code_lines.append("%s }" % space)
790 elif 'serialize' == context:
791 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
792 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
793 code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length))
794 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
795 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
796 code_lines.append('%s }' % space)
797 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
800 # _c_serialize_helper_list_field()
802 def _c_serialize_helper_fields_fixed_size(context, self, field,
803 code_lines, temp_vars,
805 # keep the C code a bit more readable by giving the field name
806 if not self.is_bitcase:
807 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
809 scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
810 typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
811 code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
813 abs_field_name = _c_helper_absolute_name(prefix, field)
814 # default for simple cases: call sizeof()
815 length = "sizeof(%s)" % field.c_field_type
817 if context in ('unserialize', 'unpack', 'sizeof'):
818 # default: simple cast
819 value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
821 # padding - we could probably just ignore it
822 if field.type.is_pad and field.type.nmemb > 1:
824 for i in range(field.type.nmemb):
825 code_lines.append('%s %s[%d] = *(%s *)xcb_tmp;' %
826 (space, abs_field_name, i, field.c_field_type))
827 # total padding = sizeof(pad0) * nmemb
828 length += " * %d" % field.type.nmemb
830 if field.type.is_list:
831 # no such case in the protocol, cannot be tested and therefore ignored for now
832 raise Exception('list with fixed number of elemens unhandled in _unserialize()')
834 elif 'serialize' == context:
835 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
837 if field.type.is_expr:
838 # need to register a temporary variable for the expression in case we know its type
839 if field.type.c_type is None:
840 raise Exception("type for field '%s' (expression '%s') unkown" %
841 (field.field_name, _c_accessor_get_expr(field.type.expr)))
843 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
844 _c_accessor_get_expr(field.type.expr, prefix)))
845 value += "&xcb_expr_%s;" % _cpp(field.field_name)
847 elif field.type.is_pad:
848 if field.type.nmemb == 1:
851 # we could also set it to 0, see definition of xcb_send_request()
852 value = ' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
853 length += "*%d" % field.type.nmemb
856 # non-list type with fixed size
857 if field.type.nmemb == 1:
858 value += "&%s;" % (abs_field_name)
860 # list with nmemb (fixed size) elements
862 value += '%s;' % (abs_field_name)
863 length = '%d' % field.type.nmemb
865 return (value, length)
866 # _c_serialize_helper_fields_fixed_size()
868 def _c_serialize_helper_fields_variable_size(context, self, field,
869 code_lines, temp_vars,
871 prefix_str = _c_helper_absolute_name(prefix)
873 if context in ('unserialize', 'unpack', 'sizeof'):
875 var_field_name = 'xcb_tmp'
877 # special case: intermixed fixed and variable size fields
878 if self.var_followed_by_fixed_fields and 'unserialize' == context:
879 value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
880 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
881 # special case: switch
882 if 'unpack' == context:
883 value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
885 elif 'serialize' == context:
886 # variable size fields appear as parameters to _serialize() if the
887 # 'toplevel' container is not a switch
888 prefix_string = prefix_str if prefix[0][2].is_switch else ''
889 var_field_name = "%s%s" % (prefix_string, field.c_field_name)
890 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
894 code_lines.append('%s /* %s */' % (space, field.c_field_name))
896 if field.type.is_list:
898 # in any context, list is already a pointer, so the default assignment is ok
899 code_lines.append("%s%s" % (space, value))
901 length = _c_serialize_helper_list_field(context, self, field,
902 code_lines, temp_vars,
905 elif field.type.is_switch:
907 if context == 'serialize':
908 # the _serialize() function allocates the correct amount memory if given a NULL pointer
909 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
910 length = _c_serialize_helper_switch_field(context, self, field,
911 'xcb_parts[xcb_parts_idx].iov_base',
915 # in all remaining special cases - call _sizeof()
916 length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
918 return (value, length)
919 # _c_serialize_helper_fields_variable_size
921 def _c_serialize_helper_fields(context, self,
922 code_lines, temp_vars,
923 space, prefix, is_bitcase):
926 prev_field_was_variable = False
928 for field in self.fields:
929 if not field.visible:
930 if not ((field.wire and not field.auto) or 'unserialize' == context):
933 # switch/bitcase: fixed size fields must be considered explicitly
934 if field.type.fixed_size():
935 if self.is_bitcase or self.var_followed_by_fixed_fields:
936 if prev_field_was_variable and need_padding:
938 # count += _c_serialize_helper_insert_padding(context, code_lines, space,
939 # self.var_followed_by_fixed_fields)
940 prev_field_was_variable = False
942 # prefix for fixed size fields
943 fixed_prefix = prefix
945 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
946 code_lines, temp_vars,
951 # fields with variable size
953 # switch/bitcase: always calculate padding before and after variable sized fields
954 if need_padding or is_bitcase:
955 count += _c_serialize_helper_insert_padding(context, code_lines, space,
956 self.var_followed_by_fixed_fields)
958 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
959 code_lines, temp_vars,
961 prev_field_was_variable = True
963 # save (un)serialization C code
965 code_lines.append('%s%s' % (space, value))
967 if field.type.fixed_size():
968 if is_bitcase or self.var_followed_by_fixed_fields:
969 # keep track of (un)serialized object's size
970 code_lines.append('%s xcb_block_len += %s;' % (space, length))
971 if context in ('unserialize', 'unpack', 'sizeof'):
972 code_lines.append('%s xcb_tmp += %s;' % (space, length))
974 # variable size objects or bitcase:
975 # value & length might have been inserted earlier for special cases
977 # special case: intermixed fixed and variable size fields
978 if (not field.type.fixed_size() and
979 self.var_followed_by_fixed_fields and 'unserialize' == context):
980 temp_vars.append(' int %s_len;' % field.c_field_name)
981 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
982 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
983 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
985 code_lines.append('%s xcb_block_len += %s;' % (space, length))
986 # increase pointer into the byte stream accordingly
987 if context in ('unserialize', 'sizeof', 'unpack'):
988 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
990 if 'serialize' == context:
992 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
993 code_lines.append('%s xcb_parts_idx++;' % space)
997 if self.var_followed_by_fixed_fields:
1001 # _c_serialize_helper_fields()
1003 def _c_serialize_helper(context, complex_type,
1004 code_lines, temp_vars,
1005 space='', prefix=[]):
1006 # count tracks the number of fields to serialize
1009 if hasattr(complex_type, 'type'):
1010 self = complex_type.type
1011 complex_name = complex_type.name
1014 if self.var_followed_by_fixed_fields and 'unserialize' == context:
1015 complex_name = 'xcb_out'
1017 complex_name = '_aux'
1019 # special case: switch is serialized by evaluating each bitcase separately
1021 count += _c_serialize_helper_switch(context, self, complex_name,
1022 code_lines, temp_vars,
1025 # all other data types can be evaluated one field a time
1027 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1028 if context in ('unserialize', 'unpack', 'sizeof') and not self.var_followed_by_fixed_fields:
1029 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1030 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1031 # probably not needed
1032 #_c_serialize_helper_insert_padding(context, code_lines, space, False)
1034 count += _c_serialize_helper_fields(context, self,
1035 code_lines, temp_vars,
1036 space, prefix, False)
1038 count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
1041 # _c_serialize_helper()
1043 def _c_serialize(context, self):
1045 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1046 for the ComplexType variable self
1052 # _serialize() returns the buffer size
1055 if self.is_switch and 'unserialize' == context:
1058 cases = { 'serialize' : self.c_serialize_name,
1059 'unserialize' : self.c_unserialize_name,
1060 'unpack' : self.c_unpack_name,
1061 'sizeof' : self.c_sizeof_name }
1062 func_name = cases[context]
1064 param_fields, wire_fields, params = get_serialize_params(context, self)
1065 variable_size_fields = 0
1066 # maximum space required for type definition of function arguments
1069 # determine N(variable_fields)
1070 for field in param_fields:
1071 # if self.is_switch, treat all fields as if they are variable sized
1072 if not field.type.fixed_size() or self.is_switch:
1073 variable_size_fields += 1
1074 # determine maxtypelen
1076 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1079 indent = ' '*(len(func_name)+2)
1082 typespec, pointerspec, field_name = p
1083 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1084 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1085 # insert function name
1086 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1087 param_str = list(map(lambda x: "%s," % x, param_str))
1088 for s in param_str[:-1]:
1090 _h("%s);" % param_str[-1].rstrip(','))
1091 _c("%s)" % param_str[-1].rstrip(','))
1098 if 'serialize' == context:
1099 if not self.is_switch and not self.var_followed_by_fixed_fields:
1100 _c(' %s *xcb_out = *_buffer;', self.c_type)
1101 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1102 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1104 _c(' char *xcb_out = *_buffer;')
1105 _c(' unsigned int xcb_buffer_len = 0;')
1106 prefix = [('_aux', '->', self)]
1109 elif context in ('unserialize', 'unpack'):
1110 _c(' char *xcb_tmp = (char *)_buffer;')
1111 if not self.is_switch:
1112 if not self.var_followed_by_fixed_fields:
1113 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1114 prefix = [('_aux', '->', self)]
1116 _c(' %s xcb_out;', self.c_type)
1117 prefix = [('xcb_out', '.', self)]
1119 aux_var = '_aux' # default for unpack: single pointer
1120 # note: unserialize not generated for switch
1121 if 'unserialize' == context:
1122 aux_var = '(*_aux)' # unserialize: double pointer (!)
1123 prefix = [(aux_var, '->', self)]
1125 _c(' unsigned int xcb_buffer_len = 0;')
1126 _c(' unsigned int xcb_block_len = 0;')
1127 _c(' unsigned int xcb_pad = 0;')
1129 elif 'sizeof' == context:
1130 param_names = [p[2] for p in params]
1132 # switch: call _unpack()
1133 _c(' %s _aux;', self.c_type)
1134 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1137 elif self.var_followed_by_fixed_fields:
1138 # special case: call _unserialize()
1139 _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1143 _c(' char *xcb_tmp = (char *)_buffer;')
1144 prefix = [('_aux', '->', self)]
1146 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1147 # update variable size fields (only important for context=='serialize'
1148 variable_size_fields = count
1149 if 'serialize' == context:
1150 temp_vars.append(' unsigned int xcb_pad = 0;')
1151 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1152 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1153 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1154 temp_vars.append(' unsigned int xcb_block_len = 0;')
1155 temp_vars.append(' unsigned int i;')
1156 temp_vars.append(' char *xcb_tmp;')
1157 elif 'sizeof' == context:
1158 # neither switch nor intermixed fixed and variable size fields:
1159 # evaluate parameters directly
1160 if not (self.is_switch or self.var_followed_by_fixed_fields):
1162 # look if we have to declare an '_aux' variable at all
1163 if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
1164 if not self.var_followed_by_fixed_fields:
1165 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1167 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1169 _c(' unsigned int xcb_buffer_len = 0;')
1170 _c(' unsigned int xcb_block_len = 0;')
1171 _c(' unsigned int xcb_pad = 0;')
1177 for l in code_lines:
1180 # variable sized fields have been collected, now
1181 # allocate memory and copy everything into a continuous memory area
1182 # note: this is not necessary in case of unpack
1183 if context in ('serialize', 'unserialize'):
1184 # unserialize: check for sizeof-only invocation
1185 if 'unserialize' == context:
1187 _c(' if (NULL == _aux)')
1188 _c(' return xcb_buffer_len;')
1191 _c(' if (NULL == %s) {', aux_ptr)
1192 _c(' /* allocate memory */')
1193 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1194 if 'serialize' == context:
1195 _c(' *_buffer = xcb_out;')
1199 # serialize: handle variable size fields in a loop
1200 if 'serialize' == context:
1201 if not self.is_switch and not self.var_followed_by_fixed_fields:
1202 if len(wire_fields)>0:
1203 _c(' *xcb_out = *_aux;')
1204 # copy variable size fields into the buffer
1205 if variable_size_fields > 0:
1207 if not self.is_switch and not self.var_followed_by_fixed_fields:
1208 _c(' xcb_tmp = (char*)++xcb_out;')
1209 _c(' xcb_tmp += xcb_out_pad;')
1211 _c(' xcb_tmp = xcb_out;')
1213 # variable sized fields
1214 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1215 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1216 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1217 _c(' if (0 != xcb_parts[i].iov_len)')
1218 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1221 # unserialize: assign variable size fields individually
1222 if 'unserialize' == context:
1223 _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1224 param_fields.reverse()
1225 for field in param_fields:
1226 if not field.type.fixed_size():
1227 _c(' xcb_tmp -= %s_len;', field.c_field_name)
1228 _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1229 _c(' *%s = xcb_out;', aux_ptr)
1232 _c(' return xcb_buffer_len;')
1236 def _c_iterator_get_end(field, accum):
1238 Figures out what C code is needed to find the end of a variable-length structure field.
1239 For nested structures, recurses into its last variable-sized field.
1240 For lists, calls the end function
1242 if field.type.is_container:
1243 accum = field.c_accessor_name + '(' + accum + ')'
1244 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1245 if field.type.is_list:
1246 # XXX we can always use the first way
1247 if field.type.member.is_simple:
1248 return field.c_end_name + '(' + accum + ')'
1250 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1252 def _c_iterator(self, name):
1254 Declares the iterator structure and next/end functions for a given type.
1259 _h(' * @brief %s', self.c_iterator_type)
1261 _h('typedef struct %s {', self.c_iterator_type)
1262 _h(' %s *data; /**< */', self.c_type)
1263 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1264 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1265 _h('} %s;', self.c_iterator_type)
1271 _h(' * Get the next element of the iterator')
1272 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1274 _h(' * Get the next element in the iterator. The member rem is')
1275 _h(' * decreased by one. The member data points to the next')
1276 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1280 _hc('/*****************************************************************************')
1282 _hc(' ** void %s', self.c_next_name)
1284 _hc(' ** @param %s *i', self.c_iterator_type)
1285 _hc(' ** @returns void')
1287 _hc(' *****************************************************************************/')
1290 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1291 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1294 if not self.fixed_size():
1295 _c(' %s *R = i->data;', self.c_type)
1298 # FIXME - how to determine the size of a variable size union??
1299 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1301 if self.need_sizeof:
1302 _c(' xcb_generic_iterator_t child;')
1303 _c(' child.data = (%s *)(((char *)R) + %s(R));',
1304 self.c_type, self.c_sizeof_name)
1305 _c(' i->index = (char *) child.data - (char *) i->data;')
1307 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1308 _c(' i->index = child.index;')
1310 _c(' i->data = (%s *) child.data;', self.c_type)
1315 _c(' i->index += sizeof(%s);', self.c_type)
1321 _h(' * Return the iterator pointing to the last element')
1322 _h(' * @param i An %s', self.c_iterator_type)
1323 _h(' * @return The iterator pointing to the last element')
1325 _h(' * Set the current element in the iterator to the last element.')
1326 _h(' * The member rem is set to 0. The member data points to the')
1327 _h(' * last element.')
1331 _hc('/*****************************************************************************')
1333 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1335 _hc(' ** @param %s i', self.c_iterator_type)
1336 _hc(' ** @returns xcb_generic_iterator_t')
1338 _hc(' *****************************************************************************/')
1340 _hc('xcb_generic_iterator_t')
1341 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1342 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1344 _c(' xcb_generic_iterator_t ret;')
1346 if self.fixed_size():
1347 _c(' ret.data = i.data + i.rem;')
1348 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1351 _c(' while(i.rem > 0)')
1352 _c(' %s(&i);', self.c_next_name)
1353 _c(' ret.data = i.data;')
1354 _c(' ret.rem = i.rem;')
1355 _c(' ret.index = i.index;')
1360 def _c_accessor_get_length(expr, field_mapping=None):
1362 Figures out what C code is needed to get a length field.
1363 The field_mapping parameter can be used to change the absolute name of a length field.
1364 For fields that follow a variable-length field, use the accessor.
1365 Otherwise, just reference the structure field directly.
1368 lenfield_name = expr.lenfield_name
1369 if lenfield_name is not None:
1370 if field_mapping is not None:
1371 lenfield_name = field_mapping[lenfield_name][0]
1373 if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1374 # special case: variable and fixed size fields are intermixed
1375 # if the lenfield is among the fixed size fields, there is no need
1376 # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1377 return field_mapping(expr.lenfield_name)
1378 elif expr.lenfield_name is not None:
1379 return lenfield_name
1381 return str(expr.nmemb)
1383 def _c_accessor_get_expr(expr, field_mapping):
1385 Figures out what C code is needed to get the length of a list field.
1386 The field_mapping parameter can be used to change the absolute name of a length field.
1387 Recurses for math operations.
1388 Returns bitcount for value-mask fields.
1389 Otherwise, uses the value of the length field.
1391 lenexp = _c_accessor_get_length(expr, field_mapping)
1394 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1395 elif expr.op == 'popcount':
1396 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1397 elif expr.op == 'enumref':
1398 enum_name = expr.lenfield_type.name
1399 constant_name = expr.lenfield_name
1400 c_name = _n(enum_name + (constant_name,)).upper()
1402 elif expr.op == 'sumof':
1403 # locate the referenced list object
1404 list_obj = expr.lenfield_type
1406 for f in expr.lenfield_parent.fields:
1407 if f.field_name == expr.lenfield_name:
1412 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1413 list_name = field_mapping[field.c_field_name][0]
1414 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1415 # note: xcb_sumof() has only been defined for integers
1416 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1417 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1418 elif expr.op != None:
1419 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1420 ' ' + expr.op + ' ' +
1421 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1423 return 'xcb_popcount(' + lenexp + ')'
1427 def type_pad_type(type):
1432 def _c_accessors_field(self, field):
1434 Declares the accessor functions for a non-list field that follows a variable-length field.
1436 c_type = self.c_type
1438 # special case: switch
1439 switch_obj = self if self.is_switch else None
1441 switch_obj = self.parents[-1]
1442 if switch_obj is not None:
1443 c_type = switch_obj.c_type
1445 if field.type.is_simple:
1448 _hc('/*****************************************************************************')
1450 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1452 _hc(' ** @param const %s *R', c_type)
1453 _hc(' ** @returns %s', field.c_field_type)
1455 _hc(' *****************************************************************************/')
1457 _hc('%s', field.c_field_type)
1458 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1459 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1461 if field.prev_varsized_field is None:
1462 _c(' return (%s *) (R + 1);', field.c_field_type)
1464 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1465 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1466 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1471 _hc('/*****************************************************************************')
1473 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1475 _hc(' ** @param const %s *R', c_type)
1476 _hc(' ** @returns %s *', field.c_field_type)
1478 _hc(' *****************************************************************************/')
1480 if field.type.is_switch and switch_obj is None:
1481 return_type = 'void *'
1483 return_type = '%s *' % field.c_field_type
1486 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1487 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1489 if field.prev_varsized_field is None:
1490 _c(' return (%s) (R + 1);', return_type)
1491 # note: the special case 'variable fields followed by fixed size fields'
1492 # is not of any consequence here, since the ordering gets
1493 # 'corrected' in the reply function
1495 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1496 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1497 return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1501 def _c_accessors_list(self, field):
1503 Declares the accessor functions for a list field.
1504 Declares a direct-accessor function only if the list members are fixed size.
1505 Declares length and get-iterator functions always.
1508 c_type = self.c_type
1510 # special case: switch
1511 # in case of switch, 2 params have to be supplied to certain accessor functions:
1512 # 1. the anchestor object (request or reply)
1513 # 2. the (anchestor) switch object
1514 # the reason is that switch is either a child of a request/reply or nested in another switch,
1515 # so whenever we need to access a length field, we might need to refer to some anchestor type
1516 switch_obj = self if self.is_switch else None
1518 switch_obj = self.parents[-1]
1519 if switch_obj is not None:
1520 c_type = switch_obj.c_type
1524 parents = self.parents if hasattr(self, 'parents') else [self]
1525 # 'R': parents[0] is always the 'toplevel' container type
1526 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1527 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1528 # auxiliary object for 'R' parameters
1531 if switch_obj is not None:
1532 # now look where the fields are defined that are needed to evaluate
1533 # the switch expr, and store the parent objects in accessor_params and
1534 # the fields in switch_fields
1536 # 'S': name for the 'toplevel' switch
1537 toplevel_switch = parents[1]
1538 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1539 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1541 # initialize prefix for everything "below" S
1542 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1543 prefix = [(prefix_str, '->', toplevel_switch)]
1545 # look for fields in the remaining containers
1546 for p in parents[2:] + [self]:
1547 # the separator between parent and child is always '.' here,
1548 # because of nested switch statements
1549 if not p.is_bitcase or (p.is_bitcase and p.has_name):
1550 prefix.append((p.name[-1], '.', p))
1551 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1553 # auxiliary object for 'S' parameter
1558 if list.member.fixed_size():
1559 idx = 1 if switch_obj is not None else 0
1562 _hc('/*****************************************************************************')
1564 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1566 _hc(' ** @param %s', params[idx][0])
1567 _hc(' ** @returns %s *', field.c_field_type)
1569 _hc(' *****************************************************************************/')
1571 _hc('%s *', field.c_field_type)
1573 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1574 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1577 if switch_obj is not None:
1578 _c(' return %s;', fields[field.c_field_name][0])
1579 elif field.prev_varsized_field is None:
1580 _c(' return (%s *) (R + 1);', field.c_field_type)
1582 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1583 _c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1584 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1589 _hc('/*****************************************************************************')
1591 _hc(' ** int %s', field.c_length_name)
1593 _hc(' ** @param const %s *R', c_type)
1594 _hc(' ** @returns int')
1596 _hc(' *****************************************************************************/')
1599 if switch_obj is not None:
1600 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1601 spacing = ' '*(len(field.c_length_name)+2)
1602 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1603 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1604 length = _c_accessor_get_expr(field.type.expr, fields)
1606 _h('%s (const %s *R /**< */);', field.c_length_name, c_type)
1607 _c('%s (const %s *R /**< */)', field.c_length_name, c_type)
1608 length = _c_accessor_get_expr(field.type.expr, fields)
1610 _c(' return %s;', length)
1613 if field.type.member.is_simple:
1616 _hc('/*****************************************************************************')
1618 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1620 _hc(' ** @param const %s *R', c_type)
1621 _hc(' ** @returns xcb_generic_iterator_t')
1623 _hc(' *****************************************************************************/')
1625 _hc('xcb_generic_iterator_t')
1626 if switch_obj is not None:
1627 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1628 spacing = ' '*(len(field.c_end_name)+2)
1629 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1630 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1632 _h('%s (const %s *R /**< */);', field.c_end_name, c_type)
1633 _c('%s (const %s *R /**< */)', field.c_end_name, c_type)
1635 _c(' xcb_generic_iterator_t i;')
1637 param = 'R' if switch_obj is None else 'S'
1638 if switch_obj is not None:
1639 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1640 _c_accessor_get_expr(field.type.expr, fields))
1641 elif field.prev_varsized_field == None:
1642 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1643 _c_accessor_get_expr(field.type.expr, fields))
1645 _c(' xcb_generic_iterator_t child = %s;',
1646 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1647 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1648 _c_accessor_get_expr(field.type.expr, fields))
1651 _c(' i.index = (char *) i.data - (char *) %s;', param)
1658 _hc('/*****************************************************************************')
1660 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1662 _hc(' ** @param const %s *R', c_type)
1663 _hc(' ** @returns %s', field.c_iterator_type)
1665 _hc(' *****************************************************************************/')
1668 _hc('%s', field.c_iterator_type)
1669 if switch_obj is not None:
1670 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1671 spacing = ' '*(len(field.c_iterator_name)+2)
1672 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1673 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1675 _h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
1676 _c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
1678 _c(' %s i;', field.c_iterator_type)
1680 if switch_obj is not None:
1681 _c(' i.data = %s;', fields[field.c_field_name][0])
1682 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1683 elif field.prev_varsized_field == None:
1684 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1686 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1687 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));',
1688 field.c_field_type, type_pad_type(field.c_field_type))
1689 if switch_obj is None:
1690 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1691 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1695 def _c_accessors(self, name, base):
1697 Declares the accessor functions for the fields of a structure.
1699 # no accessors for switch itself -
1700 # switch always needs to be unpacked explicitly
1701 # if self.is_switch:
1705 for field in self.fields:
1706 if field.type.is_list and not field.type.fixed_size():
1707 _c_accessors_list(self, field)
1708 elif field.prev_varsized_field is not None or not field.type.fixed_size():
1709 _c_accessors_field(self, field)
1711 def c_simple(self, name):
1713 Exported function that handles cardinal type declarations.
1714 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1716 _c_type_setup(self, name, ())
1718 if (self.name != name):
1723 _h('typedef %s %s;', _t(self.name), my_name)
1726 _c_iterator(self, name)
1728 def _c_complex(self):
1730 Helper function for handling all structure types.
1731 Called for all structs, requests, replies, events, errors.
1736 _h(' * @brief %s', self.c_type)
1738 _h('typedef %s %s {', self.c_container, self.c_type)
1744 for field in self.fields:
1745 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1746 varfield = field.c_field_name
1749 struct_fields.append(field)
1751 for field in struct_fields:
1752 length = len(field.c_field_type)
1753 # account for '*' pointer_spec
1754 if not field.type.fixed_size():
1756 maxtypelen = max(maxtypelen, length)
1758 def _c_complex_field(self, field, space=''):
1759 if (field.type.fixed_size() or
1760 # in case of switch with switch children, don't make the field a pointer
1761 # necessary for unserialize to work
1762 (self.is_switch and field.type.is_switch)):
1763 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1764 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1766 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1767 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1769 if not self.is_switch:
1770 for field in struct_fields:
1771 _c_complex_field(self, field)
1773 for b in self.bitcases:
1776 _h(' struct _%s {', b.c_field_name)
1778 for field in b.type.fields:
1779 _c_complex_field(self, field, space)
1781 _h(' } %s;', b.c_field_name)
1783 _h('} %s;', self.c_type)
1785 def c_struct(self, name):
1787 Exported function that handles structure declarations.
1789 _c_type_setup(self, name, ())
1791 _c_accessors(self, name, name)
1792 _c_iterator(self, name)
1794 def c_union(self, name):
1796 Exported function that handles union declarations.
1798 _c_type_setup(self, name, ())
1800 _c_iterator(self, name)
1802 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1804 Declares a request function.
1807 # Four stunningly confusing possibilities here:
1810 # ------------------------------
1812 # 0 flag CHECKED flag Normal Mode
1813 # void_cookie req_cookie
1814 # ------------------------------
1815 # "req_checked" "req_unchecked"
1816 # CHECKED flag 0 flag Abnormal Mode
1817 # void_cookie req_cookie
1818 # ------------------------------
1821 # Whether we are _checked or _unchecked
1822 checked = void and not regular
1823 unchecked = not void and not regular
1825 # What kind of cookie we return
1826 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1828 # What flag is passed to xcb_request
1829 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1831 # Global extension id variable or NULL for xproto
1832 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1834 # What our function name is
1835 func_name = self.c_request_name if not aux else self.c_aux_name
1837 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1839 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1843 maxtypelen = len('xcb_connection_t')
1845 # special case: list with variable size elements
1846 list_with_var_size_elems = False
1848 for field in self.fields:
1850 # The field should appear as a call parameter
1851 param_fields.append(field)
1852 if field.wire and not field.auto:
1853 # We need to set the field up in the structure
1854 wire_fields.append(field)
1855 if field.type.need_serialize or field.type.need_sizeof:
1856 serial_fields.append(field)
1858 for field in param_fields:
1859 c_field_const_type = field.c_field_const_type
1860 if field.type.need_serialize and not aux:
1861 c_field_const_type = "const void"
1862 if len(c_field_const_type) > maxtypelen:
1863 maxtypelen = len(c_field_const_type)
1864 if field.type.is_list and not field.type.member.fixed_size():
1865 list_with_var_size_elems = True
1871 _h(' * Delivers a request to the X server')
1872 _h(' * @param c The connection')
1873 _h(' * @return A cookie')
1875 _h(' * Delivers a request to the X server.')
1878 _h(' * This form can be used only if the request will not cause')
1879 _h(' * a reply to be generated. Any returned error will be')
1880 _h(' * saved for handling by xcb_request_check().')
1882 _h(' * This form can be used only if the request will cause')
1883 _h(' * a reply to be generated. Any returned error will be')
1884 _h(' * placed in the event queue.')
1888 _hc('/*****************************************************************************')
1890 _hc(' ** %s %s', cookie_type, func_name)
1893 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1894 _hc(' ** @param xcb_connection_t%s *c', spacing)
1896 for field in param_fields:
1897 c_field_const_type = field.c_field_const_type
1898 if field.type.need_serialize and not aux:
1899 c_field_const_type = "const void"
1900 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1901 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1903 _hc(' ** @returns %s', cookie_type)
1905 _hc(' *****************************************************************************/')
1907 _hc('%s', cookie_type)
1909 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1910 comma = ',' if len(param_fields) else ');'
1911 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1912 comma = ',' if len(param_fields) else ')'
1913 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1915 func_spacing = ' ' * (len(func_name) + 2)
1916 count = len(param_fields)
1917 for field in param_fields:
1919 c_field_const_type = field.c_field_const_type
1920 c_pointer = field.c_pointer
1921 if field.type.need_serialize and not aux:
1922 c_field_const_type = "const void"
1924 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1925 comma = ',' if count else ');'
1926 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1927 spacing, c_pointer, field.c_field_name, comma)
1928 comma = ',' if count else ')'
1929 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1930 spacing, c_pointer, field.c_field_name, comma)
1933 if not self.var_followed_by_fixed_fields:
1934 for field in param_fields:
1935 if not field.type.fixed_size():
1937 if field.type.need_serialize:
1938 # _serialize() keeps track of padding automatically
1940 dimension = count + 2
1943 _c(' static const xcb_protocol_request_t xcb_req = {')
1944 _c(' /* count */ %d,', count)
1945 _c(' /* ext */ %s,', func_ext_global)
1946 _c(' /* opcode */ %s,', self.c_request_name.upper())
1947 _c(' /* isvoid */ %d', 1 if void else 0)
1951 _c(' struct iovec xcb_parts[%d];', dimension)
1952 _c(' %s xcb_ret;', func_cookie)
1953 _c(' %s xcb_out;', self.c_type)
1954 if self.var_followed_by_fixed_fields:
1955 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
1956 _c(' void *xcb_aux = 0;')
1959 for idx, f in enumerate(serial_fields):
1961 _c(' void *xcb_aux%d = 0;' % (idx))
1962 if list_with_var_size_elems:
1963 _c(' unsigned int i;')
1964 _c(' unsigned int xcb_tmp_len;')
1965 _c(' char *xcb_tmp;')
1967 # simple request call tracing
1968 # _c(' printf("in function %s\\n");' % func_name)
1971 for field in wire_fields:
1972 if field.type.fixed_size():
1973 if field.type.is_expr:
1974 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
1975 elif field.type.is_pad:
1976 if field.type.nmemb == 1:
1977 _c(' xcb_out.%s = 0;', field.c_field_name)
1979 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
1981 if field.type.nmemb == 1:
1982 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
1984 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
1986 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
1987 serialize_args = get_serialize_params(context, type_obj,
1990 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
1992 # calls in order to free dyn. all. memory
1996 if not self.var_followed_by_fixed_fields:
1997 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
1998 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
1999 _c(' xcb_parts[3].iov_base = 0;')
2000 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2004 for field in param_fields:
2005 if not field.type.fixed_size():
2006 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
2007 # default: simple cast to char *
2008 if not field.type.need_serialize and not field.type.need_sizeof:
2009 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2010 if field.type.is_list:
2011 if field.type.member.fixed_size():
2012 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
2013 _c_accessor_get_expr(field.type.expr, None),
2014 field.type.member.c_wiretype)
2016 list_length = _c_accessor_get_expr(field.type.expr, None)
2019 _c(" xcb_parts[%d].iov_len = 0;" % count)
2020 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2021 _c(" for(i=0; i<%s; i++) {" % list_length)
2022 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2023 (field.type.c_sizeof_name))
2024 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2025 _c(" xcb_tmp += xcb_tmp_len;")
2028 # not supposed to happen
2029 raise Exception("unhandled variable size field %s" % field.c_field_name)
2032 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2033 idx = serial_fields.index(field)
2034 aux_var = '&xcb_aux%d' % idx
2035 context = 'serialize' if aux else 'sizeof'
2036 _c(' xcb_parts[%d].iov_len = ', count)
2038 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2039 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2040 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2041 free_calls.append(' free(xcb_aux%d);' % idx)
2043 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2044 func_name = field.type.c_sizeof_name
2045 _c(' %s (%s);', func_name, serialize_args)
2048 if not (field.type.need_serialize or field.type.need_sizeof):
2049 # the _serialize() function keeps track of padding automatically
2050 _c(' xcb_parts[%d].iov_base = 0;', count)
2051 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2054 # elif self.var_followed_by_fixed_fields:
2056 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2057 # request header: opcodes + length
2058 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2061 buffer_var = '&xcb_aux'
2062 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2063 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2064 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2065 free_calls.append(' free(xcb_aux);')
2066 # no padding necessary - _serialize() keeps track of padding automatically
2069 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2071 # free dyn. all. data, if any
2072 for f in free_calls:
2074 _c(' return xcb_ret;')
2077 def _c_reply(self, name):
2079 Declares the function that returns the reply structure.
2081 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2082 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2083 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2085 # check if _unserialize() has to be called for any field
2086 def look_for_special_cases(complex_obj):
2087 unserialize_fields = []
2088 # no unserialize call in case of switch
2089 if not complex_obj.is_switch:
2090 for field in complex_obj.fields:
2091 # three cases: 1. field with special case
2092 # 2. container that contains special case field
2093 # 3. list with special case elements
2094 if field.type.var_followed_by_fixed_fields:
2095 unserialize_fields.append(field)
2096 elif field.type.is_container:
2097 unserialize_fields += look_for_special_cases(field.type)
2098 elif field.type.is_list:
2099 if field.type.member.var_followed_by_fixed_fields:
2100 unserialize_fields.append(field)
2101 if field.type.member.is_container:
2102 unserialize_fields += look_for_special_cases(field.type.member)
2103 return unserialize_fields
2105 unserialize_fields = look_for_special_cases(self.reply)
2109 _h(' * Return the reply')
2110 _h(' * @param c The connection')
2111 _h(' * @param cookie The cookie')
2112 _h(' * @param e The xcb_generic_error_t supplied')
2114 _h(' * Returns the reply of the request asked by')
2116 _h(' * The parameter @p e supplied to this function must be NULL if')
2117 _h(' * %s(). is used.', self.c_unchecked_name)
2118 _h(' * Otherwise, it stores the error if any.')
2120 _h(' * The returned value must be freed by the caller using free().')
2124 _hc('/*****************************************************************************')
2126 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
2128 _hc(' ** @param xcb_connection_t%s *c', spacing1)
2129 _hc(' ** @param %s cookie', self.c_cookie_type)
2130 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
2131 _hc(' ** @returns %s *', self.c_reply_type)
2133 _hc(' *****************************************************************************/')
2135 _hc('%s *', self.c_reply_type)
2136 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2137 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2138 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2139 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2142 if len(unserialize_fields)>0:
2143 # certain variable size fields need to be unserialized explicitly
2144 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2145 self.c_reply_type, self.c_reply_type)
2147 for field in unserialize_fields:
2148 if field.type.is_list:
2149 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2150 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2151 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2153 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2154 # call _unserialize(), using the reply as source and target buffer
2155 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2156 for field in unserialize_fields:
2157 if field.type.is_list:
2158 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2159 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2160 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2161 field.c_field_name, field.c_field_name)
2162 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2164 # return the transformed reply
2165 _c(' return reply;')
2168 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2172 def _c_opcode(name, opcode):
2174 Declares the opcode define for requests, events, and errors.
2178 _h('/** Opcode for %s. */', _n(name))
2179 _h('#define %s %s', _n(name).upper(), opcode)
2181 def _c_cookie(self, name):
2183 Declares the cookie type for a non-void request.
2188 _h(' * @brief %s', self.c_cookie_type)
2190 _h('typedef struct %s {', self.c_cookie_type)
2191 _h(' unsigned int sequence; /**< */')
2192 _h('} %s;', self.c_cookie_type)
2194 def c_request(self, name):
2196 Exported function that handles request declarations.
2198 _c_type_setup(self, name, ('request',))
2201 # Cookie type declaration
2202 _c_cookie(self, name)
2205 _c_opcode(name, self.opcode)
2207 # Request structure declaration
2211 _c_type_setup(self.reply, name, ('reply',))
2212 # Reply structure definition
2213 _c_complex(self.reply)
2214 # Request prototypes
2215 _c_request_helper(self, name, self.c_cookie_type, False, True)
2216 _c_request_helper(self, name, self.c_cookie_type, False, False)
2218 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
2219 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
2221 _c_accessors(self.reply, name + ('reply',), name)
2222 _c_reply(self, name)
2224 # Request prototypes
2225 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2226 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2228 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2229 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2232 def c_event(self, name):
2234 Exported function that handles event declarations.
2236 _c_type_setup(self, name, ('event',))
2239 _c_opcode(name, self.opcodes[name])
2241 if self.name == name:
2242 # Structure definition
2247 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2249 def c_error(self, name):
2251 Exported function that handles error declarations.
2253 _c_type_setup(self, name, ('error',))
2256 _c_opcode(name, self.opcodes[name])
2258 if self.name == name:
2259 # Structure definition
2264 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2267 # Main routine starts here
2269 # Must create an "output" dictionary before any xcbgen imports.
2270 output = {'open' : c_open,
2272 'simple' : c_simple,
2274 'struct' : c_struct,
2276 'request' : c_request,
2281 # Boilerplate below this point
2283 # Check for the argument that specifies path to the xcbgen python package.
2285 opts, args = getopt.getopt(sys.argv[1:], 'p:')
2286 except getopt.GetoptError as err:
2288 print('Usage: c_client.py [-p path] file.xml')
2291 for (opt, arg) in opts:
2293 sys.path.insert(1, arg)
2295 # Import the module class
2297 from xcbgen.state import Module
2300 Failed to load the xcbgen Python package!
2301 Make sure that xcb/proto installed it on your Python path.
2302 If not, you will need to create a .pth file or define $PYTHONPATH
2304 Refer to the README file in xcb/proto for more info.
2308 # Parse the xml header
2309 module = Module(args[0], output)
2311 # Build type-registry and resolve type dependencies