2 from xml.etree.cElementTree import *
3 from os.path import basename
4 from functools import reduce
12 # Jump to the bottom of this file for the main routine
14 # Some hacks to make the API more readable, and to keep backwards compability
15 _cname_re = re.compile('([A-Z0-9][a-z]+|[A-Z0-9]+(?![a-z])|[a-z]+)')
16 _cname_special_cases = {'DECnet':'decnet'}
18 _extension_special_cases = ['XPrint', 'XCMisc', 'BigRequests']
20 _cplusplus_annoyances = {'class' : '_class',
23 _c_keywords = {'default' : '_default'}
31 # global variable to keep track of serializers and
32 # switch data types due to weird dependencies
33 finished_serializers = []
37 # keeps enum objects so that we can refer to them when generating manpages.
44 Writes the given line to the header file.
46 _hlines[_hlevel].append(fmt % args)
50 Writes the given line to the source file.
52 _clines[_clevel].append(fmt % args)
56 Writes the given line to both the header and source files.
61 def _c_wr_stringlist(indent, strlist):
63 Writes the given list of strings to the source file.
64 Each line is prepended by the indent string
67 _c("%s%s", indent, str)
70 class PreCode(object):
72 For pre-code generated by expression generation
73 (for example, the for-loop of a sumof)
74 This has to account for recursiveness of the expression
75 generation, i.e., there may be pre-code for pre-code.
76 Therefore this is implemented as a stack of lists of lines.
78 If redirection is switched on, then all output is collected in
79 self.redirect_code and self.redirect_tempvars instead of
80 being sent to the output via _h und _c.
83 self.nesting_level = 0
86 self.redirect_code = None
87 self.redirect_tempvars = None
89 self.indent_stack = []
93 # start and end of pre-code blocks
95 self.nesting_level += 1
98 self.nesting_level -= 1
99 if self.nesting_level == 0:
100 # lowest pre-code level is finished -> output to source
101 if self.redirect_tempvars is None:
102 _c_wr_stringlist('', self.tempvars)
105 self.redirect_tempvars.extend(self.tempvars)
107 if self.redirect_code == None:
108 _c_wr_stringlist('', self.codelines)
111 self.redirect_code.extend(self.codelines)
115 def output_tempvars(self):
116 if self.redirect_code == None:
117 _c_wr_stringlist('', self.tempvars)
121 def code(self, fmt, *args):
122 self.codelines.append(self.indent_str + fmt % args)
124 def tempvar(self, fmt, *args):
125 self.tempvars.append(' ' + (fmt % args))
127 # get a unique name for a temporary variable
128 def get_tempvarname(self):
129 self.tempvar_num += 1
130 return "xcb_pre_tmp_%d" % self.tempvar_num
134 def push_indent(self, indentstr):
135 self.indent_stack.append(self.indent_str)
136 self.indent_str = indentstr
138 def push_addindent(self, indent_add_str):
139 self.push_indent(self.indent_str + indent_add_str)
142 self.push_addindent(' ')
144 def pop_indent(self):
145 self.indent_str = self.indent_stack.pop()
147 # redirection to lists
148 def redirect_start(self, redirect_code, redirect_tempvars=None):
149 self.redirect_code = redirect_code
150 self.redirect_tempvars = redirect_tempvars
151 if redirect_tempvars is not None:
154 def redirect_end(self):
155 self.redirect_code = None
156 self.redirect_tempvars = None
158 # global PreCode handler
162 # XXX See if this level thing is really necessary.
163 def _h_setlevel(idx):
165 Changes the array that header lines are written to.
166 Supports writing different sections of the header file.
169 while len(_hlines) <= idx:
173 def _c_setlevel(idx):
175 Changes the array that source lines are written to.
176 Supports writing to different sections of the source file.
179 while len(_clines) <= idx:
185 Does C-name conversion on a single string fragment.
186 Uses a regexp with some hard-coded special cases.
188 if str in _cname_special_cases:
189 return _cname_special_cases[str]
191 split = _cname_re.finditer(str)
192 name_parts = [match.group(0) for match in split]
193 return '_'.join(name_parts)
197 Checks for certain C++ reserved words and fixes them.
199 if str in _cplusplus_annoyances:
200 return _cplusplus_annoyances[str]
201 elif str in _c_keywords:
202 return _c_keywords[str]
208 Does C-name conversion on an extension name.
209 Has some additional special cases on top of _n_item.
211 if str in _extension_special_cases:
212 return _n_item(str).lower()
218 Does C-name conversion on a tuple of strings.
219 Different behavior depending on length of tuple, extension/not extension, etc.
220 Basically C-name converts the individual pieces, then joins with underscores.
225 parts = [list[0], _n_item(list[1])]
227 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
229 parts = [list[0]] + [_n_item(i) for i in list[1:]]
230 return '_'.join(parts).lower()
234 Does C-name conversion on a tuple of strings representing a type.
235 Same as _n but adds a "_t" on the end.
240 parts = [list[0], _n_item(list[1]), 't']
242 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
244 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
245 return '_'.join(parts).lower()
250 Exported function that handles module open.
251 Opens the files and writes out the auto-generated comment, header file includes, etc.
255 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
257 # Build the type-name collision avoidance table used by c_enum
258 build_collision_table()
264 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
265 _hc(' * Edit at your peril.')
270 _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
271 _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
275 _h('#ifndef __%s_H', _ns.header.upper())
276 _h('#define __%s_H', _ns.header.upper())
278 _h('#include "xcb.h"')
280 _c('#ifdef HAVE_CONFIG_H')
281 _c('#include "config.h"')
283 _c('#include <stdlib.h>')
284 _c('#include <string.h>')
285 _c('#include <assert.h>')
286 _c('#include <stddef.h> /* for offsetof() */')
287 _c('#include "xcbext.h"')
288 _c('#include "%s.h"', _ns.header)
291 _c('#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)')
294 for (n, h) in self.direct_imports:
295 _hc('#include "%s.h"', h)
298 _h('#ifdef __cplusplus')
304 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
305 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
307 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
310 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
314 Exported function that handles module close.
315 Writes out all the stored content lines, then closes the files.
322 _h('#ifdef __cplusplus')
334 hfile = open('%s.h' % _ns.header, 'w')
342 cfile = open('%s.c' % _ns.header, 'w')
349 def build_collision_table():
353 for v in module.types.values():
355 namecount[name] = (namecount.get(name) or 0) + 1
357 def c_enum(self, name):
359 Exported function that handles enum declarations.
365 if namecount[tname] > 1:
366 tname = _t(name + ('enum',))
370 _h('typedef enum %s {', tname)
372 count = len(self.values)
374 for (enam, eval) in self.values:
376 equals = ' = ' if eval != '' else ''
377 comma = ',' if count > 0 else ''
379 if hasattr(self, "doc") and self.doc and enam in self.doc.fields:
380 doc = '\n/**< %s */\n' % self.doc.fields[enam]
381 _h(' %s%s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma, doc)
385 def _c_type_setup(self, name, postfix):
387 Sets up all the C-related state by adding additional data fields to
388 all Field and Type objects. Here is where we figure out most of our
389 variable and function names.
391 Recurses into child fields and list member types.
393 # Do all the various names in advance
394 self.c_type = _t(name + postfix)
395 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
397 self.c_iterator_type = _t(name + ('iterator',))
398 self.c_next_name = _n(name + ('next',))
399 self.c_end_name = _n(name + ('end',))
401 self.c_request_name = _n(name)
402 self.c_checked_name = _n(name + ('checked',))
403 self.c_unchecked_name = _n(name + ('unchecked',))
404 self.c_reply_name = _n(name + ('reply',))
405 self.c_reply_type = _t(name + ('reply',))
406 self.c_cookie_type = _t(name + ('cookie',))
407 self.c_reply_fds_name = _n(name + ('reply_fds',))
409 self.c_need_aux = False
410 self.c_need_serialize = False
411 self.c_need_sizeof = False
413 self.c_aux_name = _n(name + ('aux',))
414 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
415 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
416 self.c_serialize_name = _n(name + ('serialize',))
417 self.c_unserialize_name = _n(name + ('unserialize',))
418 self.c_unpack_name = _n(name + ('unpack',))
419 self.c_sizeof_name = _n(name + ('sizeof',))
421 # special case: structs where variable size fields are followed by fixed size fields
422 self.c_var_followed_by_fixed_fields = False
425 self.c_need_serialize = True
426 self.c_container = 'struct'
427 for bitcase in self.bitcases:
428 bitcase.c_field_name = _cpp(bitcase.field_name)
429 bitcase_name = bitcase.field_type if bitcase.type.has_name else name
430 _c_type_setup(bitcase.type, bitcase_name, ())
432 elif self.is_container:
434 self.c_container = 'union' if self.is_union else 'struct'
435 prev_varsized_field = None
436 prev_varsized_offset = 0
437 first_field_after_varsized = None
439 for field in self.fields:
440 field.c_field_type = _t(field.field_type)
441 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
442 field.c_field_name = _cpp(field.field_name)
443 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb and field.type.nmemb > 1) else ''
444 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
446 # correct the c_pointer field for variable size non-list types
447 if not field.type.fixed_size() and field.c_pointer == ' ':
448 field.c_pointer = '*'
449 if field.type.is_list and not field.type.member.fixed_size():
450 field.c_pointer = '*'
452 if field.type.is_switch:
453 field.c_pointer = '*'
454 field.c_field_const_type = 'const ' + field.c_field_type
455 self.c_need_aux = True
457 if not field.type.fixed_size() and not field.type.is_case_or_bitcase:
458 self.c_need_sizeof = True
460 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
461 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
462 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
463 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
464 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
466 field.prev_varsized_field = prev_varsized_field
467 field.prev_varsized_offset = prev_varsized_offset
469 if prev_varsized_offset == 0:
470 first_field_after_varsized = field
471 field.first_field_after_varsized = first_field_after_varsized
473 if field.type.fixed_size():
474 prev_varsized_offset += field.type.size
475 # special case: intermixed fixed and variable size fields
476 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
477 if not self.is_union:
478 self.c_need_serialize = True
479 self.c_var_followed_by_fixed_fields = True
481 self.last_varsized_field = field
482 prev_varsized_field = field
483 prev_varsized_offset = 0
485 if self.c_var_followed_by_fixed_fields:
486 if field.type.fixed_size():
487 field.prev_varsized_field = None
489 # recurse into this field this has to be done here, i.e.,
490 # after the field has been set up. Otherwise the function
491 # _c_helper_fieldaccess_expr will produce garbage or crash
492 _c_type_setup(field.type, field.field_type, ())
493 if field.type.is_list:
494 _c_type_setup(field.type.member, field.field_type, ())
495 if (field.type.nmemb is None):
496 self.c_need_sizeof = True
498 if self.c_need_serialize:
499 # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
500 self.c_need_sizeof = True
502 # as switch does never appear at toplevel,
503 # continue here with type construction
505 if self.c_type not in finished_switch:
506 finished_switch.append(self.c_type)
507 # special: switch C structs get pointer fields for variable-sized members
509 for bitcase in self.bitcases:
510 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
511 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
512 # no list with switch as element, so no call to
513 # _c_iterator(field.type, field_name) necessary
515 if not self.is_case_or_bitcase:
516 if self.c_need_serialize:
517 if self.c_serialize_name not in finished_serializers:
518 finished_serializers.append(self.c_serialize_name)
519 _c_serialize('serialize', self)
521 # _unpack() and _unserialize() are only needed for special cases:
523 # special cases -> unserialize
524 if self.is_switch or self.c_var_followed_by_fixed_fields:
525 _c_serialize('unserialize', self)
527 if self.c_need_sizeof:
528 if self.c_sizeof_name not in finished_sizeof:
529 if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
530 finished_sizeof.append(self.c_sizeof_name)
531 _c_serialize('sizeof', self)
534 # Functions for querying field properties
535 def _c_field_needs_list_accessor(field):
536 return field.type.is_list and not field.type.fixed_size()
538 def _c_field_needs_field_accessor(field):
539 if field.type.is_list:
542 return (field.prev_varsized_field is not None or
543 not field.type.fixed_size())
545 def _c_field_needs_accessor(field):
546 return (_c_field_needs_list_accessor(field) or
547 _c_field_needs_field_accessor(field))
549 def _c_field_is_member_of_case_or_bitcase(field):
550 return field.parent and field.parent.is_case_or_bitcase
552 def _c_helper_fieldaccess_expr(prefix, field=None):
554 turn prefix, which is a list of tuples (name, separator, Type obj) into a string
555 representing a valid field-access-expression in C (based on the context)
556 if field is not None, append access to the field as well.
558 "separator" is one of the C-operators "." or "->".
560 A field access expression can consist of the following components:
561 * struct/union member access from a value with the "."-operator
562 * struct/union member access from a pointer with "->"-operator
563 * function-call of an accessor function:
564 This is used when a xcb-field is not contained in a struct.
565 This can, e.g., happen for fields after var-sized fields, etc.
569 for name, sep, obj in prefix:
570 prefix_str += last_sep + name
574 # add separator for access to a yet unknown field
575 prefix_str += last_sep
577 if _c_field_needs_accessor(field):
578 if _c_field_is_member_of_case_or_bitcase(field):
579 # case members are available in the deserialized struct,
580 # so there is no need to use the accessor function
581 # (also, their accessor function needs a different arglist
582 # so this would require special treatment here)
583 # Therefore: Access as struct member
584 prefix_str += last_sep + _cpp(field.field_name)
586 # Access with the accessor function
587 prefix_str = field.c_accessor_name + "(" + prefix_str + ")"
589 # Access as struct member
590 prefix_str += last_sep + _cpp(field.field_name)
595 def _c_helper_field_mapping(complex_type, prefix, flat=False):
597 generate absolute names, based on prefix, for all fields starting from complex_type
598 if flat == True, nested complex types are not taken into account
601 if complex_type.is_switch:
602 for b in complex_type.bitcases:
604 switch_name, switch_sep, switch_type = prefix[-1]
605 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
607 bitcase_prefix = prefix
609 if (True==flat and not b.type.has_name) or False==flat:
610 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
612 for f in complex_type.fields:
613 fname = _c_helper_fieldaccess_expr(prefix, f)
614 if f.field_name in all_fields:
615 raise Exception("field name %s has been registered before" % f.field_name)
617 all_fields[f.field_name] = (fname, f)
618 if f.type.is_container and flat==False:
619 if f.type.is_case_or_bitcase and not f.type.has_name:
621 elif f.type.is_switch and len(f.type.parents)>1:
622 # nested switch gets another separator
623 new_prefix = prefix+[(f.c_field_name, '.', f.type)]
625 new_prefix = prefix+[(f.c_field_name, '->', f.type)]
626 all_fields.update(_c_helper_field_mapping(f.type, new_prefix, flat))
631 def _c_helper_resolve_field_names (prefix):
633 get field names for all objects in the prefix array
637 # look for fields in the remaining containers
638 for idx, p in enumerate(prefix):
641 # sep can be preset in prefix, if not, make a sensible guess
642 sep = '.' if (obj.is_switch or obj.is_case_or_bitcase) else '->'
643 # exception: 'toplevel' object (switch as well!) always have sep '->'
644 sep = '->' if idx<1 else sep
645 if not obj.is_case_or_bitcase or (obj.is_case_or_bitcase and obj.has_name):
646 tmp_prefix.append((name, sep, obj))
647 all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
650 # _c_helper_resolve_field_names
652 def get_expr_fields(self):
654 get the Fields referenced by switch or list expression
656 def get_expr_field_names(expr):
658 if expr.lenfield_name is not None:
659 return [expr.lenfield_name]
661 # constant value expr
665 return get_expr_field_names(expr.rhs)
666 elif expr.op == 'popcount':
667 return get_expr_field_names(expr.rhs)
668 elif expr.op == 'sumof':
669 # sumof expr references another list,
670 # we need that list's length field here
672 for f in expr.lenfield_parent.fields:
673 if f.field_name == expr.lenfield_name:
677 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
678 # referenced list + its length field
679 return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
680 elif expr.op == 'enumref':
683 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
684 # get_expr_field_names()
686 # resolve the field names with the parent structure(s)
687 unresolved_fields_names = get_expr_field_names(self.expr)
689 # construct prefix from self
690 prefix = [('', '', p) for p in self.parents]
691 if self.is_container:
692 prefix.append(('', '', self))
694 all_fields = _c_helper_resolve_field_names (prefix)
695 resolved_fields_names = list(filter(lambda x: x in all_fields.keys(), unresolved_fields_names))
696 if len(unresolved_fields_names) != len(resolved_fields_names):
697 raise Exception("could not resolve all fields for %s" % self.name)
699 resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
700 return resolved_fields
703 def resolve_expr_fields(complex_obj):
705 find expr fields appearing in complex_obj and descendents that cannot be resolved within complex_obj
706 these are normally fields that need to be given as function parameters
712 for field in complex_obj.fields:
713 all_fields.append(field)
714 if field.type.is_switch or field.type.is_list:
715 expr_fields += get_expr_fields(field.type)
716 if field.type.is_container:
717 expr_fields += resolve_expr_fields(field.type)
719 # try to resolve expr fields
720 for e in expr_fields:
721 if e not in all_fields and e not in unresolved:
724 # resolve_expr_fields()
726 def resolve_expr_fields_list(self, parents):
728 Find expr fields appearing in a list and descendents
729 that cannot be resolved within the parents of the list.
730 These are normally fields that need to be given as function parameters
731 for length and iterator functions.
734 expr_fields = get_expr_fields(self)
737 for complex_obj in parents:
738 for field in complex_obj.fields:
740 all_fields.append(field)
742 # try to resolve expr fields
743 for e in expr_fields:
744 if e not in all_fields and e not in unresolved:
748 # resolve_expr_fields_list()
751 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
753 functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
754 E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch
755 expression. This function tries to resolve all fields within a structure, and returns the
756 unresolved fields as the list of external parameters.
758 def add_param(params, param):
759 if param not in params:
762 # collect all fields into param_fields
766 for field in self.fields:
768 # the field should appear as a parameter in the function call
769 param_fields.append(field)
770 if field.wire and not field.auto:
771 if field.type.fixed_size() and not self.is_switch:
772 # field in the xcb_out structure
773 wire_fields.append(field)
774 # fields like 'pad0' are skipped!
776 # in case of switch, parameters always contain any fields referenced in the switch expr
777 # we do not need any variable size fields here, as the switch data type contains both
778 # fixed and variable size fields
780 param_fields = get_expr_fields(self)
782 # _serialize()/_unserialize()/_unpack() function parameters
783 # note: don't use set() for params, it is unsorted
786 # 1. the parameter for the void * buffer
787 if 'serialize' == context:
788 params.append(('void', '**', buffer_var))
789 elif context in ('unserialize', 'unpack', 'sizeof'):
790 params.append(('const void', '*', buffer_var))
792 # 2. any expr fields that cannot be resolved within self and descendants
793 unresolved_fields = resolve_expr_fields(self)
794 for f in unresolved_fields:
795 add_param(params, (f.c_field_type, '', f.c_field_name))
797 # 3. param_fields contain the fields necessary to evaluate the switch expr or any other fields
798 # that do not appear in the data type struct
799 for p in param_fields:
801 typespec = p.c_field_const_type
802 pointerspec = p.c_pointer
803 add_param(params, (typespec, pointerspec, p.c_field_name))
805 if p.visible and not p.wire and not p.auto:
806 typespec = p.c_field_type
808 add_param(params, (typespec, pointerspec, p.c_field_name))
811 if 'serialize' == context:
812 add_param(params, ('const %s' % self.c_type, '*', aux_var))
813 elif 'unserialize' == context:
814 add_param(params, ('%s' % self.c_type, '**', aux_var))
815 elif 'unpack' == context:
816 add_param(params, ('%s' % self.c_type, '*', aux_var))
818 # 5. switch contains all variable size fields as struct members
819 # for other data types though, these have to be supplied separately
820 # this is important for the special case of intermixed fixed and
821 # variable size fields
822 if not self.is_switch and 'serialize' == context:
823 for p in param_fields:
824 if not p.type.fixed_size():
825 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
827 return (param_fields, wire_fields, params)
828 # get_serialize_params()
830 def _c_serialize_helper_insert_padding(context, code_lines, space, postpone, is_case_or_bitcase):
831 code_lines.append('%s /* insert padding */' % space)
832 if is_case_or_bitcase:
834 '%s xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);'
838 '%s xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
839 # code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
840 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
843 code_lines.append('%s if (0 != xcb_pad) {' % space)
845 if 'serialize' == context:
846 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
847 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
848 code_lines.append('%s xcb_parts_idx++;' % space)
849 elif context in ('unserialize', 'unpack', 'sizeof'):
850 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
852 code_lines.append('%s xcb_pad = 0;' % space)
853 code_lines.append('%s }' % space)
855 code_lines.append('%s xcb_block_len = 0;' % space)
856 if is_case_or_bitcase:
857 code_lines.append('%s xcb_padding_offset = 0;' % space)
859 # keep tracking of xcb_parts entries for serialize
861 # _c_serialize_helper_insert_padding()
863 def _c_serialize_helper_switch(context, self, complex_name,
864 code_lines, temp_vars,
867 switch_expr = _c_accessor_get_expr(self.expr, None)
869 for b in self.bitcases:
870 len_expr = len(b.type.expr)
872 compare_operator = '&'
874 compare_operator = '=='
876 compare_operator = '&'
878 for n, expr in enumerate(b.type.expr):
879 bitcase_expr = _c_accessor_get_expr(expr, None)
880 # only one <enumref> in the <bitcase>
883 ' if(%s %s %s) {' % (switch_expr, compare_operator, bitcase_expr))
884 # multiple <enumref> in the <bitcase>
887 ' if((%s %s %s) ||' % (switch_expr, compare_operator, bitcase_expr))
888 elif len_expr == (n + 1): # last
890 ' (%s %s %s)) {' % (switch_expr, compare_operator, bitcase_expr))
891 else: # between first and last
893 ' (%s %s %s) ||' % (switch_expr, compare_operator, bitcase_expr))
897 b_prefix = prefix + [(b.c_field_name, '.', b.type)]
899 count += _c_serialize_helper_fields(context, b.type,
900 code_lines, temp_vars,
903 is_case_or_bitcase = True)
904 code_lines.append(' }')
906 # if 'serialize' == context:
907 # count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
908 # elif context in ('unserialize', 'unpack', 'sizeof'):
910 # code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
911 # code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
914 # _c_serialize_helper_switch
916 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
918 handle switch by calling _serialize() or _unpack(), depending on context
920 # switch is handled by this function as a special case
921 param_fields, wire_fields, params = get_serialize_params(context, self)
922 field_mapping = _c_helper_field_mapping(self, prefix)
923 prefix_str = _c_helper_fieldaccess_expr(prefix)
925 # find the parameters that need to be passed to _serialize()/_unpack():
926 # all switch expr fields must be given as parameters
927 args = get_expr_fields(field.type)
928 # length fields for variable size types in switch, normally only some of need
929 # need to be passed as parameters
930 switch_len_fields = resolve_expr_fields(field.type)
932 # a switch field at this point _must_ be a bitcase field
933 # we require that bitcases are "self-contiguous"
934 bitcase_unresolved = resolve_expr_fields(self)
935 if len(bitcase_unresolved) != 0:
936 raise Exception('unresolved fields within bitcase is not supported at this point')
938 # get the C names for the parameters
940 for a in switch_len_fields:
941 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
943 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
945 # call _serialize()/_unpack() to determine the actual size
946 if 'serialize' == context:
947 length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
948 c_field_names, prefix_str, field.c_field_name)
949 elif context in ('unserialize', 'unpack'):
950 length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
951 c_field_names, prefix_str, field.c_field_name)
952 elif 'sizeof' == context:
953 # remove trailing ", " from c_field_names because it will be used at end of arglist
954 my_c_field_names = c_field_names[:-2]
955 length = "%s(xcb_tmp, %s)" % (field.type.c_sizeof_name, my_c_field_names)
958 # _c_serialize_helper_switch_field()
960 def _c_get_additional_type_params(type):
962 compute list of additional params for functions created for the given type
967 param_fields, wire_fields, params = get_serialize_params('sizeof', type)
970 def _c_serialize_helper_list_field(context, self, field,
971 code_lines, temp_vars,
974 helper function to cope with lists of variable length
976 expr = field.type.expr
977 prefix_str = _c_helper_fieldaccess_expr(prefix)
978 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
979 param_names = [p[2] for p in params]
981 expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
982 resolved = list(filter(lambda x: x in param_names, expr_fields_names))
983 unresolved = list(filter(lambda x: x not in param_names, expr_fields_names))
987 field_mapping[r] = (r, None)
989 if len(unresolved)>0:
991 if len(tmp_prefix)==0:
992 raise Exception("found an empty prefix while resolving expr field names for list %s",
995 field_mapping.update(_c_helper_resolve_field_names(prefix))
996 resolved += list(filter(lambda x: x in field_mapping, unresolved))
997 unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
998 if len(unresolved)>0:
999 raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
1001 list_length = _c_accessor_get_expr(expr, field_mapping)
1003 # default: list with fixed size elements
1004 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
1006 # list with variable-sized elements
1007 if not field.type.member.fixed_size():
1008 # compute string for argumentlist for member-type functions
1009 member_params = _c_get_additional_type_params(field.type.member)
1010 member_arg_names = [p[2] for p in member_params]
1012 for member_arg_name in member_arg_names:
1013 member_arg_str += ', ' + field_mapping[member_arg_name][0]
1017 if context in ('unserialize', 'sizeof', 'unpack'):
1018 int_i = ' unsigned int i;'
1019 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
1020 if int_i not in temp_vars:
1021 temp_vars.append(int_i)
1022 if xcb_tmp_len not in temp_vars:
1023 temp_vars.append(xcb_tmp_len)
1024 # loop over all list elements and call sizeof repeatedly
1025 # this should be a bit faster than using the iterators
1026 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
1027 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp%s);" %
1028 (space, field.type.c_sizeof_name, member_arg_str))
1029 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
1030 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
1031 code_lines.append("%s }" % space)
1033 elif 'serialize' == context:
1034 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
1035 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
1036 code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length))
1037 code_lines.append('%s xcb_block_len = %s(xcb_tmp%s);' % (space, field.type.c_sizeof_name, member_arg_str))
1038 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
1039 code_lines.append('%s }' % space)
1040 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
1043 # _c_serialize_helper_list_field()
1045 def _c_serialize_helper_fields_fixed_size(context, self, field,
1046 code_lines, temp_vars,
1048 # keep the C code a bit more readable by giving the field name
1049 if not self.is_case_or_bitcase:
1050 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
1052 scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
1053 typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
1054 code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
1056 abs_field_name = _c_helper_fieldaccess_expr(prefix, field)
1057 # default for simple cases: call sizeof()
1058 length = "sizeof(%s)" % field.c_field_type
1060 if context in ('unserialize', 'unpack', 'sizeof'):
1061 # default: simple cast
1062 value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
1064 # padding - we could probably just ignore it
1065 if field.type.is_pad and field.type.nmemb > 1:
1067 for i in range(field.type.nmemb):
1068 code_lines.append('%s %s[%d] = *(%s *)xcb_tmp;' %
1069 (space, abs_field_name, i, field.c_field_type))
1070 # total padding = sizeof(pad0) * nmemb
1071 length += " * %d" % field.type.nmemb
1073 elif field.type.is_list:
1074 # list with fixed number of elements
1075 # length of array = sizeof(arrayElementType) * nmemb
1076 length += " * %d" % field.type.nmemb
1077 # use memcpy because C cannot assign whole arrays with operator=
1078 value = ' memcpy(%s, xcb_tmp, %s);' % (abs_field_name, length)
1081 elif 'serialize' == context:
1082 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
1084 if field.type.is_expr:
1085 # need to register a temporary variable for the expression in case we know its type
1086 if field.type.c_type is None:
1087 raise Exception("type for field '%s' (expression '%s') unkown" %
1088 (field.field_name, _c_accessor_get_expr(field.type.expr)))
1090 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
1091 _c_accessor_get_expr(field.type.expr, prefix)))
1092 value += "&xcb_expr_%s;" % _cpp(field.field_name)
1094 elif field.type.is_pad:
1095 if field.type.nmemb == 1:
1096 value += "&xcb_pad;"
1098 # we could also set it to 0, see definition of xcb_send_request()
1099 value = ' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
1100 length += "*%d" % field.type.nmemb
1103 # non-list type with fixed size
1104 if field.type.nmemb == 1:
1105 value += "&%s;" % (abs_field_name)
1107 # list with nmemb (fixed size) elements
1109 value += '%s;' % (abs_field_name)
1110 length = '%d' % field.type.nmemb
1112 return (value, length)
1113 # _c_serialize_helper_fields_fixed_size()
1115 def _c_serialize_helper_fields_variable_size(context, self, field,
1116 code_lines, temp_vars,
1118 prefix_str = _c_helper_fieldaccess_expr(prefix)
1120 if context in ('unserialize', 'unpack', 'sizeof'):
1122 var_field_name = 'xcb_tmp'
1124 # special case: intermixed fixed and variable size fields
1125 if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
1126 value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
1127 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
1128 # special case: switch
1129 if 'unpack' == context:
1130 value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
1132 elif 'serialize' == context:
1133 # variable size fields appear as parameters to _serialize() if the
1134 # 'toplevel' container is not a switch
1135 prefix_string = prefix_str if prefix[0][2].is_switch else ''
1136 var_field_name = "%s%s" % (prefix_string, field.c_field_name)
1137 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
1141 code_lines.append('%s /* %s */' % (space, field.c_field_name))
1143 if field.type.is_list:
1145 # in any context, list is already a pointer, so the default assignment is ok
1146 code_lines.append("%s%s" % (space, value))
1148 length = _c_serialize_helper_list_field(context, self, field,
1149 code_lines, temp_vars,
1152 elif field.type.is_switch:
1154 if context == 'serialize':
1155 # the _serialize() function allocates the correct amount memory if given a NULL pointer
1156 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
1157 length = _c_serialize_helper_switch_field(context, self, field,
1158 'xcb_parts[xcb_parts_idx].iov_base',
1162 # in all remaining special cases - call _sizeof()
1163 length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
1165 return (value, length)
1166 # _c_serialize_helper_fields_variable_size
1168 def _c_serialize_helper_fields(context, self,
1169 code_lines, temp_vars,
1170 space, prefix, is_case_or_bitcase):
1172 need_padding = False
1173 prev_field_was_variable = False
1175 _c_pre.push_indent(space + ' ')
1177 for field in self.fields:
1178 if not field.visible:
1179 if not ((field.wire and not field.auto) or 'unserialize' == context):
1182 # switch/bitcase: fixed size fields must be considered explicitly
1183 if field.type.fixed_size():
1184 if self.is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
1185 if prev_field_was_variable and need_padding:
1187 # count += _c_serialize_helper_insert_padding(context, code_lines, space,
1188 # self.c_var_followed_by_fixed_fields)
1189 prev_field_was_variable = False
1191 # prefix for fixed size fields
1192 fixed_prefix = prefix
1194 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
1195 code_lines, temp_vars,
1196 space, fixed_prefix)
1200 # fields with variable size
1202 if field.type.is_pad:
1203 # Variable length pad is <pad align= />
1204 code_lines.append('%s xcb_align_to = %d;' % (space, field.type.align))
1205 count += _c_serialize_helper_insert_padding(context, code_lines, space,
1206 self.c_var_followed_by_fixed_fields,
1210 # switch/bitcase: always calculate padding before and after variable sized fields
1211 if need_padding or is_case_or_bitcase:
1212 count += _c_serialize_helper_insert_padding(context, code_lines, space,
1213 self.c_var_followed_by_fixed_fields,
1216 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
1217 code_lines, temp_vars,
1219 prev_field_was_variable = True
1221 # save (un)serialization C code
1223 code_lines.append('%s%s' % (space, value))
1225 if field.type.fixed_size():
1226 if is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
1227 # keep track of (un)serialized object's size
1228 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1229 if context in ('unserialize', 'unpack', 'sizeof'):
1230 code_lines.append('%s xcb_tmp += %s;' % (space, length))
1232 # variable size objects or bitcase:
1233 # value & length might have been inserted earlier for special cases
1235 # special case: intermixed fixed and variable size fields
1236 if (not field.type.fixed_size() and
1237 self.c_var_followed_by_fixed_fields and 'unserialize' == context):
1238 temp_vars.append(' int %s_len;' % field.c_field_name)
1239 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
1240 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
1241 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
1243 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1244 # increase pointer into the byte stream accordingly
1245 if context in ('unserialize', 'sizeof', 'unpack'):
1246 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1248 if 'serialize' == context:
1250 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
1251 code_lines.append('%s xcb_parts_idx++;' % space)
1255 '%s xcb_align_to = ALIGNOF(%s);'
1258 if field.c_field_type == 'void' or field.type.is_switch
1259 else field.c_field_type))
1262 if self.c_var_followed_by_fixed_fields:
1263 need_padding = False
1268 # _c_serialize_helper_fields()
1270 def _c_serialize_helper(context, complex_type,
1271 code_lines, temp_vars,
1272 space='', prefix=[]):
1273 # count tracks the number of fields to serialize
1276 if hasattr(complex_type, 'type'):
1277 self = complex_type.type
1278 complex_name = complex_type.name
1281 if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
1282 complex_name = 'xcb_out'
1284 complex_name = '_aux'
1286 # special case: switch is serialized by evaluating each bitcase separately
1288 count += _c_serialize_helper_switch(context, self, complex_name,
1289 code_lines, temp_vars,
1292 # all other data types can be evaluated one field a time
1294 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1295 if context in ('unserialize', 'unpack', 'sizeof') and not self.c_var_followed_by_fixed_fields:
1296 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1297 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1298 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
1299 code_lines.append('%s xcb_block_len = 0;' % space)
1301 count += _c_serialize_helper_fields(context, self,
1302 code_lines, temp_vars,
1303 space, prefix, False)
1305 count += _c_serialize_helper_insert_padding(context, code_lines, space, False, self.is_switch)
1308 # _c_serialize_helper()
1310 def _c_serialize(context, self):
1312 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1313 for the ComplexType variable self
1319 # _serialize() returns the buffer size
1322 if self.is_switch and 'unserialize' == context:
1325 cases = { 'serialize' : self.c_serialize_name,
1326 'unserialize' : self.c_unserialize_name,
1327 'unpack' : self.c_unpack_name,
1328 'sizeof' : self.c_sizeof_name }
1329 func_name = cases[context]
1331 param_fields, wire_fields, params = get_serialize_params(context, self)
1332 variable_size_fields = 0
1333 # maximum space required for type definition of function arguments
1336 # determine N(variable_fields)
1337 for field in param_fields:
1338 # if self.is_switch, treat all fields as if they are variable sized
1339 if not field.type.fixed_size() or self.is_switch:
1340 variable_size_fields += 1
1341 # determine maxtypelen
1343 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1346 indent = ' '*(len(func_name)+2)
1349 typespec, pointerspec, field_name = p
1350 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1351 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1352 # insert function name
1353 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1354 param_str = list(map(lambda x: "%s," % x, param_str))
1355 for s in param_str[:-1]:
1357 _h("%s);" % param_str[-1].rstrip(','))
1358 _c("%s)" % param_str[-1].rstrip(','))
1365 _c_pre.redirect_start(code_lines, temp_vars)
1367 if 'serialize' == context:
1368 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1369 _c(' %s *xcb_out = *_buffer;', self.c_type)
1370 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1371 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1372 _c(' unsigned int xcb_align_to = 0;')
1374 _c(' char *xcb_out = *_buffer;')
1375 _c(' unsigned int xcb_buffer_len = 0;')
1376 _c(' unsigned int xcb_align_to = 0;')
1378 _c(' unsigned int xcb_padding_offset = ((size_t)xcb_out) & 7;')
1379 prefix = [('_aux', '->', self)]
1382 elif context in ('unserialize', 'unpack'):
1383 _c(' char *xcb_tmp = (char *)_buffer;')
1384 if not self.is_switch:
1385 if not self.c_var_followed_by_fixed_fields:
1386 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1387 prefix = [('_aux', '->', self)]
1389 _c(' %s xcb_out;', self.c_type)
1390 prefix = [('xcb_out', '.', self)]
1392 aux_var = '_aux' # default for unpack: single pointer
1393 # note: unserialize not generated for switch
1394 if 'unserialize' == context:
1395 aux_var = '(*_aux)' # unserialize: double pointer (!)
1396 prefix = [(aux_var, '->', self)]
1398 _c(' unsigned int xcb_buffer_len = 0;')
1399 _c(' unsigned int xcb_block_len = 0;')
1400 _c(' unsigned int xcb_pad = 0;')
1401 _c(' unsigned int xcb_align_to = 0;')
1403 _c(' unsigned int xcb_padding_offset = ((size_t)_buffer) & 7;')
1405 elif 'sizeof' == context:
1406 param_names = [p[2] for p in params]
1408 # switch: call _unpack()
1409 _c(' %s _aux;', self.c_type)
1410 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1412 _c_pre.redirect_end()
1414 elif self.c_var_followed_by_fixed_fields:
1415 # special case: call _unserialize()
1416 _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1418 _c_pre.redirect_end()
1421 _c(' char *xcb_tmp = (char *)_buffer;')
1422 prefix = [('_aux', '->', self)]
1424 _c(' unsigned int xcb_padding_offset = 0;')
1426 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1427 # update variable size fields (only important for context=='serialize'
1428 variable_size_fields = count
1429 if 'serialize' == context:
1430 temp_vars.append(' unsigned int xcb_pad = 0;')
1431 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1432 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1433 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1434 temp_vars.append(' unsigned int xcb_block_len = 0;')
1435 temp_vars.append(' unsigned int i;')
1436 temp_vars.append(' char *xcb_tmp;')
1437 elif 'sizeof' == context:
1438 # neither switch nor intermixed fixed and variable size fields:
1439 # evaluate parameters directly
1440 if not (self.is_switch or self.c_var_followed_by_fixed_fields):
1442 # look if we have to declare an '_aux' variable at all
1443 if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
1444 if not self.c_var_followed_by_fixed_fields:
1445 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1447 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1449 _c(' unsigned int xcb_buffer_len = 0;')
1450 _c(' unsigned int xcb_block_len = 0;')
1451 _c(' unsigned int xcb_pad = 0;')
1452 _c(' unsigned int xcb_align_to = 0;')
1454 _c_pre.redirect_end()
1460 for l in code_lines:
1463 # variable sized fields have been collected, now
1464 # allocate memory and copy everything into a continuous memory area
1465 # note: this is not necessary in case of unpack
1466 if context in ('serialize', 'unserialize'):
1467 # unserialize: check for sizeof-only invocation
1468 if 'unserialize' == context:
1470 _c(' if (NULL == _aux)')
1471 _c(' return xcb_buffer_len;')
1474 _c(' if (NULL == %s) {', aux_ptr)
1475 _c(' /* allocate memory */')
1476 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1477 if 'serialize' == context:
1478 _c(' *_buffer = xcb_out;')
1482 # serialize: handle variable size fields in a loop
1483 if 'serialize' == context:
1484 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1485 if len(wire_fields)>0:
1486 _c(' *xcb_out = *_aux;')
1487 # copy variable size fields into the buffer
1488 if variable_size_fields > 0:
1490 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1491 _c(' xcb_tmp = (char*)++xcb_out;')
1492 _c(' xcb_tmp += xcb_out_pad;')
1494 _c(' xcb_tmp = xcb_out;')
1496 # variable sized fields
1497 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1498 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1499 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1500 _c(' if (0 != xcb_parts[i].iov_len)')
1501 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1504 # unserialize: assign variable size fields individually
1505 if 'unserialize' == context:
1506 _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1507 param_fields.reverse()
1508 for field in param_fields:
1509 if not field.type.fixed_size():
1510 _c(' xcb_tmp -= %s_len;', field.c_field_name)
1511 _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1512 _c(' *%s = xcb_out;', aux_ptr)
1515 _c(' return xcb_buffer_len;')
1519 def _c_iterator_get_end(field, accum):
1521 Figures out what C code is needed to find the end of a variable-length structure field.
1522 For nested structures, recurses into its last variable-sized field.
1523 For lists, calls the end function
1525 if field.type.is_container:
1526 accum = field.c_accessor_name + '(' + accum + ')'
1527 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1528 if field.type.is_list:
1529 # XXX we can always use the first way
1530 if field.type.member.is_simple:
1531 return field.c_end_name + '(' + accum + ')'
1533 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1535 def _c_iterator(self, name):
1537 Declares the iterator structure and next/end functions for a given type.
1542 _h(' * @brief %s', self.c_iterator_type)
1544 _h('typedef struct %s {', self.c_iterator_type)
1545 _h(' %s *data; /**< */', self.c_type)
1546 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1547 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1548 # add additional params of the type "self" as fields to the iterator struct
1549 # so that they can be passed to the sizeof-function by the iterator's next-function
1550 params = _c_get_additional_type_params(self)
1551 for param in params:
1552 _h(' %s%s %s; /**< */',
1554 ' ' * (len(self.c_type) + 1 - len(param[0])),
1556 _h('} %s;', self.c_iterator_type)
1562 _h(' * Get the next element of the iterator')
1563 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1565 _h(' * Get the next element in the iterator. The member rem is')
1566 _h(' * decreased by one. The member data points to the next')
1567 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1571 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1572 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1575 if not self.fixed_size():
1576 _c(' %s *R = i->data;', self.c_type)
1579 # FIXME - how to determine the size of a variable size union??
1580 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1582 if self.c_need_sizeof:
1583 # compute the string of additional arguments for the sizeof-function
1584 additional_args = ''
1585 for param in params:
1586 additional_args += ', i->' + param[2]
1588 _c(' xcb_generic_iterator_t child;')
1589 _c(' child.data = (%s *)(((char *)R) + %s(R%s));',
1590 self.c_type, self.c_sizeof_name, additional_args)
1591 _c(' i->index = (char *) child.data - (char *) i->data;')
1593 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1594 _c(' i->index = child.index;')
1596 _c(' i->data = (%s *) child.data;', self.c_type)
1601 _c(' i->index += sizeof(%s);', self.c_type)
1607 _h(' * Return the iterator pointing to the last element')
1608 _h(' * @param i An %s', self.c_iterator_type)
1609 _h(' * @return The iterator pointing to the last element')
1611 _h(' * Set the current element in the iterator to the last element.')
1612 _h(' * The member rem is set to 0. The member data points to the')
1613 _h(' * last element.')
1616 _hc('xcb_generic_iterator_t')
1617 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1618 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1620 _c(' xcb_generic_iterator_t ret;')
1622 if self.fixed_size():
1623 _c(' ret.data = i.data + i.rem;')
1624 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1627 _c(' while(i.rem > 0)')
1628 _c(' %s(&i);', self.c_next_name)
1629 _c(' ret.data = i.data;')
1630 _c(' ret.rem = i.rem;')
1631 _c(' ret.index = i.index;')
1636 def _c_accessor_get_length(expr, field_mapping=None):
1638 Figures out what C code is needed to get a length field.
1639 The field_mapping parameter can be used to change the absolute name of a length field.
1640 For fields that follow a variable-length field, use the accessor.
1641 Otherwise, just reference the structure field directly.
1644 lenfield_name = expr.lenfield_name
1645 if lenfield_name is not None:
1646 if field_mapping is not None:
1647 lenfield_name = field_mapping[lenfield_name][0]
1649 if expr.lenfield_name is not None:
1650 return lenfield_name
1652 return str(expr.nmemb)
1654 def _c_accessor_get_expr(expr, field_mapping):
1656 Figures out what C code is needed to get the length of a list field.
1657 The field_mapping parameter can be used to change the absolute name of a length field.
1658 Recurses for math operations.
1659 Returns bitcount for value-mask fields.
1660 Otherwise, uses the value of the length field.
1662 lenexp = _c_accessor_get_length(expr, field_mapping)
1665 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1666 elif expr.op == 'popcount':
1667 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1668 elif expr.op == 'enumref':
1669 enum_name = expr.lenfield_type.name
1670 constant_name = expr.lenfield_name
1671 c_name = _n(enum_name + (constant_name,)).upper()
1673 elif expr.op == 'sumof':
1674 # locate the referenced list object
1675 list_obj = expr.lenfield_type
1677 for f in expr.lenfield_parent.fields:
1678 if f.field_name == expr.lenfield_name:
1683 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1684 list_name = field_mapping[field.c_field_name][0]
1685 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1686 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1687 # create explicit code for computing the sum.
1688 # This works for all C-types which can be added to int64_t with +=
1690 lengthvar = _c_pre.get_tempvarname()
1691 loopvar = _c_pre.get_tempvarname()
1692 sumvar = _c_pre.get_tempvarname()
1693 listvar = _c_pre.get_tempvarname()
1694 _c_pre.tempvar("int %s; /* sumof length */", lengthvar)
1695 _c_pre.tempvar("int %s; /* sumof loop counter */", loopvar)
1696 _c_pre.tempvar("int64_t %s; /* sumof sum */", sumvar)
1697 _c_pre.tempvar("const %s* %s; /* sumof list ptr */", field.c_field_type, listvar)
1698 _c_pre.code("/* sumof start */")
1699 _c_pre.code("%s = %s;", lengthvar, c_length_func)
1700 _c_pre.code("%s = 0;", sumvar)
1701 _c_pre.code("%s = %s;", listvar, list_name)
1702 _c_pre.code("for (%s = 0; %s < %s; %s++) {", loopvar, loopvar, lengthvar, loopvar)
1705 # define and set xcb_listelement, so that it can be used by
1706 # listelement-ref expressions.
1707 if expr.contains_listelement_ref:
1709 "const %s *xcb_listelement = %s;",
1710 field.c_field_type, listvar)
1713 if expr.rhs is None:
1714 _c_pre.code("%s += *%s;", sumvar, listvar)
1716 # sumof has a nested expression which has to be evaluated in
1717 # the context of this list element
1719 # field mapping for the subexpression needs to include
1720 # the fields of the list-member type
1721 scoped_field_mapping = field_mapping.copy()
1722 if not field.type.member.is_simple:
1723 scoped_field_mapping.update(
1724 _c_helper_field_mapping(
1726 [(listvar, '->', field.type.member)]))
1728 # cause pre-code of the subexpression be added right here
1730 # compute the subexpression
1731 rhs_expr_str = _c_accessor_get_expr(expr.rhs, scoped_field_mapping)
1732 # resume with our code
1734 # output the summation expression
1735 _c_pre.code("%s += %s;", sumvar, rhs_expr_str)
1737 _c_pre.code("%s++;", listvar)
1740 _c_pre.code("/* sumof end. Result is in %s */", sumvar)
1743 elif expr.op == 'listelement-ref':
1744 return '(*xcb_listelement)'
1745 elif expr.op != None:
1746 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1747 ' ' + expr.op + ' ' +
1748 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1750 return 'xcb_popcount(' + lenexp + ')'
1754 def type_pad_type(type):
1759 def _c_accessors_field(self, field):
1761 Declares the accessor functions for a non-list field that follows a variable-length field.
1763 c_type = self.c_type
1765 # special case: switch
1766 switch_obj = self if self.is_switch else None
1767 if self.is_case_or_bitcase:
1768 switch_obj = self.parents[-1]
1769 if switch_obj is not None:
1770 c_type = switch_obj.c_type
1772 if field.type.is_simple:
1774 _hc('%s', field.c_field_type)
1775 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1776 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1778 if field.prev_varsized_field is None:
1779 _c(' return (%s *) (R + 1);', field.c_field_type)
1781 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1782 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1783 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1787 if field.type.is_switch and switch_obj is None:
1788 return_type = 'void *'
1790 return_type = '%s *' % field.c_field_type
1793 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1794 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1796 if field.prev_varsized_field is None:
1797 _c(' return (%s) (R + 1);', return_type)
1798 # note: the special case 'variable fields followed by fixed size fields'
1799 # is not of any consequence here, since the ordering gets
1800 # 'corrected' in the reply function
1802 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1803 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1804 return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1808 def _c_accessors_list(self, field):
1810 Declares the accessor functions for a list field.
1811 Declares a direct-accessor function only if the list members are fixed size.
1812 Declares length and get-iterator functions always.
1815 def get_align_pad(field):
1816 prev = field.prev_varsized_field
1817 prev_prev = field.prev_varsized_field.prev_varsized_field
1819 if (prev.type.is_pad and prev.type.align > 0 and prev_prev is not None):
1820 return (prev_prev, '((-prev.index) & (%d - 1))' % prev.type.align)
1826 c_type = self.c_type
1828 # special case: switch
1829 # in case of switch, 2 params have to be supplied to certain accessor functions:
1830 # 1. the anchestor object (request or reply)
1831 # 2. the (anchestor) switch object
1832 # the reason is that switch is either a child of a request/reply or nested in another switch,
1833 # so whenever we need to access a length field, we might need to refer to some anchestor type
1834 switch_obj = self if self.is_switch else None
1835 if self.is_case_or_bitcase:
1836 switch_obj = self.parents[-1]
1837 if switch_obj is not None:
1838 c_type = switch_obj.c_type
1842 parents = self.parents if hasattr(self, 'parents') else [self]
1843 # 'R': parents[0] is always the 'toplevel' container type
1844 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1845 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1846 # auxiliary object for 'R' parameters
1849 if switch_obj is not None:
1850 # now look where the fields are defined that are needed to evaluate
1851 # the switch expr, and store the parent objects in accessor_params and
1852 # the fields in switch_fields
1854 # 'S': name for the 'toplevel' switch
1855 toplevel_switch = parents[1]
1856 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1857 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1859 # initialize prefix for everything "below" S
1860 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1861 prefix = [(prefix_str, '->', toplevel_switch)]
1863 # look for fields in the remaining containers
1864 for p in parents[2:] + [self]:
1865 # the separator between parent and child is always '.' here,
1866 # because of nested switch statements
1867 if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
1868 prefix.append((p.name[-1], '.', p))
1869 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1871 # auxiliary object for 'S' parameter
1874 # for functions generated below:
1875 # * compute list of additional parameters which contains as parameter
1876 # any expr fields that cannot be resolved within self and descendants.
1877 # * and make sure that they are accessed without prefix within the function.
1878 unresolved_fields = resolve_expr_fields_list(list, parents)
1879 additional_params = []
1880 additional_param_names = set();
1881 for f in unresolved_fields:
1882 if f.c_field_name not in additional_param_names:
1883 # add to the list of additional params
1884 additional_params.append((f.c_field_type, f.c_field_name));
1885 # make sure that the param is accessed without prefix within the function
1886 fields[ f.c_field_name ] = (f.c_field_name, f)
1888 # internal function to compute the parameterlist with given indentation
1889 # such that the formatting of the additional parameters is consistent with
1890 # the other parameters.
1891 def additional_params_to_str(indent):
1892 if len(additional_params) == 0:
1895 return (',\n' + indent).join([''] + ['%s %s /**< */' % p for p in additional_params])
1899 if list.member.fixed_size():
1900 idx = 1 if switch_obj is not None else 0
1902 _hc('%s *', field.c_field_type)
1904 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1905 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1908 if switch_obj is not None:
1909 _c(' return %s;', fields[field.c_field_name][0])
1910 elif field.prev_varsized_field is None:
1911 _c(' return (%s *) (R + 1);', field.c_field_type)
1913 (prev_varsized_field, align_pad) = get_align_pad(field)
1915 if align_pad is None:
1916 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
1917 type_pad_type(field.first_field_after_varsized.type.c_type))
1919 _c(' xcb_generic_iterator_t prev = %s;',
1920 _c_iterator_get_end(prev_varsized_field, 'R'))
1921 _c(' return (%s *) ((char *) prev.data + %s + %d);',
1922 field.c_field_type, align_pad, field.prev_varsized_offset)
1927 spacing = ' '*(len(field.c_length_name)+2)
1928 add_param_str = additional_params_to_str(spacing)
1929 if switch_obj is not None:
1930 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1931 _h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
1932 _c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
1934 _h('%s (const %s *R /**< */%s);', field.c_length_name, c_type, add_param_str)
1935 _c('%s (const %s *R /**< */%s)', field.c_length_name, c_type, add_param_str)
1937 length = _c_accessor_get_expr(field.type.expr, fields)
1938 _c(' return %s;', length)
1941 if field.type.member.is_simple:
1943 _hc('xcb_generic_iterator_t')
1944 spacing = ' '*(len(field.c_end_name)+2)
1945 add_param_str = additional_params_to_str(spacing)
1946 if switch_obj is not None:
1947 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1948 _h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
1949 _c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
1951 _h('%s (const %s *R /**< */%s);', field.c_end_name, c_type, add_param_str)
1952 _c('%s (const %s *R /**< */%s)', field.c_end_name, c_type, add_param_str)
1954 _c(' xcb_generic_iterator_t i;')
1956 param = 'R' if switch_obj is None else 'S'
1957 if switch_obj is not None:
1958 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1959 _c_accessor_get_expr(field.type.expr, fields))
1960 elif field.prev_varsized_field == None:
1961 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1962 _c_accessor_get_expr(field.type.expr, fields))
1964 _c(' xcb_generic_iterator_t child = %s;',
1965 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1966 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1967 _c_accessor_get_expr(field.type.expr, fields))
1970 _c(' i.index = (char *) i.data - (char *) %s;', param)
1976 _hc('%s', field.c_iterator_type)
1977 spacing = ' '*(len(field.c_iterator_name)+2)
1978 add_param_str = additional_params_to_str(spacing)
1979 if switch_obj is not None:
1980 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1981 _h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
1982 _c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
1984 _h('%s (const %s *R /**< */%s);', field.c_iterator_name, c_type, add_param_str)
1985 _c('%s (const %s *R /**< */%s)', field.c_iterator_name, c_type, add_param_str)
1987 _c(' %s i;', field.c_iterator_type)
1990 length_expr_str = _c_accessor_get_expr(field.type.expr, fields)
1992 if switch_obj is not None:
1994 _c(' i.data = %s;', fields[field.c_field_name][0])
1995 _c(' i.rem = %s;', length_expr_str)
1996 elif field.prev_varsized_field == None:
1998 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
2000 (prev_varsized_field, align_pad) = get_align_pad(field)
2002 if align_pad is None:
2003 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
2004 type_pad_type(field.c_field_type))
2006 _c(' xcb_generic_iterator_t prev = %s;',
2007 _c_iterator_get_end(prev_varsized_field, 'R'))
2009 _c(' i.data = (%s *) ((char *) prev.data + %s);',
2010 field.c_field_type, align_pad)
2012 if switch_obj is None:
2013 _c(' i.rem = %s;', length_expr_str)
2014 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
2016 # initialize additional iterator fields which are derived from
2017 # additional type parameters for the list member type.
2018 additional_iter_fields = _c_get_additional_type_params(field.type.member)
2019 for iter_field in additional_iter_fields:
2020 _c(' i.%s = %s;', iter_field[2], fields[iter_field[2]][0])
2025 def _c_accessors(self, name, base):
2027 Declares the accessor functions for the fields of a structure.
2029 # no accessors for switch itself -
2030 # switch always needs to be unpacked explicitly
2031 # if self.is_switch:
2035 for field in self.fields:
2036 if not field.type.is_pad:
2037 if _c_field_needs_list_accessor(field):
2038 _c_accessors_list(self, field)
2039 elif _c_field_needs_field_accessor(field):
2040 _c_accessors_field(self, field)
2042 def c_simple(self, name):
2044 Exported function that handles cardinal type declarations.
2045 These are types which are typedef'd to one of the CARDx's, char, float, etc.
2047 _c_type_setup(self, name, ())
2049 if (self.name != name):
2054 _h('typedef %s %s;', _t(self.name), my_name)
2057 _c_iterator(self, name)
2059 def _c_complex(self, force_packed = False):
2061 Helper function for handling all structure types.
2062 Called for all structs, requests, replies, events, errors.
2067 _h(' * @brief %s', self.c_type)
2069 _h('typedef %s %s {', self.c_container, self.c_type)
2075 for field in self.fields:
2076 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2077 varfield = field.c_field_name
2080 struct_fields.append(field)
2082 for field in struct_fields:
2083 length = len(field.c_field_type)
2084 # account for '*' pointer_spec
2085 if not field.type.fixed_size() and not self.is_union:
2087 maxtypelen = max(maxtypelen, length)
2089 def _c_complex_field(self, field, space=''):
2090 if (field.type.fixed_size() or self.is_union or
2091 # in case of switch with switch children, don't make the field a pointer
2092 # necessary for unserialize to work
2093 (self.is_switch and field.type.is_switch)):
2094 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2095 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2097 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
2098 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2100 if not self.is_switch:
2101 for field in struct_fields:
2102 _c_complex_field(self, field)
2104 for b in self.bitcases:
2109 for field in b.type.fields:
2110 _c_complex_field(self, field, space)
2112 _h(' } %s;', b.c_field_name)
2114 _h('} %s%s;', 'XCB_PACKED ' if force_packed else '', self.c_type)
2116 def c_struct(self, name):
2118 Exported function that handles structure declarations.
2120 _c_type_setup(self, name, ())
2122 _c_accessors(self, name, name)
2123 _c_iterator(self, name)
2125 def c_union(self, name):
2127 Exported function that handles union declarations.
2129 _c_type_setup(self, name, ())
2131 _c_iterator(self, name)
2133 def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_fds=False):
2135 Declares a request function.
2138 # Four stunningly confusing possibilities here:
2141 # ------------------------------
2143 # 0 flag CHECKED flag Normal Mode
2144 # void_cookie req_cookie
2145 # ------------------------------
2146 # "req_checked" "req_unchecked"
2147 # CHECKED flag 0 flag Abnormal Mode
2148 # void_cookie req_cookie
2149 # ------------------------------
2152 # Whether we are _checked or _unchecked
2153 checked = void and not regular
2154 unchecked = not void and not regular
2156 # What kind of cookie we return
2157 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
2159 # What flag is passed to xcb_request
2160 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
2163 if func_flags == '0':
2164 func_flags = 'XCB_REQUEST_REPLY_FDS'
2166 func_flags = func_flags + '|XCB_REQUEST_REPLY_FDS'
2168 # Global extension id variable or NULL for xproto
2169 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
2171 # What our function name is
2172 func_name = self.c_request_name if not aux else self.c_aux_name
2174 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
2176 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
2180 maxtypelen = len('xcb_connection_t')
2182 # special case: list with variable size elements
2183 list_with_var_size_elems = False
2185 for field in self.fields:
2187 # The field should appear as a call parameter
2188 param_fields.append(field)
2189 if field.wire and not field.auto:
2190 # We need to set the field up in the structure
2191 wire_fields.append(field)
2192 if field.type.c_need_serialize or field.type.c_need_sizeof:
2193 serial_fields.append(field)
2195 for field in param_fields:
2196 c_field_const_type = field.c_field_const_type
2197 if field.type.c_need_serialize and not aux:
2198 c_field_const_type = "const void"
2199 if len(c_field_const_type) > maxtypelen:
2200 maxtypelen = len(c_field_const_type)
2201 if field.type.is_list and not field.type.member.fixed_size():
2202 list_with_var_size_elems = True
2208 if hasattr(self, "doc") and self.doc:
2210 _h(' * @brief ' + self.doc.brief)
2212 _h(' * No brief doc yet')
2215 _h(' * @param c The connection')
2216 param_names = [f.c_field_name for f in param_fields]
2217 if hasattr(self, "doc") and self.doc:
2218 for field in param_fields:
2219 # XXX: hard-coded until we fix xproto.xml
2220 base_func_name = self.c_request_name if not aux else self.c_aux_name
2221 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
2223 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
2225 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
2228 # XXX: why the 'xcb' prefix?
2229 key = ('xcb', field.enum)
2232 if namecount[tname] > 1:
2233 tname = _t(key + ('enum',))
2234 _h(' * @param %s A bitmask of #%s values.' % (field.c_field_name, tname))
2236 if self.doc and field.field_name in self.doc.fields:
2237 desc = self.doc.fields[field.field_name]
2238 for name in param_names:
2239 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
2240 desc = desc.split("\n")
2241 desc = [line if line != '' else '\\n' for line in desc]
2242 _h(' * @param %s %s' % (field.c_field_name, "\n * ".join(desc)))
2243 # If there is no documentation yet, we simply don't generate an
2244 # @param tag. Doxygen will then warn about missing documentation.
2246 _h(' * @return A cookie')
2249 if hasattr(self, "doc") and self.doc:
2250 if self.doc.description:
2251 desc = self.doc.description
2252 for name in param_names:
2253 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
2254 desc = desc.split("\n")
2255 _h(' * ' + "\n * ".join(desc))
2257 _h(' * No description yet')
2259 _h(' * Delivers a request to the X server.')
2262 _h(' * This form can be used only if the request will not cause')
2263 _h(' * a reply to be generated. Any returned error will be')
2264 _h(' * saved for handling by xcb_request_check().')
2266 _h(' * This form can be used only if the request will cause')
2267 _h(' * a reply to be generated. Any returned error will be')
2268 _h(' * placed in the event queue.')
2271 _hc('%s', cookie_type)
2273 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
2274 comma = ',' if len(param_fields) else ');'
2275 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
2276 comma = ',' if len(param_fields) else ')'
2277 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
2279 func_spacing = ' ' * (len(func_name) + 2)
2280 count = len(param_fields)
2281 for field in param_fields:
2283 c_field_const_type = field.c_field_const_type
2284 c_pointer = field.c_pointer
2285 if field.type.c_need_serialize and not aux:
2286 c_field_const_type = "const void"
2288 spacing = ' ' * (maxtypelen - len(c_field_const_type))
2289 comma = ',' if count else ');'
2290 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
2291 spacing, c_pointer, field.c_field_name, comma)
2292 comma = ',' if count else ')'
2293 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
2294 spacing, c_pointer, field.c_field_name, comma)
2297 if not self.c_var_followed_by_fixed_fields:
2298 for field in param_fields:
2299 if not field.type.fixed_size():
2301 if field.type.c_need_serialize:
2302 # _serialize() keeps track of padding automatically
2304 dimension = count + 2
2307 _c(' static const xcb_protocol_request_t xcb_req = {')
2308 _c(' /* count */ %d,', count)
2309 _c(' /* ext */ %s,', func_ext_global)
2310 _c(' /* opcode */ %s,', self.c_request_name.upper())
2311 _c(' /* isvoid */ %d', 1 if void else 0)
2315 _c(' struct iovec xcb_parts[%d];', dimension)
2316 _c(' %s xcb_ret;', func_cookie)
2317 _c(' %s xcb_out;', self.c_type)
2318 if self.c_var_followed_by_fixed_fields:
2319 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
2320 _c(' void *xcb_aux = 0;')
2323 for idx, f in enumerate(serial_fields):
2325 _c(' void *xcb_aux%d = 0;' % (idx))
2326 if list_with_var_size_elems:
2327 _c(' unsigned int i;')
2328 _c(' unsigned int xcb_tmp_len;')
2329 _c(' char *xcb_tmp;')
2331 # simple request call tracing
2332 # _c(' printf("in function %s\\n");' % func_name)
2335 for field in wire_fields:
2336 if field.type.fixed_size():
2337 if field.type.is_expr:
2338 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
2339 elif field.type.is_pad:
2340 if field.type.nmemb == 1:
2341 _c(' xcb_out.%s = 0;', field.c_field_name)
2343 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
2345 if field.type.nmemb == 1:
2346 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
2348 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
2350 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
2351 serialize_args = get_serialize_params(context, type_obj,
2354 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
2356 # calls in order to free dyn. all. memory
2360 if not self.c_var_followed_by_fixed_fields:
2361 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2362 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
2363 _c(' xcb_parts[3].iov_base = 0;')
2364 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2368 for field in param_fields:
2369 if not field.type.fixed_size():
2370 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
2371 # default: simple cast to char *
2372 if not field.type.c_need_serialize and not field.type.c_need_sizeof:
2373 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2374 if field.type.is_list:
2375 if field.type.member.fixed_size():
2376 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
2377 _c_accessor_get_expr(field.type.expr, None),
2378 field.type.member.c_wiretype)
2380 list_length = _c_accessor_get_expr(field.type.expr, None)
2383 _c(" xcb_parts[%d].iov_len = 0;" % count)
2384 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2385 _c(" for(i=0; i<%s; i++) {" % list_length)
2386 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2387 (field.type.c_sizeof_name))
2388 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2389 _c(" xcb_tmp += xcb_tmp_len;")
2392 # not supposed to happen
2393 raise Exception("unhandled variable size field %s" % field.c_field_name)
2396 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2397 idx = serial_fields.index(field)
2398 aux_var = '&xcb_aux%d' % idx
2399 context = 'serialize' if aux else 'sizeof'
2400 _c(' xcb_parts[%d].iov_len =', count)
2402 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2403 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2404 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2405 free_calls.append(' free(xcb_aux%d);' % idx)
2407 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2408 func_name = field.type.c_sizeof_name
2409 _c(' %s (%s);', func_name, serialize_args)
2412 if not (field.type.c_need_serialize or field.type.c_need_sizeof):
2413 # the _serialize() function keeps track of padding automatically
2414 _c(' xcb_parts[%d].iov_base = 0;', count)
2415 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2418 # elif self.c_var_followed_by_fixed_fields:
2420 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2421 # request header: opcodes + length
2422 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2425 buffer_var = '&xcb_aux'
2426 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2427 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2428 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2429 free_calls.append(' free(xcb_aux);')
2430 # no padding necessary - _serialize() keeps track of padding automatically
2433 for field in param_fields:
2435 _c(' xcb_send_fd(c, %s);', field.c_field_name)
2437 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2439 # free dyn. all. data, if any
2440 for f in free_calls:
2442 _c(' return xcb_ret;')
2445 def _c_reply(self, name):
2447 Declares the function that returns the reply structure.
2449 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2450 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2451 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2453 # check if _unserialize() has to be called for any field
2454 def look_for_special_cases(complex_obj):
2455 unserialize_fields = []
2456 # no unserialize call in case of switch
2457 if not complex_obj.is_switch:
2458 for field in complex_obj.fields:
2459 # three cases: 1. field with special case
2460 # 2. container that contains special case field
2461 # 3. list with special case elements
2462 if field.type.c_var_followed_by_fixed_fields:
2463 unserialize_fields.append(field)
2464 elif field.type.is_container:
2465 unserialize_fields += look_for_special_cases(field.type)
2466 elif field.type.is_list:
2467 if field.type.member.c_var_followed_by_fixed_fields:
2468 unserialize_fields.append(field)
2469 if field.type.member.is_container:
2470 unserialize_fields += look_for_special_cases(field.type.member)
2471 return unserialize_fields
2473 unserialize_fields = look_for_special_cases(self.reply)
2477 _h(' * Return the reply')
2478 _h(' * @param c The connection')
2479 _h(' * @param cookie The cookie')
2480 _h(' * @param e The xcb_generic_error_t supplied')
2482 _h(' * Returns the reply of the request asked by')
2484 _h(' * The parameter @p e supplied to this function must be NULL if')
2485 _h(' * %s(). is used.', self.c_unchecked_name)
2486 _h(' * Otherwise, it stores the error if any.')
2488 _h(' * The returned value must be freed by the caller using free().')
2491 _hc('%s *', self.c_reply_type)
2492 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2493 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2494 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2495 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2498 if len(unserialize_fields)>0:
2499 # certain variable size fields need to be unserialized explicitly
2500 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2501 self.c_reply_type, self.c_reply_type)
2503 for field in unserialize_fields:
2504 if field.type.is_list:
2505 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2506 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2507 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2509 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2510 # call _unserialize(), using the reply as source and target buffer
2511 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2512 for field in unserialize_fields:
2513 if field.type.is_list:
2514 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2515 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2516 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2517 field.c_field_name, field.c_field_name)
2518 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2520 # return the transformed reply
2521 _c(' return reply;')
2524 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2528 def _c_reply_has_fds(self):
2529 for field in self.fields:
2534 def _c_reply_fds(self, name):
2536 Declares the function that returns fds related to the reply.
2538 spacing1 = ' ' * (len(self.c_reply_type) - len('xcb_connection_t'))
2539 spacing3 = ' ' * (len(self.c_reply_fds_name) + 2)
2542 _h(' * Return the reply fds')
2543 _h(' * @param c The connection')
2544 _h(' * @param reply The reply')
2546 _h(' * Returns the array of reply fds of the request asked by')
2548 _h(' * The returned value must be freed by the caller using free().')
2552 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_fds_name, spacing1)
2553 _h('%s%s *reply /**< */);', spacing3, self.c_reply_type)
2554 _c('%s%s *reply /**< */)', spacing3, self.c_reply_type)
2557 _c(' return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
2562 def _c_opcode(name, opcode):
2564 Declares the opcode define for requests, events, and errors.
2568 _h('/** Opcode for %s. */', _n(name))
2569 _h('#define %s %s', _n(name).upper(), opcode)
2571 def _c_cookie(self, name):
2573 Declares the cookie type for a non-void request.
2578 _h(' * @brief %s', self.c_cookie_type)
2580 _h('typedef struct %s {', self.c_cookie_type)
2581 _h(' unsigned int sequence; /**< */')
2582 _h('} %s;', self.c_cookie_type)
2584 def _man_request(self, name, cookie_type, void, aux):
2585 param_fields = [f for f in self.fields if f.visible]
2587 func_name = self.c_request_name if not aux else self.c_aux_name
2589 def create_link(linkname):
2590 name = 'man/%s.%s' % (linkname, section)
2592 sys.stdout.write(name)
2594 f.write('.so man%s/%s.%s' % (section, func_name, section))
2598 sys.stdout.write('man/%s.%s ' % (func_name, section))
2599 # Our CWD is src/, so this will end up in src/man/
2600 f = open('man/%s.%s' % (func_name, section), 'w')
2601 f.write('.TH %s %s "%s" "%s" "XCB Requests"\n' % (func_name, section, center_footer, left_footer))
2602 # Left-adjust instead of adjusting to both sides
2604 f.write('.SH NAME\n')
2605 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2606 f.write('%s \\- %s\n' % (func_name, brief))
2607 f.write('.SH SYNOPSIS\n')
2608 # Don't split words (hyphenate)
2610 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2612 # function prototypes
2614 count = len(param_fields)
2615 for field in param_fields:
2617 c_field_const_type = field.c_field_const_type
2618 c_pointer = field.c_pointer
2619 if c_pointer == ' ':
2621 if field.type.c_need_serialize and not aux:
2622 c_field_const_type = "const void"
2624 comma = ', ' if count else ');'
2625 prototype += '%s\\ %s\\fI%s\\fP%s' % (c_field_const_type, c_pointer, field.c_field_name, comma)
2627 f.write('.SS Request function\n')
2629 base_func_name = self.c_request_name if not aux else self.c_aux_name
2630 f.write('%s \\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\n' % (cookie_type, base_func_name, prototype))
2631 create_link('%s_%s' % (base_func_name, ('checked' if void else 'unchecked')))
2634 f.write('.SS Reply datastructure\n')
2637 f.write('typedef %s %s {\n' % (self.reply.c_container, self.reply.c_type))
2641 for field in self.reply.fields:
2642 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2645 struct_fields.append(field)
2647 for field in struct_fields:
2648 length = len(field.c_field_type)
2649 # account for '*' pointer_spec
2650 if not field.type.fixed_size():
2652 maxtypelen = max(maxtypelen, length)
2654 def _c_complex_field(self, field, space=''):
2655 if (field.type.fixed_size() or
2656 # in case of switch with switch children, don't make the field a pointer
2657 # necessary for unserialize to work
2658 (self.is_switch and field.type.is_switch)):
2659 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2660 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2662 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
2663 f.write('ELSE %s = %s\n' % (field.c_field_type, field.c_field_name))
2664 #_h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2666 if not self.is_switch:
2667 for field in struct_fields:
2668 _c_complex_field(self, field)
2670 for b in self.bitcases:
2674 for field in b.type.fields:
2675 _c_complex_field(self, field, space)
2677 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2680 f.write('} \\fB%s\\fP;\n' % self.reply.c_type)
2683 f.write('.SS Reply function\n')
2685 f.write(('%s *\\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\\ '
2686 '\\fIcookie\\fP, xcb_generic_error_t\\ **\\fIe\\fP);\n') %
2687 (self.c_reply_type, self.c_reply_name, self.c_cookie_type))
2688 create_link('%s' % self.c_reply_name)
2690 has_accessors = False
2691 for field in self.reply.fields:
2692 if field.type.is_list and not field.type.fixed_size():
2693 has_accessors = True
2694 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2695 has_accessors = True
2698 f.write('.SS Reply accessors\n')
2700 def _c_accessors_field(self, field):
2702 Declares the accessor functions for a non-list field that follows a variable-length field.
2704 c_type = self.c_type
2706 # special case: switch
2707 switch_obj = self if self.is_switch else None
2708 if self.is_case_or_bitcase:
2709 switch_obj = self.parents[-1]
2710 if switch_obj is not None:
2711 c_type = switch_obj.c_type
2713 if field.type.is_simple:
2714 f.write('%s %s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2715 create_link('%s' % field.c_accessor_name)
2717 f.write('%s *%s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2718 create_link('%s' % field.c_accessor_name)
2720 def _c_accessors_list(self, field):
2722 Declares the accessor functions for a list field.
2723 Declares a direct-accessor function only if the list members are fixed size.
2724 Declares length and get-iterator functions always.
2727 c_type = self.reply.c_type
2729 # special case: switch
2730 # in case of switch, 2 params have to be supplied to certain accessor functions:
2731 # 1. the anchestor object (request or reply)
2732 # 2. the (anchestor) switch object
2733 # the reason is that switch is either a child of a request/reply or nested in another switch,
2734 # so whenever we need to access a length field, we might need to refer to some anchestor type
2735 switch_obj = self if self.is_switch else None
2736 if self.is_case_or_bitcase:
2737 switch_obj = self.parents[-1]
2738 if switch_obj is not None:
2739 c_type = switch_obj.c_type
2743 parents = self.parents if hasattr(self, 'parents') else [self]
2744 # 'R': parents[0] is always the 'toplevel' container type
2745 params.append(('const %s *\\fIreply\\fP' % parents[0].c_type, parents[0]))
2746 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
2747 # auxiliary object for 'R' parameters
2750 if switch_obj is not None:
2751 # now look where the fields are defined that are needed to evaluate
2752 # the switch expr, and store the parent objects in accessor_params and
2753 # the fields in switch_fields
2755 # 'S': name for the 'toplevel' switch
2756 toplevel_switch = parents[1]
2757 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
2758 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
2760 # initialize prefix for everything "below" S
2761 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
2762 prefix = [(prefix_str, '->', toplevel_switch)]
2764 # look for fields in the remaining containers
2765 for p in parents[2:] + [self]:
2766 # the separator between parent and child is always '.' here,
2767 # because of nested switch statements
2768 if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
2769 prefix.append((p.name[-1], '.', p))
2770 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
2772 # auxiliary object for 'S' parameter
2775 if list.member.fixed_size():
2776 idx = 1 if switch_obj is not None else 0
2778 f.write('%s *\\fB%s\\fP(%s);\n' %
2779 (field.c_field_type, field.c_accessor_name, params[idx][0]))
2780 create_link('%s' % field.c_accessor_name)
2783 f.write('int \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2784 (field.c_length_name, c_type))
2785 create_link('%s' % field.c_length_name)
2787 if field.type.member.is_simple:
2789 f.write('xcb_generic_iterator_t \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2790 (field.c_end_name, c_type))
2791 create_link('%s' % field.c_end_name)
2794 f.write('%s \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2795 (field.c_iterator_type, field.c_iterator_name,
2797 create_link('%s' % field.c_iterator_name)
2799 for field in self.reply.fields:
2800 if field.type.is_list and not field.type.fixed_size():
2801 _c_accessors_list(self, field)
2802 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2803 _c_accessors_field(self, field)
2807 # Re-enable hyphenation and adjusting to both sides
2810 # argument reference
2811 f.write('.SH REQUEST ARGUMENTS\n')
2812 f.write('.IP \\fI%s\\fP 1i\n' % 'conn')
2813 f.write('The XCB connection to X11.\n')
2814 for field in param_fields:
2815 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2816 printed_enum = False
2817 # XXX: hard-coded until we fix xproto.xml
2818 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
2820 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
2822 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
2824 if hasattr(field, "enum") and field.enum:
2825 # XXX: why the 'xcb' prefix?
2826 key = ('xcb', field.enum)
2828 f.write('One of the following values:\n')
2831 count = len(enum.values)
2832 for (enam, eval) in enum.values:
2834 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2835 if hasattr(enum, "doc") and enum.doc and enam in enum.doc.fields:
2836 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2837 f.write('%s\n' % desc)
2839 f.write('TODO: NOT YET DOCUMENTED.\n')
2844 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2845 desc = self.doc.fields[field.field_name]
2846 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2849 f.write('%s\n' % desc)
2851 f.write('TODO: NOT YET DOCUMENTED.\n')
2857 f.write('.SH REPLY FIELDS\n')
2858 # These fields are present in every reply:
2859 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2860 f.write(('The type of this reply, in this case \\fI%s\\fP. This field '
2861 'is also present in the \\fIxcb_generic_reply_t\\fP and can '
2862 'be used to tell replies apart from each other.\n') %
2863 _n(self.reply.name).upper())
2864 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2865 f.write('The sequence number of the last request processed by the X11 server.\n')
2866 f.write('.IP \\fI%s\\fP 1i\n' % 'length')
2867 f.write('The length of the reply, in words (a word is 4 bytes).\n')
2868 for field in self.reply.fields:
2869 if (field.c_field_name in frozenset(['response_type', 'sequence', 'length']) or
2870 field.c_field_name.startswith('pad')):
2873 if field.type.is_list and not field.type.fixed_size():
2875 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2877 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2878 printed_enum = False
2879 if hasattr(field, "enum") and field.enum:
2880 # XXX: why the 'xcb' prefix?
2881 key = ('xcb', field.enum)
2883 f.write('One of the following values:\n')
2886 count = len(enum.values)
2887 for (enam, eval) in enum.values:
2889 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2890 if enum.doc and enam in enum.doc.fields:
2891 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2892 f.write('%s\n' % desc)
2894 f.write('TODO: NOT YET DOCUMENTED.\n')
2899 if hasattr(self.reply, "doc") and self.reply.doc and field.field_name in self.reply.doc.fields:
2900 desc = self.reply.doc.fields[field.field_name]
2901 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2904 f.write('%s\n' % desc)
2906 f.write('TODO: NOT YET DOCUMENTED.\n')
2913 f.write('.SH DESCRIPTION\n')
2914 if hasattr(self, "doc") and self.doc and self.doc.description:
2915 desc = self.doc.description
2916 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2917 lines = desc.split('\n')
2918 f.write('\n'.join(lines) + '\n')
2920 f.write('.SH RETURN VALUE\n')
2922 f.write(('Returns an \\fIxcb_void_cookie_t\\fP. Errors (if any) '
2923 'have to be handled in the event loop.\n\nIf you want to '
2924 'handle errors directly with \\fIxcb_request_check\\fP '
2925 'instead, use \\fI%s_checked\\fP. See '
2926 '\\fBxcb-requests(%s)\\fP for details.\n') % (base_func_name, section))
2928 f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
2929 'calling the reply function \\fI%s\\fP.\n\nIf you want to '
2930 'handle errors in the event loop instead, use '
2931 '\\fI%s_unchecked\\fP. See \\fBxcb-requests(%s)\\fP for '
2933 (cookie_type, self.c_reply_name, base_func_name, section))
2934 f.write('.SH ERRORS\n')
2935 if hasattr(self, "doc") and self.doc:
2936 for errtype, errtext in sorted(self.doc.errors.items()):
2937 f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
2938 errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
2939 f.write('%s\n' % (errtext))
2940 if not hasattr(self, "doc") or not self.doc or len(self.doc.errors) == 0:
2941 f.write('This request does never generate any errors.\n')
2942 if hasattr(self, "doc") and self.doc and self.doc.example:
2943 f.write('.SH EXAMPLE\n')
2946 lines = self.doc.example.split('\n')
2947 f.write('\n'.join(lines) + '\n')
2949 f.write('.SH SEE ALSO\n')
2950 if hasattr(self, "doc") and self.doc:
2951 see = ['.BR %s (%s)' % ('xcb-requests', section)]
2952 if self.doc.example:
2953 see.append('.BR %s (%s)' % ('xcb-examples', section))
2954 for seename, seetype in sorted(self.doc.see.items()):
2955 if seetype == 'program':
2956 see.append('.BR %s (1)' % seename)
2957 elif seetype == 'event':
2958 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2959 elif seetype == 'request':
2960 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2961 elif seetype == 'function':
2962 see.append('.BR %s (%s)' % (seename, section))
2964 see.append('TODO: %s (type %s)' % (seename, seetype))
2965 f.write(',\n'.join(see) + '\n')
2966 f.write('.SH AUTHOR\n')
2967 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2970 def _man_event(self, name):
2972 sys.stdout.write('man/%s.%s ' % (self.c_type, section))
2973 # Our CWD is src/, so this will end up in src/man/
2974 f = open('man/%s.%s' % (self.c_type, section), 'w')
2975 f.write('.TH %s %s "%s" "%s" "XCB Events"\n' % (self.c_type, section, center_footer, left_footer))
2976 # Left-adjust instead of adjusting to both sides
2978 f.write('.SH NAME\n')
2979 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2980 f.write('%s \\- %s\n' % (self.c_type, brief))
2981 f.write('.SH SYNOPSIS\n')
2982 # Don't split words (hyphenate)
2984 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2987 f.write('.SS Event datastructure\n')
2990 f.write('typedef %s %s {\n' % (self.c_container, self.c_type))
2994 for field in self.fields:
2995 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2998 struct_fields.append(field)
3000 for field in struct_fields:
3001 length = len(field.c_field_type)
3002 # account for '*' pointer_spec
3003 if not field.type.fixed_size():
3005 maxtypelen = max(maxtypelen, length)
3007 def _c_complex_field(self, field, space=''):
3008 if (field.type.fixed_size() or
3009 # in case of switch with switch children, don't make the field a pointer
3010 # necessary for unserialize to work
3011 (self.is_switch and field.type.is_switch)):
3012 spacing = ' ' * (maxtypelen - len(field.c_field_type))
3013 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
3015 print >> sys.stderr, 'ERROR: New unhandled documentation case'
3017 if not self.is_switch:
3018 for field in struct_fields:
3019 _c_complex_field(self, field)
3021 for b in self.bitcases:
3025 for field in b.type.fields:
3026 _c_complex_field(self, field, space)
3028 print >> sys.stderr, 'ERROR: New unhandled documentation case'
3031 f.write('} \\fB%s\\fP;\n' % self.c_type)
3036 # Re-enable hyphenation and adjusting to both sides
3039 # argument reference
3040 f.write('.SH EVENT FIELDS\n')
3041 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
3042 f.write(('The type of this event, in this case \\fI%s\\fP. This field is '
3043 'also present in the \\fIxcb_generic_event_t\\fP and can be used '
3044 'to tell events apart from each other.\n') % _n(name).upper())
3045 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
3046 f.write('The sequence number of the last request processed by the X11 server.\n')
3048 if not self.is_switch:
3049 for field in struct_fields:
3050 # Skip the fields which every event has, we already documented
3052 if field.c_field_name in ('response_type', 'sequence'):
3054 if isinstance(field.type, PadType):
3056 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
3057 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
3058 desc = self.doc.fields[field.field_name]
3059 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
3060 f.write('%s\n' % desc)
3062 f.write('NOT YET DOCUMENTED.\n')
3065 f.write('.SH DESCRIPTION\n')
3066 if hasattr(self, "doc") and self.doc and self.doc.description:
3067 desc = self.doc.description
3068 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
3069 lines = desc.split('\n')
3070 f.write('\n'.join(lines) + '\n')
3072 if hasattr(self, "doc") and self.doc and self.doc.example:
3073 f.write('.SH EXAMPLE\n')
3076 lines = self.doc.example.split('\n')
3077 f.write('\n'.join(lines) + '\n')
3079 f.write('.SH SEE ALSO\n')
3080 if hasattr(self, "doc") and self.doc:
3081 see = ['.BR %s (%s)' % ('xcb_generic_event_t', section)]
3082 if self.doc.example:
3083 see.append('.BR %s (%s)' % ('xcb-examples', section))
3084 for seename, seetype in sorted(self.doc.see.items()):
3085 if seetype == 'program':
3086 see.append('.BR %s (1)' % seename)
3087 elif seetype == 'event':
3088 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
3089 elif seetype == 'request':
3090 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
3091 elif seetype == 'function':
3092 see.append('.BR %s (%s)' % (seename, section))
3094 see.append('TODO: %s (type %s)' % (seename, seetype))
3095 f.write(',\n'.join(see) + '\n')
3096 f.write('.SH AUTHOR\n')
3097 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
3101 def c_request(self, name):
3103 Exported function that handles request declarations.
3105 _c_type_setup(self, name, ('request',))
3108 # Cookie type declaration
3109 _c_cookie(self, name)
3112 _c_opcode(name, self.opcode)
3114 # Request structure declaration
3118 _c_type_setup(self.reply, name, ('reply',))
3119 # Reply structure definition
3120 _c_complex(self.reply)
3121 # Request prototypes
3122 has_fds = _c_reply_has_fds(self.reply)
3123 _c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds)
3124 _c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds)
3126 _c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds)
3127 _c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds)
3129 _c_accessors(self.reply, name + ('reply',), name)
3130 _c_reply(self, name)
3132 _c_reply_fds(self, name)
3134 # Request prototypes
3135 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
3136 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
3138 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
3139 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
3141 # We generate the manpage afterwards because _c_type_setup has been called.
3142 # TODO: what about aux helpers?
3143 cookie_type = self.c_cookie_type if self.reply else 'xcb_void_cookie_t'
3144 _man_request(self, name, cookie_type, not self.reply, False)
3146 def c_event(self, name):
3148 Exported function that handles event declarations.
3151 # The generic event structure xcb_ge_event_t has the full_sequence field
3152 # at the 32byte boundary. That's why we've to inject this field into GE
3153 # events while generating the structure for them. Otherwise we would read
3154 # garbage (the internal full_sequence) when accessing normal event fields
3156 force_packed = False
3157 if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
3159 for field in self.fields:
3160 if field.type.size != None and field.type.nmemb != None:
3161 event_size += field.type.size * field.type.nmemb
3162 if event_size == 32:
3163 full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
3164 idx = self.fields.index(field)
3165 self.fields.insert(idx + 1, full_sequence)
3167 # If the event contains any 64-bit extended fields, they need
3168 # to remain aligned on a 64-bit boundary. Adding full_sequence
3169 # would normally break that; force the struct to be packed.
3170 force_packed = any(f.type.size == 8 and f.type.is_simple for f in self.fields[(idx+1):])
3173 if self.name == name:
3174 _c_type_setup(self, name, ('event',))
3175 # generate accessors
3176 # (needed for fields after var-sized fields, for lists with var-sized elements,
3178 _c_accessors(self, name, name)
3180 # no type-setup needed for eventcopies
3181 # (the type-setup of an eventcopy would overwrite members of the original
3182 # event, and it would create sizeof-etc funtions which
3183 # called undefined accessor functions)
3187 _c_opcode(name, self.opcodes[name])
3189 if self.name == name:
3190 # Structure definition
3191 _c_complex(self, force_packed)
3195 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
3197 # Create sizeof-function for eventcopies for compatibility reasons
3198 if self.c_need_sizeof:
3203 _h('%s (const void *_buffer /**< */);', _n(name + ('sizeof',)))
3206 _c('%s (const void *_buffer /**< */)', _n(name + ('sizeof',)))
3208 _c(' return %s(_buffer);', _n(self.name + ('sizeof',)))
3213 _man_event(self, name)
3215 def c_error(self, name):
3217 Exported function that handles error declarations.
3219 _c_type_setup(self, name, ('error',))
3222 _c_opcode(name, self.opcodes[name])
3224 if self.name == name:
3225 # Structure definition
3230 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
3233 # Main routine starts here
3235 # Must create an "output" dictionary before any xcbgen imports.
3236 output = {'open' : c_open,
3238 'simple' : c_simple,
3240 'struct' : c_struct,
3242 'request' : c_request,
3247 # Boilerplate below this point
3249 # Check for the argument that specifies path to the xcbgen python package.
3251 opts, args = getopt.getopt(sys.argv[1:], 'c:l:s:p:m')
3252 except getopt.GetoptError as err:
3254 print('Usage: c_client.py -c center_footer -l left_footer -s section [-p path] file.xml')
3257 for (opt, arg) in opts:
3265 sys.path.insert(1, arg)
3268 sys.stdout.write('man_MANS = ')
3270 # Import the module class
3272 from xcbgen.state import Module
3273 from xcbgen.xtypes import *
3276 Failed to load the xcbgen Python package!
3277 Make sure that xcb/proto installed it on your Python path.
3278 If not, you will need to create a .pth file or define $PYTHONPATH
3280 Refer to the README file in xcb/proto for more info.
3284 # Ensure the man subdirectory exists
3287 except OSError as e:
3288 if e.errno != errno.EEXIST:
3291 # Parse the xml header
3292 module = Module(args[0], output)
3294 # Build type-registry and resolve type dependencies