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 _c_type_setup(field.type, field.field_type, ())
340 if field.type.is_list:
341 _c_type_setup(field.type.member, field.field_type, ())
342 if (field.type.nmemb is None):
343 self.c_need_sizeof = True
345 field.c_field_type = _t(field.field_type)
346 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
347 field.c_field_name = _cpp(field.field_name)
348 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb and field.type.nmemb > 1) else ''
349 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
351 # correct the c_pointer field for variable size non-list types
352 if not field.type.fixed_size() and field.c_pointer == ' ':
353 field.c_pointer = '*'
354 if field.type.is_list and not field.type.member.fixed_size():
355 field.c_pointer = '*'
357 if field.type.is_switch:
358 field.c_pointer = '*'
359 field.c_field_const_type = 'const ' + field.c_field_type
360 self.c_need_aux = True
362 if not field.type.fixed_size() and not field.type.is_case_or_bitcase:
363 self.c_need_sizeof = True
365 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
366 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
367 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
368 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
369 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
371 field.prev_varsized_field = prev_varsized_field
372 field.prev_varsized_offset = prev_varsized_offset
374 if prev_varsized_offset == 0:
375 first_field_after_varsized = field
376 field.first_field_after_varsized = first_field_after_varsized
378 if field.type.fixed_size():
379 prev_varsized_offset += field.type.size
380 # special case: intermixed fixed and variable size fields
381 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
382 if not self.is_union:
383 self.c_need_serialize = True
384 self.c_var_followed_by_fixed_fields = True
386 self.last_varsized_field = field
387 prev_varsized_field = field
388 prev_varsized_offset = 0
390 if self.c_var_followed_by_fixed_fields:
391 if field.type.fixed_size():
392 field.prev_varsized_field = None
394 if self.c_need_serialize:
395 # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
396 self.c_need_sizeof = True
398 # as switch does never appear at toplevel,
399 # continue here with type construction
401 if self.c_type not in finished_switch:
402 finished_switch.append(self.c_type)
403 # special: switch C structs get pointer fields for variable-sized members
405 for bitcase in self.bitcases:
406 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
407 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
408 # no list with switch as element, so no call to
409 # _c_iterator(field.type, field_name) necessary
411 if not self.is_case_or_bitcase:
412 if self.c_need_serialize:
413 if self.c_serialize_name not in finished_serializers:
414 finished_serializers.append(self.c_serialize_name)
415 _c_serialize('serialize', self)
417 # _unpack() and _unserialize() are only needed for special cases:
419 # special cases -> unserialize
420 if self.is_switch or self.c_var_followed_by_fixed_fields:
421 _c_serialize('unserialize', self)
423 if self.c_need_sizeof:
424 if self.c_sizeof_name not in finished_sizeof:
425 if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
426 finished_sizeof.append(self.c_sizeof_name)
427 _c_serialize('sizeof', self)
430 def _c_helper_absolute_name(prefix, field=None):
432 turn prefix, which is a list of tuples (name, separator, Type obj) into a string
433 representing a valid name in C (based on the context)
434 if field is not None, append the field name as well
437 for name, sep, obj in prefix:
441 if ((obj.is_case_or_bitcase and obj.has_name) or # named bitcase
442 (obj.is_switch and len(obj.parents)>1)):
445 if field is not None:
446 prefix_str += _cpp(field.field_name)
450 def _c_helper_field_mapping(complex_type, prefix, flat=False):
452 generate absolute names, based on prefix, for all fields starting from complex_type
453 if flat == True, nested complex types are not taken into account
456 if complex_type.is_switch:
457 for b in complex_type.bitcases:
459 switch_name, switch_sep, switch_type = prefix[-1]
460 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
462 bitcase_prefix = prefix
464 if (True==flat and not b.type.has_name) or False==flat:
465 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
467 for f in complex_type.fields:
468 fname = _c_helper_absolute_name(prefix, f)
469 if f.field_name in all_fields:
470 raise Exception("field name %s has been registered before" % f.field_name)
472 all_fields[f.field_name] = (fname, f)
473 if f.type.is_container and flat==False:
474 if f.type.is_case_or_bitcase and not f.type.has_name:
476 elif f.type.is_switch and len(f.type.parents)>1:
477 # nested switch gets another separator
478 new_prefix = prefix+[(f.c_field_name, '.', f.type)]
480 new_prefix = prefix+[(f.c_field_name, '->', f.type)]
481 all_fields.update(_c_helper_field_mapping(f.type, new_prefix, flat))
486 def _c_helper_resolve_field_names (prefix):
488 get field names for all objects in the prefix array
492 # look for fields in the remaining containers
493 for idx, p in enumerate(prefix):
496 # sep can be preset in prefix, if not, make a sensible guess
497 sep = '.' if (obj.is_switch or obj.is_case_or_bitcase) else '->'
498 # exception: 'toplevel' object (switch as well!) always have sep '->'
499 sep = '->' if idx<1 else sep
500 if not obj.is_case_or_bitcase or (obj.is_case_or_bitcase and obj.has_name):
501 tmp_prefix.append((name, sep, obj))
502 all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
505 # _c_helper_resolve_field_names
507 def get_expr_fields(self):
509 get the Fields referenced by switch or list expression
511 def get_expr_field_names(expr):
513 if expr.lenfield_name is not None:
514 return [expr.lenfield_name]
516 # constant value expr
520 return get_expr_field_names(expr.rhs)
521 elif expr.op == 'popcount':
522 return get_expr_field_names(expr.rhs)
523 elif expr.op == 'sumof':
524 # sumof expr references another list,
525 # we need that list's length field here
527 for f in expr.lenfield_parent.fields:
528 if f.field_name == expr.lenfield_name:
532 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
533 # referenced list + its length field
534 return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
535 elif expr.op == 'enumref':
538 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
539 # get_expr_field_names()
541 # resolve the field names with the parent structure(s)
542 unresolved_fields_names = get_expr_field_names(self.expr)
544 # construct prefix from self
545 prefix = [('', '', p) for p in self.parents]
546 if self.is_container:
547 prefix.append(('', '', self))
549 all_fields = _c_helper_resolve_field_names (prefix)
550 resolved_fields_names = list(filter(lambda x: x in all_fields.keys(), unresolved_fields_names))
551 if len(unresolved_fields_names) != len(resolved_fields_names):
552 raise Exception("could not resolve all fields for %s" % self.name)
554 resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
555 return resolved_fields
558 def resolve_expr_fields(complex_obj):
560 find expr fields appearing in complex_obj and descendents that cannot be resolved within complex_obj
561 these are normally fields that need to be given as function parameters
567 for field in complex_obj.fields:
568 all_fields.append(field)
569 if field.type.is_switch or field.type.is_list:
570 expr_fields += get_expr_fields(field.type)
571 if field.type.is_container:
572 expr_fields += resolve_expr_fields(field.type)
574 # try to resolve expr fields
575 for e in expr_fields:
576 if e not in all_fields and e not in unresolved:
579 # resolve_expr_fields()
581 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
583 functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
584 E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch
585 expression. This function tries to resolve all fields within a structure, and returns the
586 unresolved fields as the list of external parameters.
588 def add_param(params, param):
589 if param not in params:
592 # collect all fields into param_fields
596 for field in self.fields:
598 # the field should appear as a parameter in the function call
599 param_fields.append(field)
600 if field.wire and not field.auto:
601 if field.type.fixed_size() and not self.is_switch:
602 # field in the xcb_out structure
603 wire_fields.append(field)
604 # fields like 'pad0' are skipped!
606 # in case of switch, parameters always contain any fields referenced in the switch expr
607 # we do not need any variable size fields here, as the switch data type contains both
608 # fixed and variable size fields
610 param_fields = get_expr_fields(self)
612 # _serialize()/_unserialize()/_unpack() function parameters
613 # note: don't use set() for params, it is unsorted
616 # 1. the parameter for the void * buffer
617 if 'serialize' == context:
618 params.append(('void', '**', buffer_var))
619 elif context in ('unserialize', 'unpack', 'sizeof'):
620 params.append(('const void', '*', buffer_var))
622 # 2. any expr fields that cannot be resolved within self and descendants
623 unresolved_fields = resolve_expr_fields(self)
624 for f in unresolved_fields:
625 add_param(params, (f.c_field_type, '', f.c_field_name))
627 # 3. param_fields contain the fields necessary to evaluate the switch expr or any other fields
628 # that do not appear in the data type struct
629 for p in param_fields:
631 typespec = p.c_field_const_type
632 pointerspec = p.c_pointer
633 add_param(params, (typespec, pointerspec, p.c_field_name))
635 if p.visible and not p.wire and not p.auto:
636 typespec = p.c_field_type
638 add_param(params, (typespec, pointerspec, p.c_field_name))
641 if 'serialize' == context:
642 add_param(params, ('const %s' % self.c_type, '*', aux_var))
643 elif 'unserialize' == context:
644 add_param(params, ('%s' % self.c_type, '**', aux_var))
645 elif 'unpack' == context:
646 add_param(params, ('%s' % self.c_type, '*', aux_var))
648 # 5. switch contains all variable size fields as struct members
649 # for other data types though, these have to be supplied separately
650 # this is important for the special case of intermixed fixed and
651 # variable size fields
652 if not self.is_switch and 'serialize' == context:
653 for p in param_fields:
654 if not p.type.fixed_size():
655 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
657 return (param_fields, wire_fields, params)
658 # get_serialize_params()
660 def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
661 code_lines.append('%s /* insert padding */' % space)
662 code_lines.append('%s xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
663 # code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
664 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
667 code_lines.append('%s if (0 != xcb_pad) {' % space)
669 if 'serialize' == context:
670 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
671 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
672 code_lines.append('%s xcb_parts_idx++;' % space)
673 elif context in ('unserialize', 'unpack', 'sizeof'):
674 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
676 code_lines.append('%s xcb_pad = 0;' % space)
677 code_lines.append('%s }' % space)
679 code_lines.append('%s xcb_block_len = 0;' % space)
681 # keep tracking of xcb_parts entries for serialize
683 # _c_serialize_helper_insert_padding()
685 def _c_serialize_helper_switch(context, self, complex_name,
686 code_lines, temp_vars,
689 switch_expr = _c_accessor_get_expr(self.expr, None)
691 for b in self.bitcases:
692 len_expr = len(b.type.expr)
694 compare_operator = '&'
696 compare_operator = '=='
698 compare_operator = '&'
700 for n, expr in enumerate(b.type.expr):
701 bitcase_expr = _c_accessor_get_expr(expr, None)
702 # only one <enumref> in the <bitcase>
705 ' if(%s %s %s) {' % (switch_expr, compare_operator, bitcase_expr))
706 # multiple <enumref> in the <bitcase>
709 ' if((%s %s %s) ||' % (switch_expr, compare_operator, bitcase_expr))
710 elif len_expr == (n + 1): # last
712 ' (%s %s %s)) {' % (switch_expr, compare_operator, bitcase_expr))
713 else: # between first and last
715 ' (%s %s %s) ||' % (switch_expr, compare_operator, bitcase_expr))
719 b_prefix = prefix + [(b.c_field_name, '.', b.type)]
721 count += _c_serialize_helper_fields(context, b.type,
722 code_lines, temp_vars,
725 is_case_or_bitcase = True)
726 code_lines.append(' }')
728 # if 'serialize' == context:
729 # count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
730 # elif context in ('unserialize', 'unpack', 'sizeof'):
732 # code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
733 # code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
736 # _c_serialize_helper_switch
738 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
740 handle switch by calling _serialize() or _unpack(), depending on context
742 # switch is handled by this function as a special case
743 param_fields, wire_fields, params = get_serialize_params(context, self)
744 field_mapping = _c_helper_field_mapping(self, prefix)
745 prefix_str = _c_helper_absolute_name(prefix)
747 # find the parameters that need to be passed to _serialize()/_unpack():
748 # all switch expr fields must be given as parameters
749 args = get_expr_fields(field.type)
750 # length fields for variable size types in switch, normally only some of need
751 # need to be passed as parameters
752 switch_len_fields = resolve_expr_fields(field.type)
754 # a switch field at this point _must_ be a bitcase field
755 # we require that bitcases are "self-contiguous"
756 bitcase_unresolved = resolve_expr_fields(self)
757 if len(bitcase_unresolved) != 0:
758 raise Exception('unresolved fields within bitcase is not supported at this point')
760 # get the C names for the parameters
762 for a in switch_len_fields:
763 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
765 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
767 # call _serialize()/_unpack() to determine the actual size
768 if 'serialize' == context:
769 length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
770 c_field_names, prefix_str, field.c_field_name)
771 elif context in ('unserialize', 'unpack'):
772 length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
773 c_field_names, prefix_str, field.c_field_name)
774 elif 'sizeof' == context:
775 # remove trailing ", " from c_field_names because it will be used at end of arglist
776 my_c_field_names = c_field_names[:-2]
777 length = "%s(xcb_tmp, %s)" % (field.type.c_sizeof_name, my_c_field_names)
780 # _c_serialize_helper_switch_field()
782 def _c_serialize_helper_list_field(context, self, field,
783 code_lines, temp_vars,
786 helper function to cope with lists of variable length
788 expr = field.type.expr
789 prefix_str = _c_helper_absolute_name(prefix)
790 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
791 param_names = [p[2] for p in params]
793 expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
794 resolved = list(filter(lambda x: x in param_names, expr_fields_names))
795 unresolved = list(filter(lambda x: x not in param_names, expr_fields_names))
799 field_mapping[r] = (r, None)
801 if len(unresolved)>0:
803 if len(tmp_prefix)==0:
804 raise Exception("found an empty prefix while resolving expr field names for list %s",
807 field_mapping.update(_c_helper_resolve_field_names(prefix))
808 resolved += list(filter(lambda x: x in field_mapping, unresolved))
809 unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
810 if len(unresolved)>0:
811 raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
813 list_length = _c_accessor_get_expr(expr, field_mapping)
815 # default: list with fixed size elements
816 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
818 # list with variable-sized elements
819 if not field.type.member.fixed_size():
821 if context in ('unserialize', 'sizeof', 'unpack'):
822 int_i = ' unsigned int i;'
823 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
824 if int_i not in temp_vars:
825 temp_vars.append(int_i)
826 if xcb_tmp_len not in temp_vars:
827 temp_vars.append(xcb_tmp_len)
828 # loop over all list elements and call sizeof repeatedly
829 # this should be a bit faster than using the iterators
830 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
831 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
832 (space, field.type.c_sizeof_name))
833 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
834 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
835 code_lines.append("%s }" % space)
837 elif 'serialize' == context:
838 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
839 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
840 code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length))
841 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
842 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
843 code_lines.append('%s }' % space)
844 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
847 # _c_serialize_helper_list_field()
849 def _c_serialize_helper_fields_fixed_size(context, self, field,
850 code_lines, temp_vars,
852 # keep the C code a bit more readable by giving the field name
853 if not self.is_case_or_bitcase:
854 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
856 scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
857 typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
858 code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
860 abs_field_name = _c_helper_absolute_name(prefix, field)
861 # default for simple cases: call sizeof()
862 length = "sizeof(%s)" % field.c_field_type
864 if context in ('unserialize', 'unpack', 'sizeof'):
865 # default: simple cast
866 value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
868 # padding - we could probably just ignore it
869 if field.type.is_pad and field.type.nmemb > 1:
871 for i in range(field.type.nmemb):
872 code_lines.append('%s %s[%d] = *(%s *)xcb_tmp;' %
873 (space, abs_field_name, i, field.c_field_type))
874 # total padding = sizeof(pad0) * nmemb
875 length += " * %d" % field.type.nmemb
877 elif field.type.is_list:
878 # list with fixed number of elements
879 # length of array = sizeof(arrayElementType) * nmemb
880 length += " * %d" % field.type.nmemb
881 # use memcpy because C cannot assign whole arrays with operator=
882 value = ' memcpy(%s, xcb_tmp, %s);' % (abs_field_name, length)
885 elif 'serialize' == context:
886 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
888 if field.type.is_expr:
889 # need to register a temporary variable for the expression in case we know its type
890 if field.type.c_type is None:
891 raise Exception("type for field '%s' (expression '%s') unkown" %
892 (field.field_name, _c_accessor_get_expr(field.type.expr)))
894 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
895 _c_accessor_get_expr(field.type.expr, prefix)))
896 value += "&xcb_expr_%s;" % _cpp(field.field_name)
898 elif field.type.is_pad:
899 if field.type.nmemb == 1:
902 # we could also set it to 0, see definition of xcb_send_request()
903 value = ' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
904 length += "*%d" % field.type.nmemb
907 # non-list type with fixed size
908 if field.type.nmemb == 1:
909 value += "&%s;" % (abs_field_name)
911 # list with nmemb (fixed size) elements
913 value += '%s;' % (abs_field_name)
914 length = '%d' % field.type.nmemb
916 return (value, length)
917 # _c_serialize_helper_fields_fixed_size()
919 def _c_serialize_helper_fields_variable_size(context, self, field,
920 code_lines, temp_vars,
922 prefix_str = _c_helper_absolute_name(prefix)
924 if context in ('unserialize', 'unpack', 'sizeof'):
926 var_field_name = 'xcb_tmp'
928 # special case: intermixed fixed and variable size fields
929 if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
930 value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
931 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
932 # special case: switch
933 if 'unpack' == context:
934 value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
936 elif 'serialize' == context:
937 # variable size fields appear as parameters to _serialize() if the
938 # 'toplevel' container is not a switch
939 prefix_string = prefix_str if prefix[0][2].is_switch else ''
940 var_field_name = "%s%s" % (prefix_string, field.c_field_name)
941 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
945 code_lines.append('%s /* %s */' % (space, field.c_field_name))
947 if field.type.is_list:
949 # in any context, list is already a pointer, so the default assignment is ok
950 code_lines.append("%s%s" % (space, value))
952 length = _c_serialize_helper_list_field(context, self, field,
953 code_lines, temp_vars,
956 elif field.type.is_switch:
958 if context == 'serialize':
959 # the _serialize() function allocates the correct amount memory if given a NULL pointer
960 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
961 length = _c_serialize_helper_switch_field(context, self, field,
962 'xcb_parts[xcb_parts_idx].iov_base',
966 # in all remaining special cases - call _sizeof()
967 length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
969 return (value, length)
970 # _c_serialize_helper_fields_variable_size
972 def _c_serialize_helper_fields(context, self,
973 code_lines, temp_vars,
974 space, prefix, is_case_or_bitcase):
977 prev_field_was_variable = False
979 for field in self.fields:
980 if not field.visible:
981 if not ((field.wire and not field.auto) or 'unserialize' == context):
984 # switch/bitcase: fixed size fields must be considered explicitly
985 if field.type.fixed_size():
986 if self.is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
987 if prev_field_was_variable and need_padding:
989 # count += _c_serialize_helper_insert_padding(context, code_lines, space,
990 # self.c_var_followed_by_fixed_fields)
991 prev_field_was_variable = False
993 # prefix for fixed size fields
994 fixed_prefix = prefix
996 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
997 code_lines, temp_vars,
1002 # fields with variable size
1004 if field.type.is_pad:
1005 # Variable length pad is <pad align= />
1006 code_lines.append('%s xcb_align_to = %d;' % (space, field.type.align))
1007 count += _c_serialize_helper_insert_padding(context, code_lines, space,
1008 self.c_var_followed_by_fixed_fields)
1011 # switch/bitcase: always calculate padding before and after variable sized fields
1012 if need_padding or is_case_or_bitcase:
1013 count += _c_serialize_helper_insert_padding(context, code_lines, space,
1014 self.c_var_followed_by_fixed_fields)
1016 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
1017 code_lines, temp_vars,
1019 prev_field_was_variable = True
1021 # save (un)serialization C code
1023 code_lines.append('%s%s' % (space, value))
1025 if field.type.fixed_size():
1026 if is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
1027 # keep track of (un)serialized object's size
1028 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1029 if context in ('unserialize', 'unpack', 'sizeof'):
1030 code_lines.append('%s xcb_tmp += %s;' % (space, length))
1032 # variable size objects or bitcase:
1033 # value & length might have been inserted earlier for special cases
1035 # special case: intermixed fixed and variable size fields
1036 if (not field.type.fixed_size() and
1037 self.c_var_followed_by_fixed_fields and 'unserialize' == context):
1038 temp_vars.append(' int %s_len;' % field.c_field_name)
1039 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
1040 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
1041 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
1043 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1044 # increase pointer into the byte stream accordingly
1045 if context in ('unserialize', 'sizeof', 'unpack'):
1046 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1048 if 'serialize' == context:
1050 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
1051 code_lines.append('%s xcb_parts_idx++;' % space)
1055 '%s xcb_align_to = ALIGNOF(%s);'
1058 if field.c_field_type == 'void' or field.type.is_switch
1059 else field.c_field_type))
1062 if self.c_var_followed_by_fixed_fields:
1063 need_padding = False
1066 # _c_serialize_helper_fields()
1068 def _c_serialize_helper(context, complex_type,
1069 code_lines, temp_vars,
1070 space='', prefix=[]):
1071 # count tracks the number of fields to serialize
1074 if hasattr(complex_type, 'type'):
1075 self = complex_type.type
1076 complex_name = complex_type.name
1079 if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
1080 complex_name = 'xcb_out'
1082 complex_name = '_aux'
1084 # special case: switch is serialized by evaluating each bitcase separately
1086 count += _c_serialize_helper_switch(context, self, complex_name,
1087 code_lines, temp_vars,
1090 # all other data types can be evaluated one field a time
1092 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1093 if context in ('unserialize', 'unpack', 'sizeof') and not self.c_var_followed_by_fixed_fields:
1094 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1095 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1096 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
1097 code_lines.append('%s xcb_block_len = 0;' % space)
1099 count += _c_serialize_helper_fields(context, self,
1100 code_lines, temp_vars,
1101 space, prefix, False)
1103 count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
1106 # _c_serialize_helper()
1108 def _c_serialize(context, self):
1110 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1111 for the ComplexType variable self
1117 # _serialize() returns the buffer size
1120 if self.is_switch and 'unserialize' == context:
1123 cases = { 'serialize' : self.c_serialize_name,
1124 'unserialize' : self.c_unserialize_name,
1125 'unpack' : self.c_unpack_name,
1126 'sizeof' : self.c_sizeof_name }
1127 func_name = cases[context]
1129 param_fields, wire_fields, params = get_serialize_params(context, self)
1130 variable_size_fields = 0
1131 # maximum space required for type definition of function arguments
1134 # determine N(variable_fields)
1135 for field in param_fields:
1136 # if self.is_switch, treat all fields as if they are variable sized
1137 if not field.type.fixed_size() or self.is_switch:
1138 variable_size_fields += 1
1139 # determine maxtypelen
1141 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1144 indent = ' '*(len(func_name)+2)
1147 typespec, pointerspec, field_name = p
1148 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1149 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1150 # insert function name
1151 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1152 param_str = list(map(lambda x: "%s," % x, param_str))
1153 for s in param_str[:-1]:
1155 _h("%s);" % param_str[-1].rstrip(','))
1156 _c("%s)" % param_str[-1].rstrip(','))
1163 if 'serialize' == context:
1164 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1165 _c(' %s *xcb_out = *_buffer;', self.c_type)
1166 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1167 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1168 _c(' unsigned int xcb_align_to = 0;')
1170 _c(' char *xcb_out = *_buffer;')
1171 _c(' unsigned int xcb_buffer_len = 0;')
1172 _c(' unsigned int xcb_align_to = 0;')
1173 prefix = [('_aux', '->', self)]
1176 elif context in ('unserialize', 'unpack'):
1177 _c(' char *xcb_tmp = (char *)_buffer;')
1178 if not self.is_switch:
1179 if not self.c_var_followed_by_fixed_fields:
1180 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1181 prefix = [('_aux', '->', self)]
1183 _c(' %s xcb_out;', self.c_type)
1184 prefix = [('xcb_out', '.', self)]
1186 aux_var = '_aux' # default for unpack: single pointer
1187 # note: unserialize not generated for switch
1188 if 'unserialize' == context:
1189 aux_var = '(*_aux)' # unserialize: double pointer (!)
1190 prefix = [(aux_var, '->', self)]
1192 _c(' unsigned int xcb_buffer_len = 0;')
1193 _c(' unsigned int xcb_block_len = 0;')
1194 _c(' unsigned int xcb_pad = 0;')
1195 _c(' unsigned int xcb_align_to = 0;')
1197 elif 'sizeof' == context:
1198 param_names = [p[2] for p in params]
1200 # switch: call _unpack()
1201 _c(' %s _aux;', self.c_type)
1202 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1205 elif self.c_var_followed_by_fixed_fields:
1206 # special case: call _unserialize()
1207 _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1211 _c(' char *xcb_tmp = (char *)_buffer;')
1212 prefix = [('_aux', '->', self)]
1214 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1215 # update variable size fields (only important for context=='serialize'
1216 variable_size_fields = count
1217 if 'serialize' == context:
1218 temp_vars.append(' unsigned int xcb_pad = 0;')
1219 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1220 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1221 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1222 temp_vars.append(' unsigned int xcb_block_len = 0;')
1223 temp_vars.append(' unsigned int i;')
1224 temp_vars.append(' char *xcb_tmp;')
1225 elif 'sizeof' == context:
1226 # neither switch nor intermixed fixed and variable size fields:
1227 # evaluate parameters directly
1228 if not (self.is_switch or self.c_var_followed_by_fixed_fields):
1230 # look if we have to declare an '_aux' variable at all
1231 if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
1232 if not self.c_var_followed_by_fixed_fields:
1233 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1235 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1237 _c(' unsigned int xcb_buffer_len = 0;')
1238 _c(' unsigned int xcb_block_len = 0;')
1239 _c(' unsigned int xcb_pad = 0;')
1240 _c(' unsigned int xcb_align_to = 0;')
1246 for l in code_lines:
1249 # variable sized fields have been collected, now
1250 # allocate memory and copy everything into a continuous memory area
1251 # note: this is not necessary in case of unpack
1252 if context in ('serialize', 'unserialize'):
1253 # unserialize: check for sizeof-only invocation
1254 if 'unserialize' == context:
1256 _c(' if (NULL == _aux)')
1257 _c(' return xcb_buffer_len;')
1260 _c(' if (NULL == %s) {', aux_ptr)
1261 _c(' /* allocate memory */')
1262 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1263 if 'serialize' == context:
1264 _c(' *_buffer = xcb_out;')
1268 # serialize: handle variable size fields in a loop
1269 if 'serialize' == context:
1270 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1271 if len(wire_fields)>0:
1272 _c(' *xcb_out = *_aux;')
1273 # copy variable size fields into the buffer
1274 if variable_size_fields > 0:
1276 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1277 _c(' xcb_tmp = (char*)++xcb_out;')
1278 _c(' xcb_tmp += xcb_out_pad;')
1280 _c(' xcb_tmp = xcb_out;')
1282 # variable sized fields
1283 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1284 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1285 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1286 _c(' if (0 != xcb_parts[i].iov_len)')
1287 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1290 # unserialize: assign variable size fields individually
1291 if 'unserialize' == context:
1292 _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1293 param_fields.reverse()
1294 for field in param_fields:
1295 if not field.type.fixed_size():
1296 _c(' xcb_tmp -= %s_len;', field.c_field_name)
1297 _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1298 _c(' *%s = xcb_out;', aux_ptr)
1301 _c(' return xcb_buffer_len;')
1305 def _c_iterator_get_end(field, accum):
1307 Figures out what C code is needed to find the end of a variable-length structure field.
1308 For nested structures, recurses into its last variable-sized field.
1309 For lists, calls the end function
1311 if field.type.is_container:
1312 accum = field.c_accessor_name + '(' + accum + ')'
1313 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1314 if field.type.is_list:
1315 # XXX we can always use the first way
1316 if field.type.member.is_simple:
1317 return field.c_end_name + '(' + accum + ')'
1319 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1321 def _c_iterator(self, name):
1323 Declares the iterator structure and next/end functions for a given type.
1328 _h(' * @brief %s', self.c_iterator_type)
1330 _h('typedef struct %s {', self.c_iterator_type)
1331 _h(' %s *data; /**< */', self.c_type)
1332 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1333 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1334 _h('} %s;', self.c_iterator_type)
1340 _h(' * Get the next element of the iterator')
1341 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1343 _h(' * Get the next element in the iterator. The member rem is')
1344 _h(' * decreased by one. The member data points to the next')
1345 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1349 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1350 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1353 if not self.fixed_size():
1354 _c(' %s *R = i->data;', self.c_type)
1357 # FIXME - how to determine the size of a variable size union??
1358 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1360 if self.c_need_sizeof:
1361 _c(' xcb_generic_iterator_t child;')
1362 _c(' child.data = (%s *)(((char *)R) + %s(R));',
1363 self.c_type, self.c_sizeof_name)
1364 _c(' i->index = (char *) child.data - (char *) i->data;')
1366 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1367 _c(' i->index = child.index;')
1369 _c(' i->data = (%s *) child.data;', self.c_type)
1374 _c(' i->index += sizeof(%s);', self.c_type)
1380 _h(' * Return the iterator pointing to the last element')
1381 _h(' * @param i An %s', self.c_iterator_type)
1382 _h(' * @return The iterator pointing to the last element')
1384 _h(' * Set the current element in the iterator to the last element.')
1385 _h(' * The member rem is set to 0. The member data points to the')
1386 _h(' * last element.')
1389 _hc('xcb_generic_iterator_t')
1390 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1391 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1393 _c(' xcb_generic_iterator_t ret;')
1395 if self.fixed_size():
1396 _c(' ret.data = i.data + i.rem;')
1397 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1400 _c(' while(i.rem > 0)')
1401 _c(' %s(&i);', self.c_next_name)
1402 _c(' ret.data = i.data;')
1403 _c(' ret.rem = i.rem;')
1404 _c(' ret.index = i.index;')
1409 def _c_accessor_get_length(expr, field_mapping=None):
1411 Figures out what C code is needed to get a length field.
1412 The field_mapping parameter can be used to change the absolute name of a length field.
1413 For fields that follow a variable-length field, use the accessor.
1414 Otherwise, just reference the structure field directly.
1417 lenfield_name = expr.lenfield_name
1418 if lenfield_name is not None:
1419 if field_mapping is not None:
1420 lenfield_name = field_mapping[lenfield_name][0]
1422 if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1423 # special case: variable and fixed size fields are intermixed
1424 # if the lenfield is among the fixed size fields, there is no need
1425 # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1426 return field_mapping(expr.lenfield_name)
1427 elif expr.lenfield_name is not None:
1428 return lenfield_name
1430 return str(expr.nmemb)
1432 def _c_accessor_get_expr(expr, field_mapping):
1434 Figures out what C code is needed to get the length of a list field.
1435 The field_mapping parameter can be used to change the absolute name of a length field.
1436 Recurses for math operations.
1437 Returns bitcount for value-mask fields.
1438 Otherwise, uses the value of the length field.
1440 lenexp = _c_accessor_get_length(expr, field_mapping)
1443 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1444 elif expr.op == 'popcount':
1445 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1446 elif expr.op == 'enumref':
1447 enum_name = expr.lenfield_type.name
1448 constant_name = expr.lenfield_name
1449 c_name = _n(enum_name + (constant_name,)).upper()
1451 elif expr.op == 'sumof':
1452 # locate the referenced list object
1453 list_obj = expr.lenfield_type
1455 for f in expr.lenfield_parent.fields:
1456 if f.field_name == expr.lenfield_name:
1461 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1462 list_name = field_mapping[field.c_field_name][0]
1463 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1464 # note: xcb_sumof() has only been defined for integers
1465 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1466 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1467 elif expr.op != None:
1468 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1469 ' ' + expr.op + ' ' +
1470 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1472 return 'xcb_popcount(' + lenexp + ')'
1476 def type_pad_type(type):
1481 def _c_accessors_field(self, field):
1483 Declares the accessor functions for a non-list field that follows a variable-length field.
1485 c_type = self.c_type
1487 # special case: switch
1488 switch_obj = self if self.is_switch else None
1489 if self.is_case_or_bitcase:
1490 switch_obj = self.parents[-1]
1491 if switch_obj is not None:
1492 c_type = switch_obj.c_type
1494 if field.type.is_simple:
1496 _hc('%s', field.c_field_type)
1497 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1498 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1500 if field.prev_varsized_field is None:
1501 _c(' return (%s *) (R + 1);', field.c_field_type)
1503 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1504 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1505 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1509 if field.type.is_switch and switch_obj is None:
1510 return_type = 'void *'
1512 return_type = '%s *' % field.c_field_type
1515 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1516 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1518 if field.prev_varsized_field is None:
1519 _c(' return (%s) (R + 1);', return_type)
1520 # note: the special case 'variable fields followed by fixed size fields'
1521 # is not of any consequence here, since the ordering gets
1522 # 'corrected' in the reply function
1524 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1525 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1526 return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1530 def _c_accessors_list(self, field):
1532 Declares the accessor functions for a list field.
1533 Declares a direct-accessor function only if the list members are fixed size.
1534 Declares length and get-iterator functions always.
1537 def get_align_pad(field):
1538 prev = field.prev_varsized_field
1539 prev_prev = field.prev_varsized_field.prev_varsized_field
1541 if (prev.type.is_pad and prev.type.align > 0 and prev_prev is not None):
1542 return (prev_prev, '((-prev.index) & (%d - 1))' % prev.type.align)
1548 c_type = self.c_type
1550 # special case: switch
1551 # in case of switch, 2 params have to be supplied to certain accessor functions:
1552 # 1. the anchestor object (request or reply)
1553 # 2. the (anchestor) switch object
1554 # the reason is that switch is either a child of a request/reply or nested in another switch,
1555 # so whenever we need to access a length field, we might need to refer to some anchestor type
1556 switch_obj = self if self.is_switch else None
1557 if self.is_case_or_bitcase:
1558 switch_obj = self.parents[-1]
1559 if switch_obj is not None:
1560 c_type = switch_obj.c_type
1564 parents = self.parents if hasattr(self, 'parents') else [self]
1565 # 'R': parents[0] is always the 'toplevel' container type
1566 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1567 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1568 # auxiliary object for 'R' parameters
1571 if switch_obj is not None:
1572 # now look where the fields are defined that are needed to evaluate
1573 # the switch expr, and store the parent objects in accessor_params and
1574 # the fields in switch_fields
1576 # 'S': name for the 'toplevel' switch
1577 toplevel_switch = parents[1]
1578 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1579 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1581 # initialize prefix for everything "below" S
1582 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1583 prefix = [(prefix_str, '->', toplevel_switch)]
1585 # look for fields in the remaining containers
1586 for p in parents[2:] + [self]:
1587 # the separator between parent and child is always '.' here,
1588 # because of nested switch statements
1589 if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
1590 prefix.append((p.name[-1], '.', p))
1591 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1593 # auxiliary object for 'S' parameter
1598 if list.member.fixed_size():
1599 idx = 1 if switch_obj is not None else 0
1601 _hc('%s *', field.c_field_type)
1603 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1604 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1607 if switch_obj is not None:
1608 _c(' return %s;', fields[field.c_field_name][0])
1609 elif field.prev_varsized_field is None:
1610 _c(' return (%s *) (R + 1);', field.c_field_type)
1612 (prev_varsized_field, align_pad) = get_align_pad(field)
1614 if align_pad is None:
1615 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
1616 type_pad_type(field.first_field_after_varsized.type.c_type))
1618 _c(' xcb_generic_iterator_t prev = %s;',
1619 _c_iterator_get_end(prev_varsized_field, 'R'))
1620 _c(' return (%s *) ((char *) prev.data + %s + %d);',
1621 field.c_field_type, align_pad, field.prev_varsized_offset)
1626 if switch_obj is not None:
1627 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1628 spacing = ' '*(len(field.c_length_name)+2)
1629 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1630 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1631 length = _c_accessor_get_expr(field.type.expr, fields)
1633 _h('%s (const %s *R /**< */);', field.c_length_name, c_type)
1634 _c('%s (const %s *R /**< */)', field.c_length_name, c_type)
1635 length = _c_accessor_get_expr(field.type.expr, fields)
1637 _c(' return %s;', length)
1640 if field.type.member.is_simple:
1642 _hc('xcb_generic_iterator_t')
1643 if switch_obj is not None:
1644 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1645 spacing = ' '*(len(field.c_end_name)+2)
1646 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1647 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1649 _h('%s (const %s *R /**< */);', field.c_end_name, c_type)
1650 _c('%s (const %s *R /**< */)', field.c_end_name, c_type)
1652 _c(' xcb_generic_iterator_t i;')
1654 param = 'R' if switch_obj is None else 'S'
1655 if switch_obj is not None:
1656 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1657 _c_accessor_get_expr(field.type.expr, fields))
1658 elif field.prev_varsized_field == None:
1659 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1660 _c_accessor_get_expr(field.type.expr, fields))
1662 _c(' xcb_generic_iterator_t child = %s;',
1663 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1664 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1665 _c_accessor_get_expr(field.type.expr, fields))
1668 _c(' i.index = (char *) i.data - (char *) %s;', param)
1674 _hc('%s', field.c_iterator_type)
1675 if switch_obj is not None:
1676 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1677 spacing = ' '*(len(field.c_iterator_name)+2)
1678 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1679 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1681 _h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
1682 _c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
1684 _c(' %s i;', field.c_iterator_type)
1686 if switch_obj is not None:
1687 _c(' i.data = %s;', fields[field.c_field_name][0])
1688 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1689 elif field.prev_varsized_field == None:
1690 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1692 (prev_varsized_field, align_pad) = get_align_pad(field)
1694 if align_pad is None:
1695 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
1696 type_pad_type(field.c_field_type))
1698 _c(' xcb_generic_iterator_t prev = %s;',
1699 _c_iterator_get_end(prev_varsized_field, 'R'))
1700 _c(' i.data = (%s *) ((char *) prev.data + %s);',
1701 field.c_field_type, align_pad)
1703 if switch_obj is None:
1704 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1705 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1709 def _c_accessors(self, name, base):
1711 Declares the accessor functions for the fields of a structure.
1713 # no accessors for switch itself -
1714 # switch always needs to be unpacked explicitly
1715 # if self.is_switch:
1719 for field in self.fields:
1720 if not field.type.is_pad:
1721 if field.type.is_list and not field.type.fixed_size():
1722 _c_accessors_list(self, field)
1723 elif field.prev_varsized_field is not None or not field.type.fixed_size():
1724 _c_accessors_field(self, field)
1726 def c_simple(self, name):
1728 Exported function that handles cardinal type declarations.
1729 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1731 _c_type_setup(self, name, ())
1733 if (self.name != name):
1738 _h('typedef %s %s;', _t(self.name), my_name)
1741 _c_iterator(self, name)
1743 def _c_complex(self, force_packed = False):
1745 Helper function for handling all structure types.
1746 Called for all structs, requests, replies, events, errors.
1751 _h(' * @brief %s', self.c_type)
1753 _h('typedef %s %s {', self.c_container, self.c_type)
1759 for field in self.fields:
1760 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1761 varfield = field.c_field_name
1764 struct_fields.append(field)
1766 for field in struct_fields:
1767 length = len(field.c_field_type)
1768 # account for '*' pointer_spec
1769 if not field.type.fixed_size() and not self.is_union:
1771 maxtypelen = max(maxtypelen, length)
1773 def _c_complex_field(self, field, space=''):
1774 if (field.type.fixed_size() or self.is_union or
1775 # in case of switch with switch children, don't make the field a pointer
1776 # necessary for unserialize to work
1777 (self.is_switch and field.type.is_switch)):
1778 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1779 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1781 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1782 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1784 if not self.is_switch:
1785 for field in struct_fields:
1786 _c_complex_field(self, field)
1788 for b in self.bitcases:
1791 _h(' struct _%s {', b.c_field_name)
1793 for field in b.type.fields:
1794 _c_complex_field(self, field, space)
1796 _h(' } %s;', b.c_field_name)
1798 _h('} %s%s;', 'XCB_PACKED ' if force_packed else '', self.c_type)
1800 def c_struct(self, name):
1802 Exported function that handles structure declarations.
1804 _c_type_setup(self, name, ())
1806 _c_accessors(self, name, name)
1807 _c_iterator(self, name)
1809 def c_union(self, name):
1811 Exported function that handles union declarations.
1813 _c_type_setup(self, name, ())
1815 _c_iterator(self, name)
1817 def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_fds=False):
1819 Declares a request function.
1822 # Four stunningly confusing possibilities here:
1825 # ------------------------------
1827 # 0 flag CHECKED flag Normal Mode
1828 # void_cookie req_cookie
1829 # ------------------------------
1830 # "req_checked" "req_unchecked"
1831 # CHECKED flag 0 flag Abnormal Mode
1832 # void_cookie req_cookie
1833 # ------------------------------
1836 # Whether we are _checked or _unchecked
1837 checked = void and not regular
1838 unchecked = not void and not regular
1840 # What kind of cookie we return
1841 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1843 # What flag is passed to xcb_request
1844 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1847 if func_flags == '0':
1848 func_flags = 'XCB_REQUEST_REPLY_FDS'
1850 func_flags = func_flags + '|XCB_REQUEST_REPLY_FDS'
1852 # Global extension id variable or NULL for xproto
1853 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1855 # What our function name is
1856 func_name = self.c_request_name if not aux else self.c_aux_name
1858 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1860 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1864 maxtypelen = len('xcb_connection_t')
1866 # special case: list with variable size elements
1867 list_with_var_size_elems = False
1869 for field in self.fields:
1871 # The field should appear as a call parameter
1872 param_fields.append(field)
1873 if field.wire and not field.auto:
1874 # We need to set the field up in the structure
1875 wire_fields.append(field)
1876 if field.type.c_need_serialize or field.type.c_need_sizeof:
1877 serial_fields.append(field)
1879 for field in param_fields:
1880 c_field_const_type = field.c_field_const_type
1881 if field.type.c_need_serialize and not aux:
1882 c_field_const_type = "const void"
1883 if len(c_field_const_type) > maxtypelen:
1884 maxtypelen = len(c_field_const_type)
1885 if field.type.is_list and not field.type.member.fixed_size():
1886 list_with_var_size_elems = True
1892 if hasattr(self, "doc") and self.doc:
1894 _h(' * @brief ' + self.doc.brief)
1896 _h(' * No brief doc yet')
1899 _h(' * @param c The connection')
1900 param_names = [f.c_field_name for f in param_fields]
1901 if hasattr(self, "doc") and self.doc:
1902 for field in param_fields:
1903 # XXX: hard-coded until we fix xproto.xml
1904 base_func_name = self.c_request_name if not aux else self.c_aux_name
1905 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
1907 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
1909 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
1912 # XXX: why the 'xcb' prefix?
1913 key = ('xcb', field.enum)
1916 if namecount[tname] > 1:
1917 tname = _t(key + ('enum',))
1918 _h(' * @param %s A bitmask of #%s values.' % (field.c_field_name, tname))
1920 if self.doc and field.field_name in self.doc.fields:
1921 desc = self.doc.fields[field.field_name]
1922 for name in param_names:
1923 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1924 desc = desc.split("\n")
1925 desc = [line if line != '' else '\\n' for line in desc]
1926 _h(' * @param %s %s' % (field.c_field_name, "\n * ".join(desc)))
1927 # If there is no documentation yet, we simply don't generate an
1928 # @param tag. Doxygen will then warn about missing documentation.
1930 _h(' * @return A cookie')
1933 if hasattr(self, "doc") and self.doc:
1934 if self.doc.description:
1935 desc = self.doc.description
1936 for name in param_names:
1937 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1938 desc = desc.split("\n")
1939 _h(' * ' + "\n * ".join(desc))
1941 _h(' * No description yet')
1943 _h(' * Delivers a request to the X server.')
1946 _h(' * This form can be used only if the request will not cause')
1947 _h(' * a reply to be generated. Any returned error will be')
1948 _h(' * saved for handling by xcb_request_check().')
1950 _h(' * This form can be used only if the request will cause')
1951 _h(' * a reply to be generated. Any returned error will be')
1952 _h(' * placed in the event queue.')
1955 _hc('%s', cookie_type)
1957 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1958 comma = ',' if len(param_fields) else ');'
1959 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1960 comma = ',' if len(param_fields) else ')'
1961 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1963 func_spacing = ' ' * (len(func_name) + 2)
1964 count = len(param_fields)
1965 for field in param_fields:
1967 c_field_const_type = field.c_field_const_type
1968 c_pointer = field.c_pointer
1969 if field.type.c_need_serialize and not aux:
1970 c_field_const_type = "const void"
1972 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1973 comma = ',' if count else ');'
1974 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1975 spacing, c_pointer, field.c_field_name, comma)
1976 comma = ',' if count else ')'
1977 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1978 spacing, c_pointer, field.c_field_name, comma)
1981 if not self.c_var_followed_by_fixed_fields:
1982 for field in param_fields:
1983 if not field.type.fixed_size():
1985 if field.type.c_need_serialize:
1986 # _serialize() keeps track of padding automatically
1988 dimension = count + 2
1991 _c(' static const xcb_protocol_request_t xcb_req = {')
1992 _c(' /* count */ %d,', count)
1993 _c(' /* ext */ %s,', func_ext_global)
1994 _c(' /* opcode */ %s,', self.c_request_name.upper())
1995 _c(' /* isvoid */ %d', 1 if void else 0)
1999 _c(' struct iovec xcb_parts[%d];', dimension)
2000 _c(' %s xcb_ret;', func_cookie)
2001 _c(' %s xcb_out;', self.c_type)
2002 if self.c_var_followed_by_fixed_fields:
2003 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
2004 _c(' void *xcb_aux = 0;')
2007 for idx, f in enumerate(serial_fields):
2009 _c(' void *xcb_aux%d = 0;' % (idx))
2010 if list_with_var_size_elems:
2011 _c(' unsigned int i;')
2012 _c(' unsigned int xcb_tmp_len;')
2013 _c(' char *xcb_tmp;')
2015 # simple request call tracing
2016 # _c(' printf("in function %s\\n");' % func_name)
2019 for field in wire_fields:
2020 if field.type.fixed_size():
2021 if field.type.is_expr:
2022 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
2023 elif field.type.is_pad:
2024 if field.type.nmemb == 1:
2025 _c(' xcb_out.%s = 0;', field.c_field_name)
2027 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
2029 if field.type.nmemb == 1:
2030 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
2032 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
2034 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
2035 serialize_args = get_serialize_params(context, type_obj,
2038 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
2040 # calls in order to free dyn. all. memory
2044 if not self.c_var_followed_by_fixed_fields:
2045 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2046 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
2047 _c(' xcb_parts[3].iov_base = 0;')
2048 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2052 for field in param_fields:
2053 if not field.type.fixed_size():
2054 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
2055 # default: simple cast to char *
2056 if not field.type.c_need_serialize and not field.type.c_need_sizeof:
2057 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2058 if field.type.is_list:
2059 if field.type.member.fixed_size():
2060 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
2061 _c_accessor_get_expr(field.type.expr, None),
2062 field.type.member.c_wiretype)
2064 list_length = _c_accessor_get_expr(field.type.expr, None)
2067 _c(" xcb_parts[%d].iov_len = 0;" % count)
2068 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2069 _c(" for(i=0; i<%s; i++) {" % list_length)
2070 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2071 (field.type.c_sizeof_name))
2072 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2073 _c(" xcb_tmp += xcb_tmp_len;")
2076 # not supposed to happen
2077 raise Exception("unhandled variable size field %s" % field.c_field_name)
2080 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2081 idx = serial_fields.index(field)
2082 aux_var = '&xcb_aux%d' % idx
2083 context = 'serialize' if aux else 'sizeof'
2084 _c(' xcb_parts[%d].iov_len =', count)
2086 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2087 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2088 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2089 free_calls.append(' free(xcb_aux%d);' % idx)
2091 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2092 func_name = field.type.c_sizeof_name
2093 _c(' %s (%s);', func_name, serialize_args)
2096 if not (field.type.c_need_serialize or field.type.c_need_sizeof):
2097 # the _serialize() function keeps track of padding automatically
2098 _c(' xcb_parts[%d].iov_base = 0;', count)
2099 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2102 # elif self.c_var_followed_by_fixed_fields:
2104 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2105 # request header: opcodes + length
2106 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2109 buffer_var = '&xcb_aux'
2110 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2111 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2112 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2113 free_calls.append(' free(xcb_aux);')
2114 # no padding necessary - _serialize() keeps track of padding automatically
2117 for field in param_fields:
2119 _c(' xcb_send_fd(c, %s);', field.c_field_name)
2121 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2123 # free dyn. all. data, if any
2124 for f in free_calls:
2126 _c(' return xcb_ret;')
2129 def _c_reply(self, name):
2131 Declares the function that returns the reply structure.
2133 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2134 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2135 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2137 # check if _unserialize() has to be called for any field
2138 def look_for_special_cases(complex_obj):
2139 unserialize_fields = []
2140 # no unserialize call in case of switch
2141 if not complex_obj.is_switch:
2142 for field in complex_obj.fields:
2143 # three cases: 1. field with special case
2144 # 2. container that contains special case field
2145 # 3. list with special case elements
2146 if field.type.c_var_followed_by_fixed_fields:
2147 unserialize_fields.append(field)
2148 elif field.type.is_container:
2149 unserialize_fields += look_for_special_cases(field.type)
2150 elif field.type.is_list:
2151 if field.type.member.c_var_followed_by_fixed_fields:
2152 unserialize_fields.append(field)
2153 if field.type.member.is_container:
2154 unserialize_fields += look_for_special_cases(field.type.member)
2155 return unserialize_fields
2157 unserialize_fields = look_for_special_cases(self.reply)
2161 _h(' * Return the reply')
2162 _h(' * @param c The connection')
2163 _h(' * @param cookie The cookie')
2164 _h(' * @param e The xcb_generic_error_t supplied')
2166 _h(' * Returns the reply of the request asked by')
2168 _h(' * The parameter @p e supplied to this function must be NULL if')
2169 _h(' * %s(). is used.', self.c_unchecked_name)
2170 _h(' * Otherwise, it stores the error if any.')
2172 _h(' * The returned value must be freed by the caller using free().')
2175 _hc('%s *', self.c_reply_type)
2176 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2177 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2178 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2179 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2182 if len(unserialize_fields)>0:
2183 # certain variable size fields need to be unserialized explicitly
2184 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2185 self.c_reply_type, self.c_reply_type)
2187 for field in unserialize_fields:
2188 if field.type.is_list:
2189 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2190 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2191 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2193 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2194 # call _unserialize(), using the reply as source and target buffer
2195 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2196 for field in unserialize_fields:
2197 if field.type.is_list:
2198 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2199 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2200 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2201 field.c_field_name, field.c_field_name)
2202 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2204 # return the transformed reply
2205 _c(' return reply;')
2208 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2212 def _c_reply_has_fds(self):
2213 for field in self.fields:
2218 def _c_reply_fds(self, name):
2220 Declares the function that returns fds related to the reply.
2222 spacing1 = ' ' * (len(self.c_reply_type) - len('xcb_connection_t'))
2223 spacing3 = ' ' * (len(self.c_reply_fds_name) + 2)
2226 _h(' * Return the reply fds')
2227 _h(' * @param c The connection')
2228 _h(' * @param reply The reply')
2230 _h(' * Returns the array of reply fds of the request asked by')
2232 _h(' * The returned value must be freed by the caller using free().')
2236 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_fds_name, spacing1)
2237 _h('%s%s *reply /**< */);', spacing3, self.c_reply_type)
2238 _c('%s%s *reply /**< */)', spacing3, self.c_reply_type)
2241 _c(' return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
2246 def _c_opcode(name, opcode):
2248 Declares the opcode define for requests, events, and errors.
2252 _h('/** Opcode for %s. */', _n(name))
2253 _h('#define %s %s', _n(name).upper(), opcode)
2255 def _c_cookie(self, name):
2257 Declares the cookie type for a non-void request.
2262 _h(' * @brief %s', self.c_cookie_type)
2264 _h('typedef struct %s {', self.c_cookie_type)
2265 _h(' unsigned int sequence; /**< */')
2266 _h('} %s;', self.c_cookie_type)
2268 def _man_request(self, name, cookie_type, void, aux):
2269 param_fields = [f for f in self.fields if f.visible]
2271 func_name = self.c_request_name if not aux else self.c_aux_name
2273 def create_link(linkname):
2274 name = 'man/%s.%s' % (linkname, section)
2276 sys.stdout.write(name)
2278 f.write('.so man%s/%s.%s' % (section, func_name, section))
2282 sys.stdout.write('man/%s.%s ' % (func_name, section))
2283 # Our CWD is src/, so this will end up in src/man/
2284 f = open('man/%s.%s' % (func_name, section), 'w')
2285 f.write('.TH %s %s "%s" "%s" "XCB Requests"\n' % (func_name, section, center_footer, left_footer))
2286 # Left-adjust instead of adjusting to both sides
2288 f.write('.SH NAME\n')
2289 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2290 f.write('%s \\- %s\n' % (func_name, brief))
2291 f.write('.SH SYNOPSIS\n')
2292 # Don't split words (hyphenate)
2294 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2296 # function prototypes
2298 count = len(param_fields)
2299 for field in param_fields:
2301 c_field_const_type = field.c_field_const_type
2302 c_pointer = field.c_pointer
2303 if c_pointer == ' ':
2305 if field.type.c_need_serialize and not aux:
2306 c_field_const_type = "const void"
2308 comma = ', ' if count else ');'
2309 prototype += '%s\\ %s\\fI%s\\fP%s' % (c_field_const_type, c_pointer, field.c_field_name, comma)
2311 f.write('.SS Request function\n')
2313 base_func_name = self.c_request_name if not aux else self.c_aux_name
2314 f.write('%s \\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\n' % (cookie_type, base_func_name, prototype))
2315 create_link('%s_%s' % (base_func_name, ('checked' if void else 'unchecked')))
2318 f.write('.SS Reply datastructure\n')
2321 f.write('typedef %s %s {\n' % (self.reply.c_container, self.reply.c_type))
2325 for field in self.reply.fields:
2326 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2329 struct_fields.append(field)
2331 for field in struct_fields:
2332 length = len(field.c_field_type)
2333 # account for '*' pointer_spec
2334 if not field.type.fixed_size():
2336 maxtypelen = max(maxtypelen, length)
2338 def _c_complex_field(self, field, space=''):
2339 if (field.type.fixed_size() or
2340 # in case of switch with switch children, don't make the field a pointer
2341 # necessary for unserialize to work
2342 (self.is_switch and field.type.is_switch)):
2343 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2344 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2346 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
2347 f.write('ELSE %s = %s\n' % (field.c_field_type, field.c_field_name))
2348 #_h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2350 if not self.is_switch:
2351 for field in struct_fields:
2352 _c_complex_field(self, field)
2354 for b in self.bitcases:
2358 for field in b.type.fields:
2359 _c_complex_field(self, field, space)
2361 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2364 f.write('} \\fB%s\\fP;\n' % self.reply.c_type)
2367 f.write('.SS Reply function\n')
2369 f.write(('%s *\\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\\ '
2370 '\\fIcookie\\fP, xcb_generic_error_t\\ **\\fIe\\fP);\n') %
2371 (self.c_reply_type, self.c_reply_name, self.c_cookie_type))
2372 create_link('%s' % self.c_reply_name)
2374 has_accessors = False
2375 for field in self.reply.fields:
2376 if field.type.is_list and not field.type.fixed_size():
2377 has_accessors = True
2378 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2379 has_accessors = True
2382 f.write('.SS Reply accessors\n')
2384 def _c_accessors_field(self, field):
2386 Declares the accessor functions for a non-list field that follows a variable-length field.
2388 c_type = self.c_type
2390 # special case: switch
2391 switch_obj = self if self.is_switch else None
2392 if self.is_case_or_bitcase:
2393 switch_obj = self.parents[-1]
2394 if switch_obj is not None:
2395 c_type = switch_obj.c_type
2397 if field.type.is_simple:
2398 f.write('%s %s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2399 create_link('%s' % field.c_accessor_name)
2401 f.write('%s *%s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2402 create_link('%s' % field.c_accessor_name)
2404 def _c_accessors_list(self, field):
2406 Declares the accessor functions for a list field.
2407 Declares a direct-accessor function only if the list members are fixed size.
2408 Declares length and get-iterator functions always.
2411 c_type = self.reply.c_type
2413 # special case: switch
2414 # in case of switch, 2 params have to be supplied to certain accessor functions:
2415 # 1. the anchestor object (request or reply)
2416 # 2. the (anchestor) switch object
2417 # the reason is that switch is either a child of a request/reply or nested in another switch,
2418 # so whenever we need to access a length field, we might need to refer to some anchestor type
2419 switch_obj = self if self.is_switch else None
2420 if self.is_case_or_bitcase:
2421 switch_obj = self.parents[-1]
2422 if switch_obj is not None:
2423 c_type = switch_obj.c_type
2427 parents = self.parents if hasattr(self, 'parents') else [self]
2428 # 'R': parents[0] is always the 'toplevel' container type
2429 params.append(('const %s *\\fIreply\\fP' % parents[0].c_type, parents[0]))
2430 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
2431 # auxiliary object for 'R' parameters
2434 if switch_obj is not None:
2435 # now look where the fields are defined that are needed to evaluate
2436 # the switch expr, and store the parent objects in accessor_params and
2437 # the fields in switch_fields
2439 # 'S': name for the 'toplevel' switch
2440 toplevel_switch = parents[1]
2441 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
2442 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
2444 # initialize prefix for everything "below" S
2445 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
2446 prefix = [(prefix_str, '->', toplevel_switch)]
2448 # look for fields in the remaining containers
2449 for p in parents[2:] + [self]:
2450 # the separator between parent and child is always '.' here,
2451 # because of nested switch statements
2452 if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
2453 prefix.append((p.name[-1], '.', p))
2454 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
2456 # auxiliary object for 'S' parameter
2459 if list.member.fixed_size():
2460 idx = 1 if switch_obj is not None else 0
2462 f.write('%s *\\fB%s\\fP(%s);\n' %
2463 (field.c_field_type, field.c_accessor_name, params[idx][0]))
2464 create_link('%s' % field.c_accessor_name)
2467 f.write('int \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2468 (field.c_length_name, c_type))
2469 create_link('%s' % field.c_length_name)
2471 if field.type.member.is_simple:
2473 f.write('xcb_generic_iterator_t \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2474 (field.c_end_name, c_type))
2475 create_link('%s' % field.c_end_name)
2478 f.write('%s \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2479 (field.c_iterator_type, field.c_iterator_name,
2481 create_link('%s' % field.c_iterator_name)
2483 for field in self.reply.fields:
2484 if field.type.is_list and not field.type.fixed_size():
2485 _c_accessors_list(self, field)
2486 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2487 _c_accessors_field(self, field)
2491 # Re-enable hyphenation and adjusting to both sides
2494 # argument reference
2495 f.write('.SH REQUEST ARGUMENTS\n')
2496 f.write('.IP \\fI%s\\fP 1i\n' % 'conn')
2497 f.write('The XCB connection to X11.\n')
2498 for field in param_fields:
2499 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2500 printed_enum = False
2501 # XXX: hard-coded until we fix xproto.xml
2502 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
2504 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
2506 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
2508 if hasattr(field, "enum") and field.enum:
2509 # XXX: why the 'xcb' prefix?
2510 key = ('xcb', field.enum)
2512 f.write('One of the following values:\n')
2515 count = len(enum.values)
2516 for (enam, eval) in enum.values:
2518 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2519 if hasattr(enum, "doc") and enum.doc and enam in enum.doc.fields:
2520 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2521 f.write('%s\n' % desc)
2523 f.write('TODO: NOT YET DOCUMENTED.\n')
2528 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2529 desc = self.doc.fields[field.field_name]
2530 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2533 f.write('%s\n' % desc)
2535 f.write('TODO: NOT YET DOCUMENTED.\n')
2541 f.write('.SH REPLY FIELDS\n')
2542 # These fields are present in every reply:
2543 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2544 f.write(('The type of this reply, in this case \\fI%s\\fP. This field '
2545 'is also present in the \\fIxcb_generic_reply_t\\fP and can '
2546 'be used to tell replies apart from each other.\n') %
2547 _n(self.reply.name).upper())
2548 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2549 f.write('The sequence number of the last request processed by the X11 server.\n')
2550 f.write('.IP \\fI%s\\fP 1i\n' % 'length')
2551 f.write('The length of the reply, in words (a word is 4 bytes).\n')
2552 for field in self.reply.fields:
2553 if (field.c_field_name in frozenset(['response_type', 'sequence', 'length']) or
2554 field.c_field_name.startswith('pad')):
2557 if field.type.is_list and not field.type.fixed_size():
2559 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2561 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2562 printed_enum = False
2563 if hasattr(field, "enum") and field.enum:
2564 # XXX: why the 'xcb' prefix?
2565 key = ('xcb', field.enum)
2567 f.write('One of the following values:\n')
2570 count = len(enum.values)
2571 for (enam, eval) in enum.values:
2573 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2574 if enum.doc and enam in enum.doc.fields:
2575 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2576 f.write('%s\n' % desc)
2578 f.write('TODO: NOT YET DOCUMENTED.\n')
2583 if hasattr(self.reply, "doc") and self.reply.doc and field.field_name in self.reply.doc.fields:
2584 desc = self.reply.doc.fields[field.field_name]
2585 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2588 f.write('%s\n' % desc)
2590 f.write('TODO: NOT YET DOCUMENTED.\n')
2597 f.write('.SH DESCRIPTION\n')
2598 if hasattr(self, "doc") and self.doc and self.doc.description:
2599 desc = self.doc.description
2600 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2601 lines = desc.split('\n')
2602 f.write('\n'.join(lines) + '\n')
2604 f.write('.SH RETURN VALUE\n')
2606 f.write(('Returns an \\fIxcb_void_cookie_t\\fP. Errors (if any) '
2607 'have to be handled in the event loop.\n\nIf you want to '
2608 'handle errors directly with \\fIxcb_request_check\\fP '
2609 'instead, use \\fI%s_checked\\fP. See '
2610 '\\fBxcb-requests(%s)\\fP for details.\n') % (base_func_name, section))
2612 f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
2613 'calling the reply function \\fI%s\\fP.\n\nIf you want to '
2614 'handle errors in the event loop instead, use '
2615 '\\fI%s_unchecked\\fP. See \\fBxcb-requests(%s)\\fP for '
2617 (cookie_type, self.c_reply_name, base_func_name, section))
2618 f.write('.SH ERRORS\n')
2619 if hasattr(self, "doc") and self.doc:
2620 for errtype, errtext in sorted(self.doc.errors.items()):
2621 f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
2622 errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
2623 f.write('%s\n' % (errtext))
2624 if not hasattr(self, "doc") or not self.doc or len(self.doc.errors) == 0:
2625 f.write('This request does never generate any errors.\n')
2626 if hasattr(self, "doc") and self.doc and self.doc.example:
2627 f.write('.SH EXAMPLE\n')
2630 lines = self.doc.example.split('\n')
2631 f.write('\n'.join(lines) + '\n')
2633 f.write('.SH SEE ALSO\n')
2634 if hasattr(self, "doc") and self.doc:
2635 see = ['.BR %s (%s)' % ('xcb-requests', section)]
2636 if self.doc.example:
2637 see.append('.BR %s (%s)' % ('xcb-examples', section))
2638 for seename, seetype in sorted(self.doc.see.items()):
2639 if seetype == 'program':
2640 see.append('.BR %s (1)' % seename)
2641 elif seetype == 'event':
2642 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2643 elif seetype == 'request':
2644 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2645 elif seetype == 'function':
2646 see.append('.BR %s (%s)' % (seename, section))
2648 see.append('TODO: %s (type %s)' % (seename, seetype))
2649 f.write(',\n'.join(see) + '\n')
2650 f.write('.SH AUTHOR\n')
2651 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2654 def _man_event(self, name):
2656 sys.stdout.write('man/%s.%s ' % (self.c_type, section))
2657 # Our CWD is src/, so this will end up in src/man/
2658 f = open('man/%s.%s' % (self.c_type, section), 'w')
2659 f.write('.TH %s %s "%s" "%s" "XCB Events"\n' % (self.c_type, section, center_footer, left_footer))
2660 # Left-adjust instead of adjusting to both sides
2662 f.write('.SH NAME\n')
2663 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2664 f.write('%s \\- %s\n' % (self.c_type, brief))
2665 f.write('.SH SYNOPSIS\n')
2666 # Don't split words (hyphenate)
2668 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2671 f.write('.SS Event datastructure\n')
2674 f.write('typedef %s %s {\n' % (self.c_container, self.c_type))
2678 for field in self.fields:
2679 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2682 struct_fields.append(field)
2684 for field in struct_fields:
2685 length = len(field.c_field_type)
2686 # account for '*' pointer_spec
2687 if not field.type.fixed_size():
2689 maxtypelen = max(maxtypelen, length)
2691 def _c_complex_field(self, field, space=''):
2692 if (field.type.fixed_size() or
2693 # in case of switch with switch children, don't make the field a pointer
2694 # necessary for unserialize to work
2695 (self.is_switch and field.type.is_switch)):
2696 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2697 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2699 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2701 if not self.is_switch:
2702 for field in struct_fields:
2703 _c_complex_field(self, field)
2705 for b in self.bitcases:
2709 for field in b.type.fields:
2710 _c_complex_field(self, field, space)
2712 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2715 f.write('} \\fB%s\\fP;\n' % self.c_type)
2720 # Re-enable hyphenation and adjusting to both sides
2723 # argument reference
2724 f.write('.SH EVENT FIELDS\n')
2725 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2726 f.write(('The type of this event, in this case \\fI%s\\fP. This field is '
2727 'also present in the \\fIxcb_generic_event_t\\fP and can be used '
2728 'to tell events apart from each other.\n') % _n(name).upper())
2729 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2730 f.write('The sequence number of the last request processed by the X11 server.\n')
2732 if not self.is_switch:
2733 for field in struct_fields:
2734 # Skip the fields which every event has, we already documented
2736 if field.c_field_name in ('response_type', 'sequence'):
2738 if isinstance(field.type, PadType):
2740 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2741 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2742 desc = self.doc.fields[field.field_name]
2743 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2744 f.write('%s\n' % desc)
2746 f.write('NOT YET DOCUMENTED.\n')
2749 f.write('.SH DESCRIPTION\n')
2750 if hasattr(self, "doc") and self.doc and self.doc.description:
2751 desc = self.doc.description
2752 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2753 lines = desc.split('\n')
2754 f.write('\n'.join(lines) + '\n')
2756 if hasattr(self, "doc") and self.doc and self.doc.example:
2757 f.write('.SH EXAMPLE\n')
2760 lines = self.doc.example.split('\n')
2761 f.write('\n'.join(lines) + '\n')
2763 f.write('.SH SEE ALSO\n')
2764 if hasattr(self, "doc") and self.doc:
2765 see = ['.BR %s (%s)' % ('xcb_generic_event_t', section)]
2766 if self.doc.example:
2767 see.append('.BR %s (%s)' % ('xcb-examples', section))
2768 for seename, seetype in sorted(self.doc.see.items()):
2769 if seetype == 'program':
2770 see.append('.BR %s (1)' % seename)
2771 elif seetype == 'event':
2772 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2773 elif seetype == 'request':
2774 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2775 elif seetype == 'function':
2776 see.append('.BR %s (%s)' % (seename, section))
2778 see.append('TODO: %s (type %s)' % (seename, seetype))
2779 f.write(',\n'.join(see) + '\n')
2780 f.write('.SH AUTHOR\n')
2781 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2785 def c_request(self, name):
2787 Exported function that handles request declarations.
2789 _c_type_setup(self, name, ('request',))
2792 # Cookie type declaration
2793 _c_cookie(self, name)
2796 _c_opcode(name, self.opcode)
2798 # Request structure declaration
2802 _c_type_setup(self.reply, name, ('reply',))
2803 # Reply structure definition
2804 _c_complex(self.reply)
2805 # Request prototypes
2806 has_fds = _c_reply_has_fds(self.reply)
2807 _c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds)
2808 _c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds)
2810 _c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds)
2811 _c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds)
2813 _c_accessors(self.reply, name + ('reply',), name)
2814 _c_reply(self, name)
2816 _c_reply_fds(self, name)
2818 # Request prototypes
2819 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2820 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2822 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2823 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2825 # We generate the manpage afterwards because _c_type_setup has been called.
2826 # TODO: what about aux helpers?
2827 cookie_type = self.c_cookie_type if self.reply else 'xcb_void_cookie_t'
2828 _man_request(self, name, cookie_type, not self.reply, False)
2830 def c_event(self, name):
2832 Exported function that handles event declarations.
2835 # The generic event structure xcb_ge_event_t has the full_sequence field
2836 # at the 32byte boundary. That's why we've to inject this field into GE
2837 # events while generating the structure for them. Otherwise we would read
2838 # garbage (the internal full_sequence) when accessing normal event fields
2840 force_packed = False
2841 if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
2843 for field in self.fields:
2844 if field.type.size != None and field.type.nmemb != None:
2845 event_size += field.type.size * field.type.nmemb
2846 if event_size == 32:
2847 full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
2848 idx = self.fields.index(field)
2849 self.fields.insert(idx + 1, full_sequence)
2851 # If the event contains any 64-bit extended fields, they need
2852 # to remain aligned on a 64-bit boundary. Adding full_sequence
2853 # would normally break that; force the struct to be packed.
2854 force_packed = any(f.type.size == 8 and f.type.is_simple for f in self.fields[(idx+1):])
2857 _c_type_setup(self, name, ('event',))
2860 _c_opcode(name, self.opcodes[name])
2862 if self.name == name:
2863 # Structure definition
2864 _c_complex(self, force_packed)
2868 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2870 _man_event(self, name)
2872 def c_error(self, name):
2874 Exported function that handles error declarations.
2876 _c_type_setup(self, name, ('error',))
2879 _c_opcode(name, self.opcodes[name])
2881 if self.name == name:
2882 # Structure definition
2887 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2890 # Main routine starts here
2892 # Must create an "output" dictionary before any xcbgen imports.
2893 output = {'open' : c_open,
2895 'simple' : c_simple,
2897 'struct' : c_struct,
2899 'request' : c_request,
2904 # Boilerplate below this point
2906 # Check for the argument that specifies path to the xcbgen python package.
2908 opts, args = getopt.getopt(sys.argv[1:], 'c:l:s:p:m')
2909 except getopt.GetoptError as err:
2911 print('Usage: c_client.py -c center_footer -l left_footer -s section [-p path] file.xml')
2914 for (opt, arg) in opts:
2922 sys.path.insert(1, arg)
2925 sys.stdout.write('man_MANS = ')
2927 # Import the module class
2929 from xcbgen.state import Module
2930 from xcbgen.xtypes import *
2933 Failed to load the xcbgen Python package!
2934 Make sure that xcb/proto installed it on your Python path.
2935 If not, you will need to create a .pth file or define $PYTHONPATH
2937 Refer to the README file in xcb/proto for more info.
2941 # Ensure the man subdirectory exists
2944 except OSError as e:
2945 if e.errno != errno.EEXIST:
2948 # Parse the xml header
2949 module = Module(args[0], output)
2951 # Build type-registry and resolve type dependencies