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 # XXX See if this level thing is really necessary.
64 Changes the array that header lines are written to.
65 Supports writing different sections of the header file.
68 while len(_hlines) <= idx:
74 Changes the array that source lines are written to.
75 Supports writing to different sections of the source file.
78 while len(_clines) <= idx:
84 Does C-name conversion on a single string fragment.
85 Uses a regexp with some hard-coded special cases.
87 if str in _cname_special_cases:
88 return _cname_special_cases[str]
90 split = _cname_re.finditer(str)
91 name_parts = [match.group(0) for match in split]
92 return '_'.join(name_parts)
96 Checks for certain C++ reserved words and fixes them.
98 if str in _cplusplus_annoyances:
99 return _cplusplus_annoyances[str]
100 elif str in _c_keywords:
101 return _c_keywords[str]
107 Does C-name conversion on an extension name.
108 Has some additional special cases on top of _n_item.
110 if str in _extension_special_cases:
111 return _n_item(str).lower()
117 Does C-name conversion on a tuple of strings.
118 Different behavior depending on length of tuple, extension/not extension, etc.
119 Basically C-name converts the individual pieces, then joins with underscores.
124 parts = [list[0], _n_item(list[1])]
126 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
128 parts = [list[0]] + [_n_item(i) for i in list[1:]]
129 return '_'.join(parts).lower()
133 Does C-name conversion on a tuple of strings representing a type.
134 Same as _n but adds a "_t" on the end.
139 parts = [list[0], _n_item(list[1]), 't']
141 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
143 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
144 return '_'.join(parts).lower()
149 Exported function that handles module open.
150 Opens the files and writes out the auto-generated comment, header file includes, etc.
154 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
156 # Build the type-name collision avoidance table used by c_enum
157 build_collision_table()
163 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
164 _hc(' * Edit at your peril.')
169 _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
170 _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
174 _h('#ifndef __%s_H', _ns.header.upper())
175 _h('#define __%s_H', _ns.header.upper())
177 _h('#include "xcb.h"')
179 _c('#ifdef HAVE_CONFIG_H')
180 _c('#include "config.h"')
182 _c('#include <stdlib.h>')
183 _c('#include <string.h>')
184 _c('#include <assert.h>')
185 _c('#include <stddef.h> /* for offsetof() */')
186 _c('#include "xcbext.h"')
187 _c('#include "%s.h"', _ns.header)
190 _c('#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)')
193 for (n, h) in self.direct_imports:
194 _hc('#include "%s.h"', h)
197 _h('#ifdef __cplusplus')
203 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
204 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
206 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
209 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
213 Exported function that handles module close.
214 Writes out all the stored content lines, then closes the files.
221 _h('#ifdef __cplusplus')
233 hfile = open('%s.h' % _ns.header, 'w')
241 cfile = open('%s.c' % _ns.header, 'w')
248 def build_collision_table():
252 for v in module.types.values():
254 namecount[name] = (namecount.get(name) or 0) + 1
256 def c_enum(self, name):
258 Exported function that handles enum declarations.
264 if namecount[tname] > 1:
265 tname = _t(name + ('enum',))
269 _h('typedef enum %s {', tname)
271 count = len(self.values)
273 for (enam, eval) in self.values:
275 equals = ' = ' if eval != '' else ''
276 comma = ',' if count > 0 else ''
278 if hasattr(self, "doc") and self.doc and enam in self.doc.fields:
279 doc = '\n/**< %s */\n' % self.doc.fields[enam]
280 _h(' %s%s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma, doc)
284 def _c_type_setup(self, name, postfix):
286 Sets up all the C-related state by adding additional data fields to
287 all Field and Type objects. Here is where we figure out most of our
288 variable and function names.
290 Recurses into child fields and list member types.
292 # Do all the various names in advance
293 self.c_type = _t(name + postfix)
294 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
296 self.c_iterator_type = _t(name + ('iterator',))
297 self.c_next_name = _n(name + ('next',))
298 self.c_end_name = _n(name + ('end',))
300 self.c_request_name = _n(name)
301 self.c_checked_name = _n(name + ('checked',))
302 self.c_unchecked_name = _n(name + ('unchecked',))
303 self.c_reply_name = _n(name + ('reply',))
304 self.c_reply_type = _t(name + ('reply',))
305 self.c_cookie_type = _t(name + ('cookie',))
306 self.c_reply_fds_name = _n(name + ('reply_fds',))
308 self.c_need_aux = False
309 self.c_need_serialize = False
310 self.c_need_sizeof = False
312 self.c_aux_name = _n(name + ('aux',))
313 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
314 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
315 self.c_serialize_name = _n(name + ('serialize',))
316 self.c_unserialize_name = _n(name + ('unserialize',))
317 self.c_unpack_name = _n(name + ('unpack',))
318 self.c_sizeof_name = _n(name + ('sizeof',))
320 # special case: structs where variable size fields are followed by fixed size fields
321 self.c_var_followed_by_fixed_fields = False
324 self.c_need_serialize = True
325 self.c_container = 'struct'
326 for bitcase in self.bitcases:
327 bitcase.c_field_name = _cpp(bitcase.field_name)
328 bitcase_name = bitcase.field_type if bitcase.type.has_name else name
329 _c_type_setup(bitcase.type, bitcase_name, ())
331 elif self.is_container:
333 self.c_container = 'union' if self.is_union else 'struct'
334 prev_varsized_field = None
335 prev_varsized_offset = 0
336 first_field_after_varsized = None
338 for field in self.fields:
339 field.c_field_type = _t(field.field_type)
340 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
341 field.c_field_name = _cpp(field.field_name)
342 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb and field.type.nmemb > 1) else ''
343 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
345 # correct the c_pointer field for variable size non-list types
346 if not field.type.fixed_size() and field.c_pointer == ' ':
347 field.c_pointer = '*'
348 if field.type.is_list and not field.type.member.fixed_size():
349 field.c_pointer = '*'
351 if field.type.is_switch:
352 field.c_pointer = '*'
353 field.c_field_const_type = 'const ' + field.c_field_type
354 self.c_need_aux = True
356 if not field.type.fixed_size() and not field.type.is_case_or_bitcase:
357 self.c_need_sizeof = True
359 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
360 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
361 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
362 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
363 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
365 field.prev_varsized_field = prev_varsized_field
366 field.prev_varsized_offset = prev_varsized_offset
368 if prev_varsized_offset == 0:
369 first_field_after_varsized = field
370 field.first_field_after_varsized = first_field_after_varsized
372 if field.type.fixed_size():
373 prev_varsized_offset += field.type.size
374 # special case: intermixed fixed and variable size fields
375 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
376 if not self.is_union:
377 self.c_need_serialize = True
378 self.c_var_followed_by_fixed_fields = True
380 self.last_varsized_field = field
381 prev_varsized_field = field
382 prev_varsized_offset = 0
384 if self.c_var_followed_by_fixed_fields:
385 if field.type.fixed_size():
386 field.prev_varsized_field = None
388 # recurse into this field
389 # this has to be done here, i.e., after the field has been set up
390 # Otherwise the function _c_helper_absolute_name
391 # will produce garbage or crash
392 _c_type_setup(field.type, field.field_type, ())
393 if field.type.is_list:
394 _c_type_setup(field.type.member, field.field_type, ())
395 if (field.type.nmemb is None):
396 self.c_need_sizeof = True
399 if self.c_need_serialize:
400 # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
401 self.c_need_sizeof = True
403 # as switch does never appear at toplevel,
404 # continue here with type construction
406 if self.c_type not in finished_switch:
407 finished_switch.append(self.c_type)
408 # special: switch C structs get pointer fields for variable-sized members
410 for bitcase in self.bitcases:
411 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
412 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
413 # no list with switch as element, so no call to
414 # _c_iterator(field.type, field_name) necessary
416 if not self.is_case_or_bitcase:
417 if self.c_need_serialize:
418 if self.c_serialize_name not in finished_serializers:
419 finished_serializers.append(self.c_serialize_name)
420 _c_serialize('serialize', self)
422 # _unpack() and _unserialize() are only needed for special cases:
424 # special cases -> unserialize
425 if self.is_switch or self.c_var_followed_by_fixed_fields:
426 _c_serialize('unserialize', self)
428 if self.c_need_sizeof:
429 if self.c_sizeof_name not in finished_sizeof:
430 if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
431 finished_sizeof.append(self.c_sizeof_name)
432 _c_serialize('sizeof', self)
435 # Functions for querying field properties
436 def _c_field_needs_list_accessor(field):
437 return field.type.is_list and not field.type.fixed_size()
439 def _c_field_needs_field_accessor(field):
440 if field.type.is_list:
444 field.prev_varsized_field is not None
445 or not field.type.fixed_size()
448 def _c_field_needs_accessor(field):
450 _c_field_needs_list_accessor(field)
452 _c_field_needs_field_accessor(field)
455 def _c_field_is_member_of_case_or_bitcase(field):
456 if field.parent is None:
458 elif field.parent.is_case_or_bitcase:
463 # end of Functions for querying field properties
465 def _c_helper_absolute_name(prefix, field=None):
467 turn prefix, which is a list of tuples (name, separator, Type obj) into a string
468 representing a valid name in C (based on the context)
469 if field is not None, append the field name as well
473 for name, sep, obj in prefix:
474 prefix_str += last_sep + name
477 if ((obj.is_case_or_bitcase and obj.has_name) or # named bitcase
478 (obj.is_switch and len(obj.parents)>1)):
483 # add separator for access to a yet unknown field
484 prefix_str += last_sep
486 if _c_field_needs_accessor(field):
487 if _c_field_is_member_of_case_or_bitcase(field):
488 # case members are available in the deserialized struct,
489 # so there is no need to use the accessor function
490 # (also, their accessor function needs a different arglist
491 # so this would require special treatment here)
492 # Therefore: Access as struct member
493 prefix_str += last_sep + _cpp(field.field_name)
495 # Access with the accessor function
496 prefix_str = field.c_accessor_name + "(" + prefix_str + ")"
498 # Access as struct member
499 prefix_str += last_sep + _cpp(field.field_name)
504 def _c_helper_field_mapping(complex_type, prefix, flat=False):
506 generate absolute names, based on prefix, for all fields starting from complex_type
507 if flat == True, nested complex types are not taken into account
510 if complex_type.is_switch:
511 for b in complex_type.bitcases:
513 switch_name, switch_sep, switch_type = prefix[-1]
514 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
516 bitcase_prefix = prefix
518 if (True==flat and not b.type.has_name) or False==flat:
519 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
521 for f in complex_type.fields:
522 fname = _c_helper_absolute_name(prefix, f)
523 if f.field_name in all_fields:
524 raise Exception("field name %s has been registered before" % f.field_name)
526 all_fields[f.field_name] = (fname, f)
527 if f.type.is_container and flat==False:
528 if f.type.is_case_or_bitcase and not f.type.has_name:
530 elif f.type.is_switch and len(f.type.parents)>1:
531 # nested switch gets another separator
532 new_prefix = prefix+[(f.c_field_name, '.', f.type)]
534 new_prefix = prefix+[(f.c_field_name, '->', f.type)]
535 all_fields.update(_c_helper_field_mapping(f.type, new_prefix, flat))
540 def _c_helper_resolve_field_names (prefix):
542 get field names for all objects in the prefix array
546 # look for fields in the remaining containers
547 for idx, p in enumerate(prefix):
550 # sep can be preset in prefix, if not, make a sensible guess
551 sep = '.' if (obj.is_switch or obj.is_case_or_bitcase) else '->'
552 # exception: 'toplevel' object (switch as well!) always have sep '->'
553 sep = '->' if idx<1 else sep
554 if not obj.is_case_or_bitcase or (obj.is_case_or_bitcase and obj.has_name):
555 tmp_prefix.append((name, sep, obj))
556 all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
559 # _c_helper_resolve_field_names
561 def get_expr_fields(self):
563 get the Fields referenced by switch or list expression
565 def get_expr_field_names(expr):
567 if expr.lenfield_name is not None:
568 return [expr.lenfield_name]
570 # constant value expr
574 return get_expr_field_names(expr.rhs)
575 elif expr.op == 'popcount':
576 return get_expr_field_names(expr.rhs)
577 elif expr.op == 'sumof':
578 # sumof expr references another list,
579 # we need that list's length field here
581 for f in expr.lenfield_parent.fields:
582 if f.field_name == expr.lenfield_name:
586 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
587 # referenced list + its length field
588 return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
589 elif expr.op == 'enumref':
592 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
593 # get_expr_field_names()
595 # resolve the field names with the parent structure(s)
596 unresolved_fields_names = get_expr_field_names(self.expr)
598 # construct prefix from self
599 prefix = [('', '', p) for p in self.parents]
600 if self.is_container:
601 prefix.append(('', '', self))
603 all_fields = _c_helper_resolve_field_names (prefix)
604 resolved_fields_names = list(filter(lambda x: x in all_fields.keys(), unresolved_fields_names))
605 if len(unresolved_fields_names) != len(resolved_fields_names):
606 raise Exception("could not resolve all fields for %s" % self.name)
608 resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
609 return resolved_fields
612 def resolve_expr_fields(complex_obj):
614 find expr fields appearing in complex_obj and descendents that cannot be resolved within complex_obj
615 these are normally fields that need to be given as function parameters
621 for field in complex_obj.fields:
622 all_fields.append(field)
623 if field.type.is_switch or field.type.is_list:
624 expr_fields += get_expr_fields(field.type)
625 if field.type.is_container:
626 expr_fields += resolve_expr_fields(field.type)
628 # try to resolve expr fields
629 for e in expr_fields:
630 if e not in all_fields and e not in unresolved:
633 # resolve_expr_fields()
635 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
637 functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
638 E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch
639 expression. This function tries to resolve all fields within a structure, and returns the
640 unresolved fields as the list of external parameters.
642 def add_param(params, param):
643 if param not in params:
646 # collect all fields into param_fields
650 for field in self.fields:
652 # the field should appear as a parameter in the function call
653 param_fields.append(field)
654 if field.wire and not field.auto:
655 if field.type.fixed_size() and not self.is_switch:
656 # field in the xcb_out structure
657 wire_fields.append(field)
658 # fields like 'pad0' are skipped!
660 # in case of switch, parameters always contain any fields referenced in the switch expr
661 # we do not need any variable size fields here, as the switch data type contains both
662 # fixed and variable size fields
664 param_fields = get_expr_fields(self)
666 # _serialize()/_unserialize()/_unpack() function parameters
667 # note: don't use set() for params, it is unsorted
670 # 1. the parameter for the void * buffer
671 if 'serialize' == context:
672 params.append(('void', '**', buffer_var))
673 elif context in ('unserialize', 'unpack', 'sizeof'):
674 params.append(('const void', '*', buffer_var))
676 # 2. any expr fields that cannot be resolved within self and descendants
677 unresolved_fields = resolve_expr_fields(self)
678 for f in unresolved_fields:
679 add_param(params, (f.c_field_type, '', f.c_field_name))
681 # 3. param_fields contain the fields necessary to evaluate the switch expr or any other fields
682 # that do not appear in the data type struct
683 for p in param_fields:
685 typespec = p.c_field_const_type
686 pointerspec = p.c_pointer
687 add_param(params, (typespec, pointerspec, p.c_field_name))
689 if p.visible and not p.wire and not p.auto:
690 typespec = p.c_field_type
692 add_param(params, (typespec, pointerspec, p.c_field_name))
695 if 'serialize' == context:
696 add_param(params, ('const %s' % self.c_type, '*', aux_var))
697 elif 'unserialize' == context:
698 add_param(params, ('%s' % self.c_type, '**', aux_var))
699 elif 'unpack' == context:
700 add_param(params, ('%s' % self.c_type, '*', aux_var))
702 # 5. switch contains all variable size fields as struct members
703 # for other data types though, these have to be supplied separately
704 # this is important for the special case of intermixed fixed and
705 # variable size fields
706 if not self.is_switch and 'serialize' == context:
707 for p in param_fields:
708 if not p.type.fixed_size():
709 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
711 return (param_fields, wire_fields, params)
712 # get_serialize_params()
714 def _c_serialize_helper_insert_padding(context, code_lines, space, postpone, is_case_or_bitcase):
715 code_lines.append('%s /* insert padding */' % space)
716 if is_case_or_bitcase:
718 '%s xcb_pad = -(xcb_block_len + xcb_padding_offset) & (xcb_align_to - 1);'
722 '%s xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
723 # code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
724 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
727 code_lines.append('%s if (0 != xcb_pad) {' % space)
729 if 'serialize' == context:
730 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
731 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
732 code_lines.append('%s xcb_parts_idx++;' % space)
733 elif context in ('unserialize', 'unpack', 'sizeof'):
734 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
736 code_lines.append('%s xcb_pad = 0;' % space)
737 code_lines.append('%s }' % space)
739 code_lines.append('%s xcb_block_len = 0;' % space)
740 if is_case_or_bitcase:
741 code_lines.append('%s xcb_padding_offset = 0;' % space)
743 # keep tracking of xcb_parts entries for serialize
745 # _c_serialize_helper_insert_padding()
747 def _c_serialize_helper_switch(context, self, complex_name,
748 code_lines, temp_vars,
751 switch_expr = _c_accessor_get_expr(self.expr, None)
753 for b in self.bitcases:
754 len_expr = len(b.type.expr)
756 compare_operator = '&'
758 compare_operator = '=='
760 compare_operator = '&'
762 for n, expr in enumerate(b.type.expr):
763 bitcase_expr = _c_accessor_get_expr(expr, None)
764 # only one <enumref> in the <bitcase>
767 ' if(%s %s %s) {' % (switch_expr, compare_operator, bitcase_expr))
768 # multiple <enumref> in the <bitcase>
771 ' if((%s %s %s) ||' % (switch_expr, compare_operator, bitcase_expr))
772 elif len_expr == (n + 1): # last
774 ' (%s %s %s)) {' % (switch_expr, compare_operator, bitcase_expr))
775 else: # between first and last
777 ' (%s %s %s) ||' % (switch_expr, compare_operator, bitcase_expr))
781 b_prefix = prefix + [(b.c_field_name, '.', b.type)]
783 count += _c_serialize_helper_fields(context, b.type,
784 code_lines, temp_vars,
787 is_case_or_bitcase = True)
788 code_lines.append(' }')
790 # if 'serialize' == context:
791 # count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
792 # elif context in ('unserialize', 'unpack', 'sizeof'):
794 # code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
795 # code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
798 # _c_serialize_helper_switch
800 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
802 handle switch by calling _serialize() or _unpack(), depending on context
804 # switch is handled by this function as a special case
805 param_fields, wire_fields, params = get_serialize_params(context, self)
806 field_mapping = _c_helper_field_mapping(self, prefix)
807 prefix_str = _c_helper_absolute_name(prefix)
809 # find the parameters that need to be passed to _serialize()/_unpack():
810 # all switch expr fields must be given as parameters
811 args = get_expr_fields(field.type)
812 # length fields for variable size types in switch, normally only some of need
813 # need to be passed as parameters
814 switch_len_fields = resolve_expr_fields(field.type)
816 # a switch field at this point _must_ be a bitcase field
817 # we require that bitcases are "self-contiguous"
818 bitcase_unresolved = resolve_expr_fields(self)
819 if len(bitcase_unresolved) != 0:
820 raise Exception('unresolved fields within bitcase is not supported at this point')
822 # get the C names for the parameters
824 for a in switch_len_fields:
825 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
827 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
829 # call _serialize()/_unpack() to determine the actual size
830 if 'serialize' == context:
831 length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
832 c_field_names, prefix_str, field.c_field_name)
833 elif context in ('unserialize', 'unpack'):
834 length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
835 c_field_names, prefix_str, field.c_field_name)
836 elif 'sizeof' == context:
837 # remove trailing ", " from c_field_names because it will be used at end of arglist
838 my_c_field_names = c_field_names[:-2]
839 length = "%s(xcb_tmp, %s)" % (field.type.c_sizeof_name, my_c_field_names)
842 # _c_serialize_helper_switch_field()
844 def _c_serialize_helper_list_field(context, self, field,
845 code_lines, temp_vars,
848 helper function to cope with lists of variable length
850 expr = field.type.expr
851 prefix_str = _c_helper_absolute_name(prefix)
852 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
853 param_names = [p[2] for p in params]
855 expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
856 resolved = list(filter(lambda x: x in param_names, expr_fields_names))
857 unresolved = list(filter(lambda x: x not in param_names, expr_fields_names))
861 field_mapping[r] = (r, None)
863 if len(unresolved)>0:
865 if len(tmp_prefix)==0:
866 raise Exception("found an empty prefix while resolving expr field names for list %s",
869 field_mapping.update(_c_helper_resolve_field_names(prefix))
870 resolved += list(filter(lambda x: x in field_mapping, unresolved))
871 unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
872 if len(unresolved)>0:
873 raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
875 list_length = _c_accessor_get_expr(expr, field_mapping)
877 # default: list with fixed size elements
878 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
880 # list with variable-sized elements
881 if not field.type.member.fixed_size():
883 if context in ('unserialize', 'sizeof', 'unpack'):
884 int_i = ' unsigned int i;'
885 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
886 if int_i not in temp_vars:
887 temp_vars.append(int_i)
888 if xcb_tmp_len not in temp_vars:
889 temp_vars.append(xcb_tmp_len)
890 # loop over all list elements and call sizeof repeatedly
891 # this should be a bit faster than using the iterators
892 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
893 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
894 (space, field.type.c_sizeof_name))
895 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
896 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
897 code_lines.append("%s }" % space)
899 elif 'serialize' == context:
900 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
901 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
902 code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length))
903 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
904 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
905 code_lines.append('%s }' % space)
906 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
909 # _c_serialize_helper_list_field()
911 def _c_serialize_helper_fields_fixed_size(context, self, field,
912 code_lines, temp_vars,
914 # keep the C code a bit more readable by giving the field name
915 if not self.is_case_or_bitcase:
916 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
918 scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
919 typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
920 code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
922 abs_field_name = _c_helper_absolute_name(prefix, field)
923 # default for simple cases: call sizeof()
924 length = "sizeof(%s)" % field.c_field_type
926 if context in ('unserialize', 'unpack', 'sizeof'):
927 # default: simple cast
928 value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
930 # padding - we could probably just ignore it
931 if field.type.is_pad and field.type.nmemb > 1:
933 for i in range(field.type.nmemb):
934 code_lines.append('%s %s[%d] = *(%s *)xcb_tmp;' %
935 (space, abs_field_name, i, field.c_field_type))
936 # total padding = sizeof(pad0) * nmemb
937 length += " * %d" % field.type.nmemb
939 elif field.type.is_list:
940 # list with fixed number of elements
941 # length of array = sizeof(arrayElementType) * nmemb
942 length += " * %d" % field.type.nmemb
943 # use memcpy because C cannot assign whole arrays with operator=
944 value = ' memcpy(%s, xcb_tmp, %s);' % (abs_field_name, length)
947 elif 'serialize' == context:
948 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
950 if field.type.is_expr:
951 # need to register a temporary variable for the expression in case we know its type
952 if field.type.c_type is None:
953 raise Exception("type for field '%s' (expression '%s') unkown" %
954 (field.field_name, _c_accessor_get_expr(field.type.expr)))
956 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
957 _c_accessor_get_expr(field.type.expr, prefix)))
958 value += "&xcb_expr_%s;" % _cpp(field.field_name)
960 elif field.type.is_pad:
961 if field.type.nmemb == 1:
964 # we could also set it to 0, see definition of xcb_send_request()
965 value = ' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
966 length += "*%d" % field.type.nmemb
969 # non-list type with fixed size
970 if field.type.nmemb == 1:
971 value += "&%s;" % (abs_field_name)
973 # list with nmemb (fixed size) elements
975 value += '%s;' % (abs_field_name)
976 length = '%d' % field.type.nmemb
978 return (value, length)
979 # _c_serialize_helper_fields_fixed_size()
981 def _c_serialize_helper_fields_variable_size(context, self, field,
982 code_lines, temp_vars,
984 prefix_str = _c_helper_absolute_name(prefix)
986 if context in ('unserialize', 'unpack', 'sizeof'):
988 var_field_name = 'xcb_tmp'
990 # special case: intermixed fixed and variable size fields
991 if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
992 value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
993 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
994 # special case: switch
995 if 'unpack' == context:
996 value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
998 elif 'serialize' == context:
999 # variable size fields appear as parameters to _serialize() if the
1000 # 'toplevel' container is not a switch
1001 prefix_string = prefix_str if prefix[0][2].is_switch else ''
1002 var_field_name = "%s%s" % (prefix_string, field.c_field_name)
1003 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
1007 code_lines.append('%s /* %s */' % (space, field.c_field_name))
1009 if field.type.is_list:
1011 # in any context, list is already a pointer, so the default assignment is ok
1012 code_lines.append("%s%s" % (space, value))
1014 length = _c_serialize_helper_list_field(context, self, field,
1015 code_lines, temp_vars,
1018 elif field.type.is_switch:
1020 if context == 'serialize':
1021 # the _serialize() function allocates the correct amount memory if given a NULL pointer
1022 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
1023 length = _c_serialize_helper_switch_field(context, self, field,
1024 'xcb_parts[xcb_parts_idx].iov_base',
1028 # in all remaining special cases - call _sizeof()
1029 length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
1031 return (value, length)
1032 # _c_serialize_helper_fields_variable_size
1034 def _c_serialize_helper_fields(context, self,
1035 code_lines, temp_vars,
1036 space, prefix, is_case_or_bitcase):
1038 need_padding = False
1039 prev_field_was_variable = False
1041 for field in self.fields:
1042 if not field.visible:
1043 if not ((field.wire and not field.auto) or 'unserialize' == context):
1046 # switch/bitcase: fixed size fields must be considered explicitly
1047 if field.type.fixed_size():
1048 if self.is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
1049 if prev_field_was_variable and need_padding:
1051 # count += _c_serialize_helper_insert_padding(context, code_lines, space,
1052 # self.c_var_followed_by_fixed_fields)
1053 prev_field_was_variable = False
1055 # prefix for fixed size fields
1056 fixed_prefix = prefix
1058 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
1059 code_lines, temp_vars,
1060 space, fixed_prefix)
1064 # fields with variable size
1066 if field.type.is_pad:
1067 # Variable length pad is <pad align= />
1068 code_lines.append('%s xcb_align_to = %d;' % (space, field.type.align))
1069 count += _c_serialize_helper_insert_padding(context, code_lines, space,
1070 self.c_var_followed_by_fixed_fields,
1074 # switch/bitcase: always calculate padding before and after variable sized fields
1075 if need_padding or is_case_or_bitcase:
1076 count += _c_serialize_helper_insert_padding(context, code_lines, space,
1077 self.c_var_followed_by_fixed_fields,
1080 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
1081 code_lines, temp_vars,
1083 prev_field_was_variable = True
1085 # save (un)serialization C code
1087 code_lines.append('%s%s' % (space, value))
1089 if field.type.fixed_size():
1090 if is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
1091 # keep track of (un)serialized object's size
1092 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1093 if context in ('unserialize', 'unpack', 'sizeof'):
1094 code_lines.append('%s xcb_tmp += %s;' % (space, length))
1096 # variable size objects or bitcase:
1097 # value & length might have been inserted earlier for special cases
1099 # special case: intermixed fixed and variable size fields
1100 if (not field.type.fixed_size() and
1101 self.c_var_followed_by_fixed_fields and 'unserialize' == context):
1102 temp_vars.append(' int %s_len;' % field.c_field_name)
1103 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
1104 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
1105 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
1107 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1108 # increase pointer into the byte stream accordingly
1109 if context in ('unserialize', 'sizeof', 'unpack'):
1110 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1112 if 'serialize' == context:
1114 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
1115 code_lines.append('%s xcb_parts_idx++;' % space)
1119 '%s xcb_align_to = ALIGNOF(%s);'
1122 if field.c_field_type == 'void' or field.type.is_switch
1123 else field.c_field_type))
1126 if self.c_var_followed_by_fixed_fields:
1127 need_padding = False
1130 # _c_serialize_helper_fields()
1132 def _c_serialize_helper(context, complex_type,
1133 code_lines, temp_vars,
1134 space='', prefix=[]):
1135 # count tracks the number of fields to serialize
1138 if hasattr(complex_type, 'type'):
1139 self = complex_type.type
1140 complex_name = complex_type.name
1143 if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
1144 complex_name = 'xcb_out'
1146 complex_name = '_aux'
1148 # special case: switch is serialized by evaluating each bitcase separately
1150 count += _c_serialize_helper_switch(context, self, complex_name,
1151 code_lines, temp_vars,
1154 # all other data types can be evaluated one field a time
1156 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1157 if context in ('unserialize', 'unpack', 'sizeof') and not self.c_var_followed_by_fixed_fields:
1158 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1159 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1160 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
1161 code_lines.append('%s xcb_block_len = 0;' % space)
1163 count += _c_serialize_helper_fields(context, self,
1164 code_lines, temp_vars,
1165 space, prefix, False)
1167 count += _c_serialize_helper_insert_padding(context, code_lines, space, False, self.is_switch)
1170 # _c_serialize_helper()
1172 def _c_serialize(context, self):
1174 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1175 for the ComplexType variable self
1181 # _serialize() returns the buffer size
1184 if self.is_switch and 'unserialize' == context:
1187 cases = { 'serialize' : self.c_serialize_name,
1188 'unserialize' : self.c_unserialize_name,
1189 'unpack' : self.c_unpack_name,
1190 'sizeof' : self.c_sizeof_name }
1191 func_name = cases[context]
1193 param_fields, wire_fields, params = get_serialize_params(context, self)
1194 variable_size_fields = 0
1195 # maximum space required for type definition of function arguments
1198 # determine N(variable_fields)
1199 for field in param_fields:
1200 # if self.is_switch, treat all fields as if they are variable sized
1201 if not field.type.fixed_size() or self.is_switch:
1202 variable_size_fields += 1
1203 # determine maxtypelen
1205 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1208 indent = ' '*(len(func_name)+2)
1211 typespec, pointerspec, field_name = p
1212 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1213 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1214 # insert function name
1215 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1216 param_str = list(map(lambda x: "%s," % x, param_str))
1217 for s in param_str[:-1]:
1219 _h("%s);" % param_str[-1].rstrip(','))
1220 _c("%s)" % param_str[-1].rstrip(','))
1227 if 'serialize' == context:
1228 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1229 _c(' %s *xcb_out = *_buffer;', self.c_type)
1230 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1231 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1232 _c(' unsigned int xcb_align_to = 0;')
1234 _c(' char *xcb_out = *_buffer;')
1235 _c(' unsigned int xcb_buffer_len = 0;')
1236 _c(' unsigned int xcb_align_to = 0;')
1238 _c(' unsigned int xcb_padding_offset = ((size_t)xcb_out) & 7;')
1239 prefix = [('_aux', '->', self)]
1242 elif context in ('unserialize', 'unpack'):
1243 _c(' char *xcb_tmp = (char *)_buffer;')
1244 if not self.is_switch:
1245 if not self.c_var_followed_by_fixed_fields:
1246 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1247 prefix = [('_aux', '->', self)]
1249 _c(' %s xcb_out;', self.c_type)
1250 prefix = [('xcb_out', '.', self)]
1252 aux_var = '_aux' # default for unpack: single pointer
1253 # note: unserialize not generated for switch
1254 if 'unserialize' == context:
1255 aux_var = '(*_aux)' # unserialize: double pointer (!)
1256 prefix = [(aux_var, '->', self)]
1258 _c(' unsigned int xcb_buffer_len = 0;')
1259 _c(' unsigned int xcb_block_len = 0;')
1260 _c(' unsigned int xcb_pad = 0;')
1261 _c(' unsigned int xcb_align_to = 0;')
1263 _c(' unsigned int xcb_padding_offset = ((size_t)_buffer) & 7;')
1265 elif 'sizeof' == context:
1266 param_names = [p[2] for p in params]
1268 # switch: call _unpack()
1269 _c(' %s _aux;', self.c_type)
1270 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1273 elif self.c_var_followed_by_fixed_fields:
1274 # special case: call _unserialize()
1275 _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1279 _c(' char *xcb_tmp = (char *)_buffer;')
1280 prefix = [('_aux', '->', self)]
1282 _c(' unsigned int xcb_padding_offset = 0;')
1284 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1285 # update variable size fields (only important for context=='serialize'
1286 variable_size_fields = count
1287 if 'serialize' == context:
1288 temp_vars.append(' unsigned int xcb_pad = 0;')
1289 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1290 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1291 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1292 temp_vars.append(' unsigned int xcb_block_len = 0;')
1293 temp_vars.append(' unsigned int i;')
1294 temp_vars.append(' char *xcb_tmp;')
1295 elif 'sizeof' == context:
1296 # neither switch nor intermixed fixed and variable size fields:
1297 # evaluate parameters directly
1298 if not (self.is_switch or self.c_var_followed_by_fixed_fields):
1300 # look if we have to declare an '_aux' variable at all
1301 if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
1302 if not self.c_var_followed_by_fixed_fields:
1303 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1305 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1307 _c(' unsigned int xcb_buffer_len = 0;')
1308 _c(' unsigned int xcb_block_len = 0;')
1309 _c(' unsigned int xcb_pad = 0;')
1310 _c(' unsigned int xcb_align_to = 0;')
1316 for l in code_lines:
1319 # variable sized fields have been collected, now
1320 # allocate memory and copy everything into a continuous memory area
1321 # note: this is not necessary in case of unpack
1322 if context in ('serialize', 'unserialize'):
1323 # unserialize: check for sizeof-only invocation
1324 if 'unserialize' == context:
1326 _c(' if (NULL == _aux)')
1327 _c(' return xcb_buffer_len;')
1330 _c(' if (NULL == %s) {', aux_ptr)
1331 _c(' /* allocate memory */')
1332 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1333 if 'serialize' == context:
1334 _c(' *_buffer = xcb_out;')
1338 # serialize: handle variable size fields in a loop
1339 if 'serialize' == context:
1340 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1341 if len(wire_fields)>0:
1342 _c(' *xcb_out = *_aux;')
1343 # copy variable size fields into the buffer
1344 if variable_size_fields > 0:
1346 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1347 _c(' xcb_tmp = (char*)++xcb_out;')
1348 _c(' xcb_tmp += xcb_out_pad;')
1350 _c(' xcb_tmp = xcb_out;')
1352 # variable sized fields
1353 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1354 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1355 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1356 _c(' if (0 != xcb_parts[i].iov_len)')
1357 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1360 # unserialize: assign variable size fields individually
1361 if 'unserialize' == context:
1362 _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1363 param_fields.reverse()
1364 for field in param_fields:
1365 if not field.type.fixed_size():
1366 _c(' xcb_tmp -= %s_len;', field.c_field_name)
1367 _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1368 _c(' *%s = xcb_out;', aux_ptr)
1371 _c(' return xcb_buffer_len;')
1375 def _c_iterator_get_end(field, accum):
1377 Figures out what C code is needed to find the end of a variable-length structure field.
1378 For nested structures, recurses into its last variable-sized field.
1379 For lists, calls the end function
1381 if field.type.is_container:
1382 accum = field.c_accessor_name + '(' + accum + ')'
1383 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1384 if field.type.is_list:
1385 # XXX we can always use the first way
1386 if field.type.member.is_simple:
1387 return field.c_end_name + '(' + accum + ')'
1389 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1391 def _c_iterator(self, name):
1393 Declares the iterator structure and next/end functions for a given type.
1398 _h(' * @brief %s', self.c_iterator_type)
1400 _h('typedef struct %s {', self.c_iterator_type)
1401 _h(' %s *data; /**< */', self.c_type)
1402 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1403 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1404 _h('} %s;', self.c_iterator_type)
1410 _h(' * Get the next element of the iterator')
1411 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1413 _h(' * Get the next element in the iterator. The member rem is')
1414 _h(' * decreased by one. The member data points to the next')
1415 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1419 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1420 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1423 if not self.fixed_size():
1424 _c(' %s *R = i->data;', self.c_type)
1427 # FIXME - how to determine the size of a variable size union??
1428 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1430 if self.c_need_sizeof:
1431 _c(' xcb_generic_iterator_t child;')
1432 _c(' child.data = (%s *)(((char *)R) + %s(R));',
1433 self.c_type, self.c_sizeof_name)
1434 _c(' i->index = (char *) child.data - (char *) i->data;')
1436 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1437 _c(' i->index = child.index;')
1439 _c(' i->data = (%s *) child.data;', self.c_type)
1444 _c(' i->index += sizeof(%s);', self.c_type)
1450 _h(' * Return the iterator pointing to the last element')
1451 _h(' * @param i An %s', self.c_iterator_type)
1452 _h(' * @return The iterator pointing to the last element')
1454 _h(' * Set the current element in the iterator to the last element.')
1455 _h(' * The member rem is set to 0. The member data points to the')
1456 _h(' * last element.')
1459 _hc('xcb_generic_iterator_t')
1460 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1461 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1463 _c(' xcb_generic_iterator_t ret;')
1465 if self.fixed_size():
1466 _c(' ret.data = i.data + i.rem;')
1467 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1470 _c(' while(i.rem > 0)')
1471 _c(' %s(&i);', self.c_next_name)
1472 _c(' ret.data = i.data;')
1473 _c(' ret.rem = i.rem;')
1474 _c(' ret.index = i.index;')
1479 def _c_accessor_get_length(expr, field_mapping=None):
1481 Figures out what C code is needed to get a length field.
1482 The field_mapping parameter can be used to change the absolute name of a length field.
1483 For fields that follow a variable-length field, use the accessor.
1484 Otherwise, just reference the structure field directly.
1487 lenfield_name = expr.lenfield_name
1488 if lenfield_name is not None:
1489 if field_mapping is not None:
1490 lenfield_name = field_mapping[lenfield_name][0]
1492 if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1493 # special case: variable and fixed size fields are intermixed
1494 # if the lenfield is among the fixed size fields, there is no need
1495 # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1496 return field_mapping(expr.lenfield_name)
1497 elif expr.lenfield_name is not None:
1498 return lenfield_name
1500 return str(expr.nmemb)
1502 def _c_accessor_get_expr(expr, field_mapping):
1504 Figures out what C code is needed to get the length of a list field.
1505 The field_mapping parameter can be used to change the absolute name of a length field.
1506 Recurses for math operations.
1507 Returns bitcount for value-mask fields.
1508 Otherwise, uses the value of the length field.
1510 lenexp = _c_accessor_get_length(expr, field_mapping)
1513 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1514 elif expr.op == 'popcount':
1515 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1516 elif expr.op == 'enumref':
1517 enum_name = expr.lenfield_type.name
1518 constant_name = expr.lenfield_name
1519 c_name = _n(enum_name + (constant_name,)).upper()
1521 elif expr.op == 'sumof':
1522 # locate the referenced list object
1523 list_obj = expr.lenfield_type
1525 for f in expr.lenfield_parent.fields:
1526 if f.field_name == expr.lenfield_name:
1531 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1532 list_name = field_mapping[field.c_field_name][0]
1533 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1534 # note: xcb_sumof() has only been defined for integers
1535 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1536 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1537 elif expr.op != None:
1538 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1539 ' ' + expr.op + ' ' +
1540 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1542 return 'xcb_popcount(' + lenexp + ')'
1546 def type_pad_type(type):
1551 def _c_accessors_field(self, field):
1553 Declares the accessor functions for a non-list field that follows a variable-length field.
1555 c_type = self.c_type
1557 # special case: switch
1558 switch_obj = self if self.is_switch else None
1559 if self.is_case_or_bitcase:
1560 switch_obj = self.parents[-1]
1561 if switch_obj is not None:
1562 c_type = switch_obj.c_type
1564 if field.type.is_simple:
1566 _hc('%s', field.c_field_type)
1567 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1568 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1570 if field.prev_varsized_field is None:
1571 _c(' return (%s *) (R + 1);', field.c_field_type)
1573 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1574 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1575 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1579 if field.type.is_switch and switch_obj is None:
1580 return_type = 'void *'
1582 return_type = '%s *' % field.c_field_type
1585 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1586 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1588 if field.prev_varsized_field is None:
1589 _c(' return (%s) (R + 1);', return_type)
1590 # note: the special case 'variable fields followed by fixed size fields'
1591 # is not of any consequence here, since the ordering gets
1592 # 'corrected' in the reply function
1594 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1595 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1596 return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1600 def _c_accessors_list(self, field):
1602 Declares the accessor functions for a list field.
1603 Declares a direct-accessor function only if the list members are fixed size.
1604 Declares length and get-iterator functions always.
1607 def get_align_pad(field):
1608 prev = field.prev_varsized_field
1609 prev_prev = field.prev_varsized_field.prev_varsized_field
1611 if (prev.type.is_pad and prev.type.align > 0 and prev_prev is not None):
1612 return (prev_prev, '((-prev.index) & (%d - 1))' % prev.type.align)
1618 c_type = self.c_type
1620 # special case: switch
1621 # in case of switch, 2 params have to be supplied to certain accessor functions:
1622 # 1. the anchestor object (request or reply)
1623 # 2. the (anchestor) switch object
1624 # the reason is that switch is either a child of a request/reply or nested in another switch,
1625 # so whenever we need to access a length field, we might need to refer to some anchestor type
1626 switch_obj = self if self.is_switch else None
1627 if self.is_case_or_bitcase:
1628 switch_obj = self.parents[-1]
1629 if switch_obj is not None:
1630 c_type = switch_obj.c_type
1634 parents = self.parents if hasattr(self, 'parents') else [self]
1635 # 'R': parents[0] is always the 'toplevel' container type
1636 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1637 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1638 # auxiliary object for 'R' parameters
1641 if switch_obj is not None:
1642 # now look where the fields are defined that are needed to evaluate
1643 # the switch expr, and store the parent objects in accessor_params and
1644 # the fields in switch_fields
1646 # 'S': name for the 'toplevel' switch
1647 toplevel_switch = parents[1]
1648 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1649 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1651 # initialize prefix for everything "below" S
1652 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1653 prefix = [(prefix_str, '->', toplevel_switch)]
1655 # look for fields in the remaining containers
1656 for p in parents[2:] + [self]:
1657 # the separator between parent and child is always '.' here,
1658 # because of nested switch statements
1659 if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
1660 prefix.append((p.name[-1], '.', p))
1661 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1663 # auxiliary object for 'S' parameter
1668 if list.member.fixed_size():
1669 idx = 1 if switch_obj is not None else 0
1671 _hc('%s *', field.c_field_type)
1673 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1674 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1677 if switch_obj is not None:
1678 _c(' return %s;', fields[field.c_field_name][0])
1679 elif field.prev_varsized_field is None:
1680 _c(' return (%s *) (R + 1);', field.c_field_type)
1682 (prev_varsized_field, align_pad) = get_align_pad(field)
1684 if align_pad is None:
1685 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
1686 type_pad_type(field.first_field_after_varsized.type.c_type))
1688 _c(' xcb_generic_iterator_t prev = %s;',
1689 _c_iterator_get_end(prev_varsized_field, 'R'))
1690 _c(' return (%s *) ((char *) prev.data + %s + %d);',
1691 field.c_field_type, align_pad, field.prev_varsized_offset)
1696 if switch_obj is not None:
1697 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1698 spacing = ' '*(len(field.c_length_name)+2)
1699 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1700 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1701 length = _c_accessor_get_expr(field.type.expr, fields)
1703 _h('%s (const %s *R /**< */);', field.c_length_name, c_type)
1704 _c('%s (const %s *R /**< */)', field.c_length_name, c_type)
1705 length = _c_accessor_get_expr(field.type.expr, fields)
1707 _c(' return %s;', length)
1710 if field.type.member.is_simple:
1712 _hc('xcb_generic_iterator_t')
1713 if switch_obj is not None:
1714 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1715 spacing = ' '*(len(field.c_end_name)+2)
1716 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1717 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1719 _h('%s (const %s *R /**< */);', field.c_end_name, c_type)
1720 _c('%s (const %s *R /**< */)', field.c_end_name, c_type)
1722 _c(' xcb_generic_iterator_t i;')
1724 param = 'R' if switch_obj is None else 'S'
1725 if switch_obj is not None:
1726 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1727 _c_accessor_get_expr(field.type.expr, fields))
1728 elif field.prev_varsized_field == None:
1729 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1730 _c_accessor_get_expr(field.type.expr, fields))
1732 _c(' xcb_generic_iterator_t child = %s;',
1733 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1734 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1735 _c_accessor_get_expr(field.type.expr, fields))
1738 _c(' i.index = (char *) i.data - (char *) %s;', param)
1744 _hc('%s', field.c_iterator_type)
1745 if switch_obj is not None:
1746 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1747 spacing = ' '*(len(field.c_iterator_name)+2)
1748 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1749 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1751 _h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
1752 _c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
1754 _c(' %s i;', field.c_iterator_type)
1756 if switch_obj is not None:
1757 _c(' i.data = %s;', fields[field.c_field_name][0])
1758 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1759 elif field.prev_varsized_field == None:
1760 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1762 (prev_varsized_field, align_pad) = get_align_pad(field)
1764 if align_pad is None:
1765 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
1766 type_pad_type(field.c_field_type))
1768 _c(' xcb_generic_iterator_t prev = %s;',
1769 _c_iterator_get_end(prev_varsized_field, 'R'))
1770 _c(' i.data = (%s *) ((char *) prev.data + %s);',
1771 field.c_field_type, align_pad)
1773 if switch_obj is None:
1774 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1775 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1779 def _c_accessors(self, name, base):
1781 Declares the accessor functions for the fields of a structure.
1783 # no accessors for switch itself -
1784 # switch always needs to be unpacked explicitly
1785 # if self.is_switch:
1789 for field in self.fields:
1790 if not field.type.is_pad:
1791 if _c_field_needs_list_accessor(field):
1792 _c_accessors_list(self, field)
1793 elif _c_field_needs_field_accessor(field):
1794 _c_accessors_field(self, field)
1796 def c_simple(self, name):
1798 Exported function that handles cardinal type declarations.
1799 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1801 _c_type_setup(self, name, ())
1803 if (self.name != name):
1808 _h('typedef %s %s;', _t(self.name), my_name)
1811 _c_iterator(self, name)
1813 def _c_complex(self, force_packed = False):
1815 Helper function for handling all structure types.
1816 Called for all structs, requests, replies, events, errors.
1821 _h(' * @brief %s', self.c_type)
1823 _h('typedef %s %s {', self.c_container, self.c_type)
1829 for field in self.fields:
1830 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1831 varfield = field.c_field_name
1834 struct_fields.append(field)
1836 for field in struct_fields:
1837 length = len(field.c_field_type)
1838 # account for '*' pointer_spec
1839 if not field.type.fixed_size() and not self.is_union:
1841 maxtypelen = max(maxtypelen, length)
1843 def _c_complex_field(self, field, space=''):
1844 if (field.type.fixed_size() or self.is_union or
1845 # in case of switch with switch children, don't make the field a pointer
1846 # necessary for unserialize to work
1847 (self.is_switch and field.type.is_switch)):
1848 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1849 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1851 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1852 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1854 if not self.is_switch:
1855 for field in struct_fields:
1856 _c_complex_field(self, field)
1858 for b in self.bitcases:
1863 for field in b.type.fields:
1864 _c_complex_field(self, field, space)
1866 _h(' } %s;', b.c_field_name)
1868 _h('} %s%s;', 'XCB_PACKED ' if force_packed else '', self.c_type)
1870 def c_struct(self, name):
1872 Exported function that handles structure declarations.
1874 _c_type_setup(self, name, ())
1876 _c_accessors(self, name, name)
1877 _c_iterator(self, name)
1879 def c_union(self, name):
1881 Exported function that handles union declarations.
1883 _c_type_setup(self, name, ())
1885 _c_iterator(self, name)
1887 def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_fds=False):
1889 Declares a request function.
1892 # Four stunningly confusing possibilities here:
1895 # ------------------------------
1897 # 0 flag CHECKED flag Normal Mode
1898 # void_cookie req_cookie
1899 # ------------------------------
1900 # "req_checked" "req_unchecked"
1901 # CHECKED flag 0 flag Abnormal Mode
1902 # void_cookie req_cookie
1903 # ------------------------------
1906 # Whether we are _checked or _unchecked
1907 checked = void and not regular
1908 unchecked = not void and not regular
1910 # What kind of cookie we return
1911 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1913 # What flag is passed to xcb_request
1914 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1917 if func_flags == '0':
1918 func_flags = 'XCB_REQUEST_REPLY_FDS'
1920 func_flags = func_flags + '|XCB_REQUEST_REPLY_FDS'
1922 # Global extension id variable or NULL for xproto
1923 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1925 # What our function name is
1926 func_name = self.c_request_name if not aux else self.c_aux_name
1928 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1930 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1934 maxtypelen = len('xcb_connection_t')
1936 # special case: list with variable size elements
1937 list_with_var_size_elems = False
1939 for field in self.fields:
1941 # The field should appear as a call parameter
1942 param_fields.append(field)
1943 if field.wire and not field.auto:
1944 # We need to set the field up in the structure
1945 wire_fields.append(field)
1946 if field.type.c_need_serialize or field.type.c_need_sizeof:
1947 serial_fields.append(field)
1949 for field in param_fields:
1950 c_field_const_type = field.c_field_const_type
1951 if field.type.c_need_serialize and not aux:
1952 c_field_const_type = "const void"
1953 if len(c_field_const_type) > maxtypelen:
1954 maxtypelen = len(c_field_const_type)
1955 if field.type.is_list and not field.type.member.fixed_size():
1956 list_with_var_size_elems = True
1962 if hasattr(self, "doc") and self.doc:
1964 _h(' * @brief ' + self.doc.brief)
1966 _h(' * No brief doc yet')
1969 _h(' * @param c The connection')
1970 param_names = [f.c_field_name for f in param_fields]
1971 if hasattr(self, "doc") and self.doc:
1972 for field in param_fields:
1973 # XXX: hard-coded until we fix xproto.xml
1974 base_func_name = self.c_request_name if not aux else self.c_aux_name
1975 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
1977 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
1979 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
1982 # XXX: why the 'xcb' prefix?
1983 key = ('xcb', field.enum)
1986 if namecount[tname] > 1:
1987 tname = _t(key + ('enum',))
1988 _h(' * @param %s A bitmask of #%s values.' % (field.c_field_name, tname))
1990 if self.doc and field.field_name in self.doc.fields:
1991 desc = self.doc.fields[field.field_name]
1992 for name in param_names:
1993 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1994 desc = desc.split("\n")
1995 desc = [line if line != '' else '\\n' for line in desc]
1996 _h(' * @param %s %s' % (field.c_field_name, "\n * ".join(desc)))
1997 # If there is no documentation yet, we simply don't generate an
1998 # @param tag. Doxygen will then warn about missing documentation.
2000 _h(' * @return A cookie')
2003 if hasattr(self, "doc") and self.doc:
2004 if self.doc.description:
2005 desc = self.doc.description
2006 for name in param_names:
2007 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
2008 desc = desc.split("\n")
2009 _h(' * ' + "\n * ".join(desc))
2011 _h(' * No description yet')
2013 _h(' * Delivers a request to the X server.')
2016 _h(' * This form can be used only if the request will not cause')
2017 _h(' * a reply to be generated. Any returned error will be')
2018 _h(' * saved for handling by xcb_request_check().')
2020 _h(' * This form can be used only if the request will cause')
2021 _h(' * a reply to be generated. Any returned error will be')
2022 _h(' * placed in the event queue.')
2025 _hc('%s', cookie_type)
2027 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
2028 comma = ',' if len(param_fields) else ');'
2029 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
2030 comma = ',' if len(param_fields) else ')'
2031 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
2033 func_spacing = ' ' * (len(func_name) + 2)
2034 count = len(param_fields)
2035 for field in param_fields:
2037 c_field_const_type = field.c_field_const_type
2038 c_pointer = field.c_pointer
2039 if field.type.c_need_serialize and not aux:
2040 c_field_const_type = "const void"
2042 spacing = ' ' * (maxtypelen - len(c_field_const_type))
2043 comma = ',' if count else ');'
2044 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
2045 spacing, c_pointer, field.c_field_name, comma)
2046 comma = ',' if count else ')'
2047 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
2048 spacing, c_pointer, field.c_field_name, comma)
2051 if not self.c_var_followed_by_fixed_fields:
2052 for field in param_fields:
2053 if not field.type.fixed_size():
2055 if field.type.c_need_serialize:
2056 # _serialize() keeps track of padding automatically
2058 dimension = count + 2
2061 _c(' static const xcb_protocol_request_t xcb_req = {')
2062 _c(' /* count */ %d,', count)
2063 _c(' /* ext */ %s,', func_ext_global)
2064 _c(' /* opcode */ %s,', self.c_request_name.upper())
2065 _c(' /* isvoid */ %d', 1 if void else 0)
2069 _c(' struct iovec xcb_parts[%d];', dimension)
2070 _c(' %s xcb_ret;', func_cookie)
2071 _c(' %s xcb_out;', self.c_type)
2072 if self.c_var_followed_by_fixed_fields:
2073 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
2074 _c(' void *xcb_aux = 0;')
2077 for idx, f in enumerate(serial_fields):
2079 _c(' void *xcb_aux%d = 0;' % (idx))
2080 if list_with_var_size_elems:
2081 _c(' unsigned int i;')
2082 _c(' unsigned int xcb_tmp_len;')
2083 _c(' char *xcb_tmp;')
2085 # simple request call tracing
2086 # _c(' printf("in function %s\\n");' % func_name)
2089 for field in wire_fields:
2090 if field.type.fixed_size():
2091 if field.type.is_expr:
2092 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
2093 elif field.type.is_pad:
2094 if field.type.nmemb == 1:
2095 _c(' xcb_out.%s = 0;', field.c_field_name)
2097 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
2099 if field.type.nmemb == 1:
2100 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
2102 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
2104 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
2105 serialize_args = get_serialize_params(context, type_obj,
2108 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
2110 # calls in order to free dyn. all. memory
2114 if not self.c_var_followed_by_fixed_fields:
2115 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2116 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
2117 _c(' xcb_parts[3].iov_base = 0;')
2118 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2122 for field in param_fields:
2123 if not field.type.fixed_size():
2124 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
2125 # default: simple cast to char *
2126 if not field.type.c_need_serialize and not field.type.c_need_sizeof:
2127 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2128 if field.type.is_list:
2129 if field.type.member.fixed_size():
2130 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
2131 _c_accessor_get_expr(field.type.expr, None),
2132 field.type.member.c_wiretype)
2134 list_length = _c_accessor_get_expr(field.type.expr, None)
2137 _c(" xcb_parts[%d].iov_len = 0;" % count)
2138 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2139 _c(" for(i=0; i<%s; i++) {" % list_length)
2140 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2141 (field.type.c_sizeof_name))
2142 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2143 _c(" xcb_tmp += xcb_tmp_len;")
2146 # not supposed to happen
2147 raise Exception("unhandled variable size field %s" % field.c_field_name)
2150 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2151 idx = serial_fields.index(field)
2152 aux_var = '&xcb_aux%d' % idx
2153 context = 'serialize' if aux else 'sizeof'
2154 _c(' xcb_parts[%d].iov_len =', count)
2156 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2157 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2158 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2159 free_calls.append(' free(xcb_aux%d);' % idx)
2161 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2162 func_name = field.type.c_sizeof_name
2163 _c(' %s (%s);', func_name, serialize_args)
2166 if not (field.type.c_need_serialize or field.type.c_need_sizeof):
2167 # the _serialize() function keeps track of padding automatically
2168 _c(' xcb_parts[%d].iov_base = 0;', count)
2169 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2172 # elif self.c_var_followed_by_fixed_fields:
2174 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2175 # request header: opcodes + length
2176 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2179 buffer_var = '&xcb_aux'
2180 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2181 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2182 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2183 free_calls.append(' free(xcb_aux);')
2184 # no padding necessary - _serialize() keeps track of padding automatically
2187 for field in param_fields:
2189 _c(' xcb_send_fd(c, %s);', field.c_field_name)
2191 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2193 # free dyn. all. data, if any
2194 for f in free_calls:
2196 _c(' return xcb_ret;')
2199 def _c_reply(self, name):
2201 Declares the function that returns the reply structure.
2203 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2204 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2205 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2207 # check if _unserialize() has to be called for any field
2208 def look_for_special_cases(complex_obj):
2209 unserialize_fields = []
2210 # no unserialize call in case of switch
2211 if not complex_obj.is_switch:
2212 for field in complex_obj.fields:
2213 # three cases: 1. field with special case
2214 # 2. container that contains special case field
2215 # 3. list with special case elements
2216 if field.type.c_var_followed_by_fixed_fields:
2217 unserialize_fields.append(field)
2218 elif field.type.is_container:
2219 unserialize_fields += look_for_special_cases(field.type)
2220 elif field.type.is_list:
2221 if field.type.member.c_var_followed_by_fixed_fields:
2222 unserialize_fields.append(field)
2223 if field.type.member.is_container:
2224 unserialize_fields += look_for_special_cases(field.type.member)
2225 return unserialize_fields
2227 unserialize_fields = look_for_special_cases(self.reply)
2231 _h(' * Return the reply')
2232 _h(' * @param c The connection')
2233 _h(' * @param cookie The cookie')
2234 _h(' * @param e The xcb_generic_error_t supplied')
2236 _h(' * Returns the reply of the request asked by')
2238 _h(' * The parameter @p e supplied to this function must be NULL if')
2239 _h(' * %s(). is used.', self.c_unchecked_name)
2240 _h(' * Otherwise, it stores the error if any.')
2242 _h(' * The returned value must be freed by the caller using free().')
2245 _hc('%s *', self.c_reply_type)
2246 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2247 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2248 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2249 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2252 if len(unserialize_fields)>0:
2253 # certain variable size fields need to be unserialized explicitly
2254 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2255 self.c_reply_type, self.c_reply_type)
2257 for field in unserialize_fields:
2258 if field.type.is_list:
2259 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2260 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2261 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2263 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2264 # call _unserialize(), using the reply as source and target buffer
2265 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2266 for field in unserialize_fields:
2267 if field.type.is_list:
2268 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2269 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2270 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2271 field.c_field_name, field.c_field_name)
2272 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2274 # return the transformed reply
2275 _c(' return reply;')
2278 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2282 def _c_reply_has_fds(self):
2283 for field in self.fields:
2288 def _c_reply_fds(self, name):
2290 Declares the function that returns fds related to the reply.
2292 spacing1 = ' ' * (len(self.c_reply_type) - len('xcb_connection_t'))
2293 spacing3 = ' ' * (len(self.c_reply_fds_name) + 2)
2296 _h(' * Return the reply fds')
2297 _h(' * @param c The connection')
2298 _h(' * @param reply The reply')
2300 _h(' * Returns the array of reply fds of the request asked by')
2302 _h(' * The returned value must be freed by the caller using free().')
2306 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_fds_name, spacing1)
2307 _h('%s%s *reply /**< */);', spacing3, self.c_reply_type)
2308 _c('%s%s *reply /**< */)', spacing3, self.c_reply_type)
2311 _c(' return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
2316 def _c_opcode(name, opcode):
2318 Declares the opcode define for requests, events, and errors.
2322 _h('/** Opcode for %s. */', _n(name))
2323 _h('#define %s %s', _n(name).upper(), opcode)
2325 def _c_cookie(self, name):
2327 Declares the cookie type for a non-void request.
2332 _h(' * @brief %s', self.c_cookie_type)
2334 _h('typedef struct %s {', self.c_cookie_type)
2335 _h(' unsigned int sequence; /**< */')
2336 _h('} %s;', self.c_cookie_type)
2338 def _man_request(self, name, cookie_type, void, aux):
2339 param_fields = [f for f in self.fields if f.visible]
2341 func_name = self.c_request_name if not aux else self.c_aux_name
2343 def create_link(linkname):
2344 name = 'man/%s.%s' % (linkname, section)
2346 sys.stdout.write(name)
2348 f.write('.so man%s/%s.%s' % (section, func_name, section))
2352 sys.stdout.write('man/%s.%s ' % (func_name, section))
2353 # Our CWD is src/, so this will end up in src/man/
2354 f = open('man/%s.%s' % (func_name, section), 'w')
2355 f.write('.TH %s %s "%s" "%s" "XCB Requests"\n' % (func_name, section, center_footer, left_footer))
2356 # Left-adjust instead of adjusting to both sides
2358 f.write('.SH NAME\n')
2359 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2360 f.write('%s \\- %s\n' % (func_name, brief))
2361 f.write('.SH SYNOPSIS\n')
2362 # Don't split words (hyphenate)
2364 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2366 # function prototypes
2368 count = len(param_fields)
2369 for field in param_fields:
2371 c_field_const_type = field.c_field_const_type
2372 c_pointer = field.c_pointer
2373 if c_pointer == ' ':
2375 if field.type.c_need_serialize and not aux:
2376 c_field_const_type = "const void"
2378 comma = ', ' if count else ');'
2379 prototype += '%s\\ %s\\fI%s\\fP%s' % (c_field_const_type, c_pointer, field.c_field_name, comma)
2381 f.write('.SS Request function\n')
2383 base_func_name = self.c_request_name if not aux else self.c_aux_name
2384 f.write('%s \\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\n' % (cookie_type, base_func_name, prototype))
2385 create_link('%s_%s' % (base_func_name, ('checked' if void else 'unchecked')))
2388 f.write('.SS Reply datastructure\n')
2391 f.write('typedef %s %s {\n' % (self.reply.c_container, self.reply.c_type))
2395 for field in self.reply.fields:
2396 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2399 struct_fields.append(field)
2401 for field in struct_fields:
2402 length = len(field.c_field_type)
2403 # account for '*' pointer_spec
2404 if not field.type.fixed_size():
2406 maxtypelen = max(maxtypelen, length)
2408 def _c_complex_field(self, field, space=''):
2409 if (field.type.fixed_size() or
2410 # in case of switch with switch children, don't make the field a pointer
2411 # necessary for unserialize to work
2412 (self.is_switch and field.type.is_switch)):
2413 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2414 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2416 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
2417 f.write('ELSE %s = %s\n' % (field.c_field_type, field.c_field_name))
2418 #_h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2420 if not self.is_switch:
2421 for field in struct_fields:
2422 _c_complex_field(self, field)
2424 for b in self.bitcases:
2428 for field in b.type.fields:
2429 _c_complex_field(self, field, space)
2431 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2434 f.write('} \\fB%s\\fP;\n' % self.reply.c_type)
2437 f.write('.SS Reply function\n')
2439 f.write(('%s *\\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\\ '
2440 '\\fIcookie\\fP, xcb_generic_error_t\\ **\\fIe\\fP);\n') %
2441 (self.c_reply_type, self.c_reply_name, self.c_cookie_type))
2442 create_link('%s' % self.c_reply_name)
2444 has_accessors = False
2445 for field in self.reply.fields:
2446 if field.type.is_list and not field.type.fixed_size():
2447 has_accessors = True
2448 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2449 has_accessors = True
2452 f.write('.SS Reply accessors\n')
2454 def _c_accessors_field(self, field):
2456 Declares the accessor functions for a non-list field that follows a variable-length field.
2458 c_type = self.c_type
2460 # special case: switch
2461 switch_obj = self if self.is_switch else None
2462 if self.is_case_or_bitcase:
2463 switch_obj = self.parents[-1]
2464 if switch_obj is not None:
2465 c_type = switch_obj.c_type
2467 if field.type.is_simple:
2468 f.write('%s %s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2469 create_link('%s' % field.c_accessor_name)
2471 f.write('%s *%s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2472 create_link('%s' % field.c_accessor_name)
2474 def _c_accessors_list(self, field):
2476 Declares the accessor functions for a list field.
2477 Declares a direct-accessor function only if the list members are fixed size.
2478 Declares length and get-iterator functions always.
2481 c_type = self.reply.c_type
2483 # special case: switch
2484 # in case of switch, 2 params have to be supplied to certain accessor functions:
2485 # 1. the anchestor object (request or reply)
2486 # 2. the (anchestor) switch object
2487 # the reason is that switch is either a child of a request/reply or nested in another switch,
2488 # so whenever we need to access a length field, we might need to refer to some anchestor type
2489 switch_obj = self if self.is_switch else None
2490 if self.is_case_or_bitcase:
2491 switch_obj = self.parents[-1]
2492 if switch_obj is not None:
2493 c_type = switch_obj.c_type
2497 parents = self.parents if hasattr(self, 'parents') else [self]
2498 # 'R': parents[0] is always the 'toplevel' container type
2499 params.append(('const %s *\\fIreply\\fP' % parents[0].c_type, parents[0]))
2500 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
2501 # auxiliary object for 'R' parameters
2504 if switch_obj is not None:
2505 # now look where the fields are defined that are needed to evaluate
2506 # the switch expr, and store the parent objects in accessor_params and
2507 # the fields in switch_fields
2509 # 'S': name for the 'toplevel' switch
2510 toplevel_switch = parents[1]
2511 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
2512 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
2514 # initialize prefix for everything "below" S
2515 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
2516 prefix = [(prefix_str, '->', toplevel_switch)]
2518 # look for fields in the remaining containers
2519 for p in parents[2:] + [self]:
2520 # the separator between parent and child is always '.' here,
2521 # because of nested switch statements
2522 if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
2523 prefix.append((p.name[-1], '.', p))
2524 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
2526 # auxiliary object for 'S' parameter
2529 if list.member.fixed_size():
2530 idx = 1 if switch_obj is not None else 0
2532 f.write('%s *\\fB%s\\fP(%s);\n' %
2533 (field.c_field_type, field.c_accessor_name, params[idx][0]))
2534 create_link('%s' % field.c_accessor_name)
2537 f.write('int \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2538 (field.c_length_name, c_type))
2539 create_link('%s' % field.c_length_name)
2541 if field.type.member.is_simple:
2543 f.write('xcb_generic_iterator_t \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2544 (field.c_end_name, c_type))
2545 create_link('%s' % field.c_end_name)
2548 f.write('%s \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2549 (field.c_iterator_type, field.c_iterator_name,
2551 create_link('%s' % field.c_iterator_name)
2553 for field in self.reply.fields:
2554 if field.type.is_list and not field.type.fixed_size():
2555 _c_accessors_list(self, field)
2556 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2557 _c_accessors_field(self, field)
2561 # Re-enable hyphenation and adjusting to both sides
2564 # argument reference
2565 f.write('.SH REQUEST ARGUMENTS\n')
2566 f.write('.IP \\fI%s\\fP 1i\n' % 'conn')
2567 f.write('The XCB connection to X11.\n')
2568 for field in param_fields:
2569 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2570 printed_enum = False
2571 # XXX: hard-coded until we fix xproto.xml
2572 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
2574 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
2576 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
2578 if hasattr(field, "enum") and field.enum:
2579 # XXX: why the 'xcb' prefix?
2580 key = ('xcb', field.enum)
2582 f.write('One of the following values:\n')
2585 count = len(enum.values)
2586 for (enam, eval) in enum.values:
2588 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2589 if hasattr(enum, "doc") and enum.doc and enam in enum.doc.fields:
2590 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2591 f.write('%s\n' % desc)
2593 f.write('TODO: NOT YET DOCUMENTED.\n')
2598 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2599 desc = self.doc.fields[field.field_name]
2600 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2603 f.write('%s\n' % desc)
2605 f.write('TODO: NOT YET DOCUMENTED.\n')
2611 f.write('.SH REPLY FIELDS\n')
2612 # These fields are present in every reply:
2613 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2614 f.write(('The type of this reply, in this case \\fI%s\\fP. This field '
2615 'is also present in the \\fIxcb_generic_reply_t\\fP and can '
2616 'be used to tell replies apart from each other.\n') %
2617 _n(self.reply.name).upper())
2618 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2619 f.write('The sequence number of the last request processed by the X11 server.\n')
2620 f.write('.IP \\fI%s\\fP 1i\n' % 'length')
2621 f.write('The length of the reply, in words (a word is 4 bytes).\n')
2622 for field in self.reply.fields:
2623 if (field.c_field_name in frozenset(['response_type', 'sequence', 'length']) or
2624 field.c_field_name.startswith('pad')):
2627 if field.type.is_list and not field.type.fixed_size():
2629 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2631 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2632 printed_enum = False
2633 if hasattr(field, "enum") and field.enum:
2634 # XXX: why the 'xcb' prefix?
2635 key = ('xcb', field.enum)
2637 f.write('One of the following values:\n')
2640 count = len(enum.values)
2641 for (enam, eval) in enum.values:
2643 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2644 if enum.doc and enam in enum.doc.fields:
2645 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2646 f.write('%s\n' % desc)
2648 f.write('TODO: NOT YET DOCUMENTED.\n')
2653 if hasattr(self.reply, "doc") and self.reply.doc and field.field_name in self.reply.doc.fields:
2654 desc = self.reply.doc.fields[field.field_name]
2655 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2658 f.write('%s\n' % desc)
2660 f.write('TODO: NOT YET DOCUMENTED.\n')
2667 f.write('.SH DESCRIPTION\n')
2668 if hasattr(self, "doc") and self.doc and self.doc.description:
2669 desc = self.doc.description
2670 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2671 lines = desc.split('\n')
2672 f.write('\n'.join(lines) + '\n')
2674 f.write('.SH RETURN VALUE\n')
2676 f.write(('Returns an \\fIxcb_void_cookie_t\\fP. Errors (if any) '
2677 'have to be handled in the event loop.\n\nIf you want to '
2678 'handle errors directly with \\fIxcb_request_check\\fP '
2679 'instead, use \\fI%s_checked\\fP. See '
2680 '\\fBxcb-requests(%s)\\fP for details.\n') % (base_func_name, section))
2682 f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
2683 'calling the reply function \\fI%s\\fP.\n\nIf you want to '
2684 'handle errors in the event loop instead, use '
2685 '\\fI%s_unchecked\\fP. See \\fBxcb-requests(%s)\\fP for '
2687 (cookie_type, self.c_reply_name, base_func_name, section))
2688 f.write('.SH ERRORS\n')
2689 if hasattr(self, "doc") and self.doc:
2690 for errtype, errtext in sorted(self.doc.errors.items()):
2691 f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
2692 errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
2693 f.write('%s\n' % (errtext))
2694 if not hasattr(self, "doc") or not self.doc or len(self.doc.errors) == 0:
2695 f.write('This request does never generate any errors.\n')
2696 if hasattr(self, "doc") and self.doc and self.doc.example:
2697 f.write('.SH EXAMPLE\n')
2700 lines = self.doc.example.split('\n')
2701 f.write('\n'.join(lines) + '\n')
2703 f.write('.SH SEE ALSO\n')
2704 if hasattr(self, "doc") and self.doc:
2705 see = ['.BR %s (%s)' % ('xcb-requests', section)]
2706 if self.doc.example:
2707 see.append('.BR %s (%s)' % ('xcb-examples', section))
2708 for seename, seetype in sorted(self.doc.see.items()):
2709 if seetype == 'program':
2710 see.append('.BR %s (1)' % seename)
2711 elif seetype == 'event':
2712 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2713 elif seetype == 'request':
2714 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2715 elif seetype == 'function':
2716 see.append('.BR %s (%s)' % (seename, section))
2718 see.append('TODO: %s (type %s)' % (seename, seetype))
2719 f.write(',\n'.join(see) + '\n')
2720 f.write('.SH AUTHOR\n')
2721 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2724 def _man_event(self, name):
2726 sys.stdout.write('man/%s.%s ' % (self.c_type, section))
2727 # Our CWD is src/, so this will end up in src/man/
2728 f = open('man/%s.%s' % (self.c_type, section), 'w')
2729 f.write('.TH %s %s "%s" "%s" "XCB Events"\n' % (self.c_type, section, center_footer, left_footer))
2730 # Left-adjust instead of adjusting to both sides
2732 f.write('.SH NAME\n')
2733 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2734 f.write('%s \\- %s\n' % (self.c_type, brief))
2735 f.write('.SH SYNOPSIS\n')
2736 # Don't split words (hyphenate)
2738 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2741 f.write('.SS Event datastructure\n')
2744 f.write('typedef %s %s {\n' % (self.c_container, self.c_type))
2748 for field in self.fields:
2749 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2752 struct_fields.append(field)
2754 for field in struct_fields:
2755 length = len(field.c_field_type)
2756 # account for '*' pointer_spec
2757 if not field.type.fixed_size():
2759 maxtypelen = max(maxtypelen, length)
2761 def _c_complex_field(self, field, space=''):
2762 if (field.type.fixed_size() or
2763 # in case of switch with switch children, don't make the field a pointer
2764 # necessary for unserialize to work
2765 (self.is_switch and field.type.is_switch)):
2766 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2767 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2769 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2771 if not self.is_switch:
2772 for field in struct_fields:
2773 _c_complex_field(self, field)
2775 for b in self.bitcases:
2779 for field in b.type.fields:
2780 _c_complex_field(self, field, space)
2782 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2785 f.write('} \\fB%s\\fP;\n' % self.c_type)
2790 # Re-enable hyphenation and adjusting to both sides
2793 # argument reference
2794 f.write('.SH EVENT FIELDS\n')
2795 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2796 f.write(('The type of this event, in this case \\fI%s\\fP. This field is '
2797 'also present in the \\fIxcb_generic_event_t\\fP and can be used '
2798 'to tell events apart from each other.\n') % _n(name).upper())
2799 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2800 f.write('The sequence number of the last request processed by the X11 server.\n')
2802 if not self.is_switch:
2803 for field in struct_fields:
2804 # Skip the fields which every event has, we already documented
2806 if field.c_field_name in ('response_type', 'sequence'):
2808 if isinstance(field.type, PadType):
2810 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2811 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2812 desc = self.doc.fields[field.field_name]
2813 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2814 f.write('%s\n' % desc)
2816 f.write('NOT YET DOCUMENTED.\n')
2819 f.write('.SH DESCRIPTION\n')
2820 if hasattr(self, "doc") and self.doc and self.doc.description:
2821 desc = self.doc.description
2822 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2823 lines = desc.split('\n')
2824 f.write('\n'.join(lines) + '\n')
2826 if hasattr(self, "doc") and self.doc and self.doc.example:
2827 f.write('.SH EXAMPLE\n')
2830 lines = self.doc.example.split('\n')
2831 f.write('\n'.join(lines) + '\n')
2833 f.write('.SH SEE ALSO\n')
2834 if hasattr(self, "doc") and self.doc:
2835 see = ['.BR %s (%s)' % ('xcb_generic_event_t', section)]
2836 if self.doc.example:
2837 see.append('.BR %s (%s)' % ('xcb-examples', section))
2838 for seename, seetype in sorted(self.doc.see.items()):
2839 if seetype == 'program':
2840 see.append('.BR %s (1)' % seename)
2841 elif seetype == 'event':
2842 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2843 elif seetype == 'request':
2844 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2845 elif seetype == 'function':
2846 see.append('.BR %s (%s)' % (seename, section))
2848 see.append('TODO: %s (type %s)' % (seename, seetype))
2849 f.write(',\n'.join(see) + '\n')
2850 f.write('.SH AUTHOR\n')
2851 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2855 def c_request(self, name):
2857 Exported function that handles request declarations.
2859 _c_type_setup(self, name, ('request',))
2862 # Cookie type declaration
2863 _c_cookie(self, name)
2866 _c_opcode(name, self.opcode)
2868 # Request structure declaration
2872 _c_type_setup(self.reply, name, ('reply',))
2873 # Reply structure definition
2874 _c_complex(self.reply)
2875 # Request prototypes
2876 has_fds = _c_reply_has_fds(self.reply)
2877 _c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds)
2878 _c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds)
2880 _c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds)
2881 _c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds)
2883 _c_accessors(self.reply, name + ('reply',), name)
2884 _c_reply(self, name)
2886 _c_reply_fds(self, name)
2888 # Request prototypes
2889 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2890 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2892 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2893 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2895 # We generate the manpage afterwards because _c_type_setup has been called.
2896 # TODO: what about aux helpers?
2897 cookie_type = self.c_cookie_type if self.reply else 'xcb_void_cookie_t'
2898 _man_request(self, name, cookie_type, not self.reply, False)
2900 def c_event(self, name):
2902 Exported function that handles event declarations.
2905 # The generic event structure xcb_ge_event_t has the full_sequence field
2906 # at the 32byte boundary. That's why we've to inject this field into GE
2907 # events while generating the structure for them. Otherwise we would read
2908 # garbage (the internal full_sequence) when accessing normal event fields
2910 force_packed = False
2911 if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
2913 for field in self.fields:
2914 if field.type.size != None and field.type.nmemb != None:
2915 event_size += field.type.size * field.type.nmemb
2916 if event_size == 32:
2917 full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
2918 idx = self.fields.index(field)
2919 self.fields.insert(idx + 1, full_sequence)
2921 # If the event contains any 64-bit extended fields, they need
2922 # to remain aligned on a 64-bit boundary. Adding full_sequence
2923 # would normally break that; force the struct to be packed.
2924 force_packed = any(f.type.size == 8 and f.type.is_simple for f in self.fields[(idx+1):])
2927 _c_type_setup(self, name, ('event',))
2930 _c_opcode(name, self.opcodes[name])
2932 if self.name == name:
2933 # Structure definition
2934 _c_complex(self, force_packed)
2938 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2940 _man_event(self, name)
2942 def c_error(self, name):
2944 Exported function that handles error declarations.
2946 _c_type_setup(self, name, ('error',))
2949 _c_opcode(name, self.opcodes[name])
2951 if self.name == name:
2952 # Structure definition
2957 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2960 # Main routine starts here
2962 # Must create an "output" dictionary before any xcbgen imports.
2963 output = {'open' : c_open,
2965 'simple' : c_simple,
2967 'struct' : c_struct,
2969 'request' : c_request,
2974 # Boilerplate below this point
2976 # Check for the argument that specifies path to the xcbgen python package.
2978 opts, args = getopt.getopt(sys.argv[1:], 'c:l:s:p:m')
2979 except getopt.GetoptError as err:
2981 print('Usage: c_client.py -c center_footer -l left_footer -s section [-p path] file.xml')
2984 for (opt, arg) in opts:
2992 sys.path.insert(1, arg)
2995 sys.stdout.write('man_MANS = ')
2997 # Import the module class
2999 from xcbgen.state import Module
3000 from xcbgen.xtypes import *
3003 Failed to load the xcbgen Python package!
3004 Make sure that xcb/proto installed it on your Python path.
3005 If not, you will need to create a .pth file or define $PYTHONPATH
3007 Refer to the README file in xcb/proto for more info.
3011 # Ensure the man subdirectory exists
3014 except OSError as e:
3015 if e.errno != errno.EEXIST:
3018 # Parse the xml header
3019 module = Module(args[0], output)
3021 # Build type-registry and resolve type dependencies