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
361 elif not field.type.fixed_size() and not field.type.is_case_or_bitcase:
362 self.c_need_sizeof = True
364 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
365 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
366 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
367 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
368 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
370 field.prev_varsized_field = prev_varsized_field
371 field.prev_varsized_offset = prev_varsized_offset
373 if prev_varsized_offset == 0:
374 first_field_after_varsized = field
375 field.first_field_after_varsized = first_field_after_varsized
377 if field.type.fixed_size():
378 prev_varsized_offset += field.type.size
379 # special case: intermixed fixed and variable size fields
380 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
381 if not self.is_union:
382 self.c_need_serialize = True
383 self.c_var_followed_by_fixed_fields = True
385 self.last_varsized_field = field
386 prev_varsized_field = field
387 prev_varsized_offset = 0
389 if self.c_var_followed_by_fixed_fields:
390 if field.type.fixed_size():
391 field.prev_varsized_field = None
393 if self.c_need_serialize:
394 # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
395 self.c_need_sizeof = True
397 # as switch does never appear at toplevel,
398 # continue here with type construction
400 if self.c_type not in finished_switch:
401 finished_switch.append(self.c_type)
402 # special: switch C structs get pointer fields for variable-sized members
404 for bitcase in self.bitcases:
405 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
406 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
407 # no list with switch as element, so no call to
408 # _c_iterator(field.type, field_name) necessary
410 if not self.is_case_or_bitcase:
411 if self.c_need_serialize:
412 if self.c_serialize_name not in finished_serializers:
413 finished_serializers.append(self.c_serialize_name)
414 _c_serialize('serialize', self)
416 # _unpack() and _unserialize() are only needed for special cases:
418 # special cases -> unserialize
419 if self.is_switch or self.c_var_followed_by_fixed_fields:
420 _c_serialize('unserialize', self)
422 if self.c_need_sizeof:
423 if self.c_sizeof_name not in finished_sizeof:
424 if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
425 finished_sizeof.append(self.c_sizeof_name)
426 _c_serialize('sizeof', self)
429 def _c_helper_absolute_name(prefix, field=None):
431 turn prefix, which is a list of tuples (name, separator, Type obj) into a string
432 representing a valid name in C (based on the context)
433 if field is not None, append the field name as well
436 for name, sep, obj in prefix:
440 if ((obj.is_case_or_bitcase and obj.has_name) or # named bitcase
441 (obj.is_switch and len(obj.parents)>1)):
444 if field is not None:
445 prefix_str += _cpp(field.field_name)
449 def _c_helper_field_mapping(complex_type, prefix, flat=False):
451 generate absolute names, based on prefix, for all fields starting from complex_type
452 if flat == True, nested complex types are not taken into account
455 if complex_type.is_switch:
456 for b in complex_type.bitcases:
458 switch_name, switch_sep, switch_type = prefix[-1]
459 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
461 bitcase_prefix = prefix
463 if (True==flat and not b.type.has_name) or False==flat:
464 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
466 for f in complex_type.fields:
467 fname = _c_helper_absolute_name(prefix, f)
468 if f.field_name in all_fields:
469 raise Exception("field name %s has been registered before" % f.field_name)
471 all_fields[f.field_name] = (fname, f)
472 if f.type.is_container and flat==False:
473 if f.type.is_case_or_bitcase and not f.type.has_name:
475 elif f.type.is_switch and len(f.type.parents)>1:
476 # nested switch gets another separator
477 new_prefix = prefix+[(f.c_field_name, '.', f.type)]
479 new_prefix = prefix+[(f.c_field_name, '->', f.type)]
480 all_fields.update(_c_helper_field_mapping(f.type, new_prefix, flat))
485 def _c_helper_resolve_field_names (prefix):
487 get field names for all objects in the prefix array
491 # look for fields in the remaining containers
492 for idx, p in enumerate(prefix):
495 # sep can be preset in prefix, if not, make a sensible guess
496 sep = '.' if (obj.is_switch or obj.is_case_or_bitcase) else '->'
497 # exception: 'toplevel' object (switch as well!) always have sep '->'
498 sep = '->' if idx<1 else sep
499 if not obj.is_case_or_bitcase or (obj.is_case_or_bitcase and obj.has_name):
500 tmp_prefix.append((name, sep, obj))
501 all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
504 # _c_helper_resolve_field_names
506 def get_expr_fields(self):
508 get the Fields referenced by switch or list expression
510 def get_expr_field_names(expr):
512 if expr.lenfield_name is not None:
513 return [expr.lenfield_name]
515 # constant value expr
519 return get_expr_field_names(expr.rhs)
520 elif expr.op == 'popcount':
521 return get_expr_field_names(expr.rhs)
522 elif expr.op == 'sumof':
523 # sumof expr references another list,
524 # we need that list's length field here
526 for f in expr.lenfield_parent.fields:
527 if f.field_name == expr.lenfield_name:
531 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
532 # referenced list + its length field
533 return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
534 elif expr.op == 'enumref':
537 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
538 # get_expr_field_names()
540 # resolve the field names with the parent structure(s)
541 unresolved_fields_names = get_expr_field_names(self.expr)
543 # construct prefix from self
544 prefix = [('', '', p) for p in self.parents]
545 if self.is_container:
546 prefix.append(('', '', self))
548 all_fields = _c_helper_resolve_field_names (prefix)
549 resolved_fields_names = list(filter(lambda x: x in all_fields.keys(), unresolved_fields_names))
550 if len(unresolved_fields_names) != len(resolved_fields_names):
551 raise Exception("could not resolve all fields for %s" % self.name)
553 resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
554 return resolved_fields
557 def resolve_expr_fields(complex_obj):
559 find expr fields appearing in complex_obj and descendents that cannot be resolved within complex_obj
560 these are normally fields that need to be given as function parameters
566 for field in complex_obj.fields:
567 all_fields.append(field)
568 if field.type.is_switch or field.type.is_list:
569 expr_fields += get_expr_fields(field.type)
570 if field.type.is_container:
571 expr_fields += resolve_expr_fields(field.type)
573 # try to resolve expr fields
574 for e in expr_fields:
575 if e not in all_fields and e not in unresolved:
578 # resolve_expr_fields()
580 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
582 functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
583 E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch
584 expression. This function tries to resolve all fields within a structure, and returns the
585 unresolved fields as the list of external parameters.
587 def add_param(params, param):
588 if param not in params:
591 # collect all fields into param_fields
595 for field in self.fields:
597 # the field should appear as a parameter in the function call
598 param_fields.append(field)
599 if field.wire and not field.auto:
600 if field.type.fixed_size() and not self.is_switch:
601 # field in the xcb_out structure
602 wire_fields.append(field)
603 # fields like 'pad0' are skipped!
605 # in case of switch, parameters always contain any fields referenced in the switch expr
606 # we do not need any variable size fields here, as the switch data type contains both
607 # fixed and variable size fields
609 param_fields = get_expr_fields(self)
611 # _serialize()/_unserialize()/_unpack() function parameters
612 # note: don't use set() for params, it is unsorted
615 # 1. the parameter for the void * buffer
616 if 'serialize' == context:
617 params.append(('void', '**', buffer_var))
618 elif context in ('unserialize', 'unpack', 'sizeof'):
619 params.append(('const void', '*', buffer_var))
621 # 2. any expr fields that cannot be resolved within self and descendants
622 unresolved_fields = resolve_expr_fields(self)
623 for f in unresolved_fields:
624 add_param(params, (f.c_field_type, '', f.c_field_name))
626 # 3. param_fields contain the fields necessary to evaluate the switch expr or any other fields
627 # that do not appear in the data type struct
628 for p in param_fields:
630 typespec = p.c_field_const_type
631 pointerspec = p.c_pointer
632 add_param(params, (typespec, pointerspec, p.c_field_name))
634 if p.visible and not p.wire and not p.auto:
635 typespec = p.c_field_type
637 add_param(params, (typespec, pointerspec, p.c_field_name))
640 if 'serialize' == context:
641 add_param(params, ('const %s' % self.c_type, '*', aux_var))
642 elif 'unserialize' == context:
643 add_param(params, ('%s' % self.c_type, '**', aux_var))
644 elif 'unpack' == context:
645 add_param(params, ('%s' % self.c_type, '*', aux_var))
647 # 5. switch contains all variable size fields as struct members
648 # for other data types though, these have to be supplied separately
649 # this is important for the special case of intermixed fixed and
650 # variable size fields
651 if not self.is_switch and 'serialize' == context:
652 for p in param_fields:
653 if not p.type.fixed_size():
654 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
656 return (param_fields, wire_fields, params)
657 # get_serialize_params()
659 def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
660 code_lines.append('%s /* insert padding */' % space)
661 code_lines.append('%s xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
662 # code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
663 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
666 code_lines.append('%s if (0 != xcb_pad) {' % space)
668 if 'serialize' == context:
669 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
670 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
671 code_lines.append('%s xcb_parts_idx++;' % space)
672 elif context in ('unserialize', 'unpack', 'sizeof'):
673 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
675 code_lines.append('%s xcb_pad = 0;' % space)
676 code_lines.append('%s }' % space)
678 code_lines.append('%s xcb_block_len = 0;' % space)
680 # keep tracking of xcb_parts entries for serialize
682 # _c_serialize_helper_insert_padding()
684 def _c_serialize_helper_switch(context, self, complex_name,
685 code_lines, temp_vars,
688 switch_expr = _c_accessor_get_expr(self.expr, None)
690 for b in self.bitcases:
691 len_expr = len(b.type.expr)
693 compare_operator = '&'
695 compare_operator = '=='
697 compare_operator = '&'
699 for n, expr in enumerate(b.type.expr):
700 bitcase_expr = _c_accessor_get_expr(expr, None)
701 # only one <enumref> in the <bitcase>
704 ' if(%s %s %s) {' % (switch_expr, compare_operator, bitcase_expr))
705 # multiple <enumref> in the <bitcase>
708 ' if((%s %s %s) ||' % (switch_expr, compare_operator, bitcase_expr))
709 elif len_expr == (n + 1): # last
711 ' (%s %s %s)) {' % (switch_expr, compare_operator, bitcase_expr))
712 else: # between first and last
714 ' (%s %s %s) ||' % (switch_expr, compare_operator, bitcase_expr))
718 b_prefix = prefix + [(b.c_field_name, '.', b.type)]
720 count += _c_serialize_helper_fields(context, b.type,
721 code_lines, temp_vars,
724 is_case_or_bitcase = True)
725 code_lines.append(' }')
727 # if 'serialize' == context:
728 # count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
729 # elif context in ('unserialize', 'unpack', 'sizeof'):
731 # code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
732 # code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
735 # _c_serialize_helper_switch
737 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
739 handle switch by calling _serialize() or _unpack(), depending on context
741 # switch is handled by this function as a special case
742 param_fields, wire_fields, params = get_serialize_params(context, self)
743 field_mapping = _c_helper_field_mapping(self, prefix)
744 prefix_str = _c_helper_absolute_name(prefix)
746 # find the parameters that need to be passed to _serialize()/_unpack():
747 # all switch expr fields must be given as parameters
748 args = get_expr_fields(field.type)
749 # length fields for variable size types in switch, normally only some of need
750 # need to be passed as parameters
751 switch_len_fields = resolve_expr_fields(field.type)
753 # a switch field at this point _must_ be a bitcase field
754 # we require that bitcases are "self-contiguous"
755 bitcase_unresolved = resolve_expr_fields(self)
756 if len(bitcase_unresolved) != 0:
757 raise Exception('unresolved fields within bitcase is not supported at this point')
759 # get the C names for the parameters
761 for a in switch_len_fields:
762 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
764 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
766 # call _serialize()/_unpack() to determine the actual size
767 if 'serialize' == context:
768 length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
769 c_field_names, prefix_str, field.c_field_name)
770 elif context in ('unserialize', 'unpack'):
771 length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
772 c_field_names, prefix_str, field.c_field_name)
775 # _c_serialize_helper_switch_field()
777 def _c_serialize_helper_list_field(context, self, field,
778 code_lines, temp_vars,
781 helper function to cope with lists of variable length
783 expr = field.type.expr
784 prefix_str = _c_helper_absolute_name(prefix)
785 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
786 param_names = [p[2] for p in params]
788 expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
789 resolved = list(filter(lambda x: x in param_names, expr_fields_names))
790 unresolved = list(filter(lambda x: x not in param_names, expr_fields_names))
794 field_mapping[r] = (r, None)
796 if len(unresolved)>0:
798 if len(tmp_prefix)==0:
799 raise Exception("found an empty prefix while resolving expr field names for list %s",
802 field_mapping.update(_c_helper_resolve_field_names(prefix))
803 resolved += list(filter(lambda x: x in field_mapping, unresolved))
804 unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
805 if len(unresolved)>0:
806 raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
808 list_length = _c_accessor_get_expr(expr, field_mapping)
810 # default: list with fixed size elements
811 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
813 # list with variable-sized elements
814 if not field.type.member.fixed_size():
816 if context in ('unserialize', 'sizeof', 'unpack'):
817 int_i = ' unsigned int i;'
818 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
819 if int_i not in temp_vars:
820 temp_vars.append(int_i)
821 if xcb_tmp_len not in temp_vars:
822 temp_vars.append(xcb_tmp_len)
823 # loop over all list elements and call sizeof repeatedly
824 # this should be a bit faster than using the iterators
825 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
826 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
827 (space, field.type.c_sizeof_name))
828 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
829 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
830 code_lines.append("%s }" % space)
832 elif 'serialize' == context:
833 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
834 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
835 code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length))
836 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
837 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
838 code_lines.append('%s }' % space)
839 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
842 # _c_serialize_helper_list_field()
844 def _c_serialize_helper_fields_fixed_size(context, self, field,
845 code_lines, temp_vars,
847 # keep the C code a bit more readable by giving the field name
848 if not self.is_case_or_bitcase:
849 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
851 scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
852 typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
853 code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
855 abs_field_name = _c_helper_absolute_name(prefix, field)
856 # default for simple cases: call sizeof()
857 length = "sizeof(%s)" % field.c_field_type
859 if context in ('unserialize', 'unpack', 'sizeof'):
860 # default: simple cast
861 value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
863 # padding - we could probably just ignore it
864 if field.type.is_pad and field.type.nmemb > 1:
866 for i in range(field.type.nmemb):
867 code_lines.append('%s %s[%d] = *(%s *)xcb_tmp;' %
868 (space, abs_field_name, i, field.c_field_type))
869 # total padding = sizeof(pad0) * nmemb
870 length += " * %d" % field.type.nmemb
872 elif field.type.is_list:
873 # list with fixed number of elements
874 # length of array = sizeof(arrayElementType) * nmemb
875 length += " * %d" % field.type.nmemb
876 # use memcpy because C cannot assign whole arrays with operator=
877 value = ' memcpy(%s, xcb_tmp, %s);' % (abs_field_name, length)
880 elif 'serialize' == context:
881 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
883 if field.type.is_expr:
884 # need to register a temporary variable for the expression in case we know its type
885 if field.type.c_type is None:
886 raise Exception("type for field '%s' (expression '%s') unkown" %
887 (field.field_name, _c_accessor_get_expr(field.type.expr)))
889 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
890 _c_accessor_get_expr(field.type.expr, prefix)))
891 value += "&xcb_expr_%s;" % _cpp(field.field_name)
893 elif field.type.is_pad:
894 if field.type.nmemb == 1:
897 # we could also set it to 0, see definition of xcb_send_request()
898 value = ' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
899 length += "*%d" % field.type.nmemb
902 # non-list type with fixed size
903 if field.type.nmemb == 1:
904 value += "&%s;" % (abs_field_name)
906 # list with nmemb (fixed size) elements
908 value += '%s;' % (abs_field_name)
909 length = '%d' % field.type.nmemb
911 return (value, length)
912 # _c_serialize_helper_fields_fixed_size()
914 def _c_serialize_helper_fields_variable_size(context, self, field,
915 code_lines, temp_vars,
917 prefix_str = _c_helper_absolute_name(prefix)
919 if context in ('unserialize', 'unpack', 'sizeof'):
921 var_field_name = 'xcb_tmp'
923 # special case: intermixed fixed and variable size fields
924 if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
925 value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
926 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
927 # special case: switch
928 if 'unpack' == context:
929 value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
931 elif 'serialize' == context:
932 # variable size fields appear as parameters to _serialize() if the
933 # 'toplevel' container is not a switch
934 prefix_string = prefix_str if prefix[0][2].is_switch else ''
935 var_field_name = "%s%s" % (prefix_string, field.c_field_name)
936 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
940 code_lines.append('%s /* %s */' % (space, field.c_field_name))
942 if field.type.is_list:
944 # in any context, list is already a pointer, so the default assignment is ok
945 code_lines.append("%s%s" % (space, value))
947 length = _c_serialize_helper_list_field(context, self, field,
948 code_lines, temp_vars,
951 elif field.type.is_switch:
953 if context == 'serialize':
954 # the _serialize() function allocates the correct amount memory if given a NULL pointer
955 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
956 length = _c_serialize_helper_switch_field(context, self, field,
957 'xcb_parts[xcb_parts_idx].iov_base',
961 # in all remaining special cases - call _sizeof()
962 length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
964 return (value, length)
965 # _c_serialize_helper_fields_variable_size
967 def _c_serialize_helper_fields(context, self,
968 code_lines, temp_vars,
969 space, prefix, is_case_or_bitcase):
972 prev_field_was_variable = False
974 for field in self.fields:
975 if not field.visible:
976 if not ((field.wire and not field.auto) or 'unserialize' == context):
979 # switch/bitcase: fixed size fields must be considered explicitly
980 if field.type.fixed_size():
981 if self.is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
982 if prev_field_was_variable and need_padding:
984 # count += _c_serialize_helper_insert_padding(context, code_lines, space,
985 # self.c_var_followed_by_fixed_fields)
986 prev_field_was_variable = False
988 # prefix for fixed size fields
989 fixed_prefix = prefix
991 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
992 code_lines, temp_vars,
997 # fields with variable size
999 if field.type.is_pad:
1000 # Variable length pad is <pad align= />
1001 code_lines.append('%s xcb_align_to = %d;' % (space, field.type.align))
1002 count += _c_serialize_helper_insert_padding(context, code_lines, space,
1003 self.c_var_followed_by_fixed_fields)
1006 # switch/bitcase: always calculate padding before and after variable sized fields
1007 if need_padding or is_case_or_bitcase:
1008 count += _c_serialize_helper_insert_padding(context, code_lines, space,
1009 self.c_var_followed_by_fixed_fields)
1011 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
1012 code_lines, temp_vars,
1014 prev_field_was_variable = True
1016 # save (un)serialization C code
1018 code_lines.append('%s%s' % (space, value))
1020 if field.type.fixed_size():
1021 if is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
1022 # keep track of (un)serialized object's size
1023 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1024 if context in ('unserialize', 'unpack', 'sizeof'):
1025 code_lines.append('%s xcb_tmp += %s;' % (space, length))
1027 # variable size objects or bitcase:
1028 # value & length might have been inserted earlier for special cases
1030 # special case: intermixed fixed and variable size fields
1031 if (not field.type.fixed_size() and
1032 self.c_var_followed_by_fixed_fields and 'unserialize' == context):
1033 temp_vars.append(' int %s_len;' % field.c_field_name)
1034 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
1035 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
1036 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
1038 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1039 # increase pointer into the byte stream accordingly
1040 if context in ('unserialize', 'sizeof', 'unpack'):
1041 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1043 if 'serialize' == context:
1045 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
1046 code_lines.append('%s xcb_parts_idx++;' % space)
1049 code_lines.append('%s xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type))
1052 if self.c_var_followed_by_fixed_fields:
1053 need_padding = False
1056 # _c_serialize_helper_fields()
1058 def _c_serialize_helper(context, complex_type,
1059 code_lines, temp_vars,
1060 space='', prefix=[]):
1061 # count tracks the number of fields to serialize
1064 if hasattr(complex_type, 'type'):
1065 self = complex_type.type
1066 complex_name = complex_type.name
1069 if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
1070 complex_name = 'xcb_out'
1072 complex_name = '_aux'
1074 # special case: switch is serialized by evaluating each bitcase separately
1076 count += _c_serialize_helper_switch(context, self, complex_name,
1077 code_lines, temp_vars,
1080 # all other data types can be evaluated one field a time
1082 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1083 if context in ('unserialize', 'unpack', 'sizeof') and not self.c_var_followed_by_fixed_fields:
1084 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1085 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1086 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
1087 code_lines.append('%s xcb_block_len = 0;' % space)
1089 count += _c_serialize_helper_fields(context, self,
1090 code_lines, temp_vars,
1091 space, prefix, False)
1093 count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
1096 # _c_serialize_helper()
1098 def _c_serialize(context, self):
1100 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1101 for the ComplexType variable self
1107 # _serialize() returns the buffer size
1110 if self.is_switch and 'unserialize' == context:
1113 cases = { 'serialize' : self.c_serialize_name,
1114 'unserialize' : self.c_unserialize_name,
1115 'unpack' : self.c_unpack_name,
1116 'sizeof' : self.c_sizeof_name }
1117 func_name = cases[context]
1119 param_fields, wire_fields, params = get_serialize_params(context, self)
1120 variable_size_fields = 0
1121 # maximum space required for type definition of function arguments
1124 # determine N(variable_fields)
1125 for field in param_fields:
1126 # if self.is_switch, treat all fields as if they are variable sized
1127 if not field.type.fixed_size() or self.is_switch:
1128 variable_size_fields += 1
1129 # determine maxtypelen
1131 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1134 indent = ' '*(len(func_name)+2)
1137 typespec, pointerspec, field_name = p
1138 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1139 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1140 # insert function name
1141 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1142 param_str = list(map(lambda x: "%s," % x, param_str))
1143 for s in param_str[:-1]:
1145 _h("%s);" % param_str[-1].rstrip(','))
1146 _c("%s)" % param_str[-1].rstrip(','))
1153 if 'serialize' == context:
1154 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1155 _c(' %s *xcb_out = *_buffer;', self.c_type)
1156 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1157 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1158 _c(' unsigned int xcb_align_to = 0;')
1160 _c(' char *xcb_out = *_buffer;')
1161 _c(' unsigned int xcb_buffer_len = 0;')
1162 _c(' unsigned int xcb_align_to = 0;')
1163 prefix = [('_aux', '->', self)]
1166 elif context in ('unserialize', 'unpack'):
1167 _c(' char *xcb_tmp = (char *)_buffer;')
1168 if not self.is_switch:
1169 if not self.c_var_followed_by_fixed_fields:
1170 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1171 prefix = [('_aux', '->', self)]
1173 _c(' %s xcb_out;', self.c_type)
1174 prefix = [('xcb_out', '.', self)]
1176 aux_var = '_aux' # default for unpack: single pointer
1177 # note: unserialize not generated for switch
1178 if 'unserialize' == context:
1179 aux_var = '(*_aux)' # unserialize: double pointer (!)
1180 prefix = [(aux_var, '->', self)]
1182 _c(' unsigned int xcb_buffer_len = 0;')
1183 _c(' unsigned int xcb_block_len = 0;')
1184 _c(' unsigned int xcb_pad = 0;')
1185 _c(' unsigned int xcb_align_to = 0;')
1187 elif 'sizeof' == context:
1188 param_names = [p[2] for p in params]
1190 # switch: call _unpack()
1191 _c(' %s _aux;', self.c_type)
1192 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1195 elif self.c_var_followed_by_fixed_fields:
1196 # special case: call _unserialize()
1197 _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1201 _c(' char *xcb_tmp = (char *)_buffer;')
1202 prefix = [('_aux', '->', self)]
1204 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1205 # update variable size fields (only important for context=='serialize'
1206 variable_size_fields = count
1207 if 'serialize' == context:
1208 temp_vars.append(' unsigned int xcb_pad = 0;')
1209 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1210 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1211 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1212 temp_vars.append(' unsigned int xcb_block_len = 0;')
1213 temp_vars.append(' unsigned int i;')
1214 temp_vars.append(' char *xcb_tmp;')
1215 elif 'sizeof' == context:
1216 # neither switch nor intermixed fixed and variable size fields:
1217 # evaluate parameters directly
1218 if not (self.is_switch or self.c_var_followed_by_fixed_fields):
1220 # look if we have to declare an '_aux' variable at all
1221 if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
1222 if not self.c_var_followed_by_fixed_fields:
1223 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1225 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1227 _c(' unsigned int xcb_buffer_len = 0;')
1228 _c(' unsigned int xcb_block_len = 0;')
1229 _c(' unsigned int xcb_pad = 0;')
1230 _c(' unsigned int xcb_align_to = 0;')
1236 for l in code_lines:
1239 # variable sized fields have been collected, now
1240 # allocate memory and copy everything into a continuous memory area
1241 # note: this is not necessary in case of unpack
1242 if context in ('serialize', 'unserialize'):
1243 # unserialize: check for sizeof-only invocation
1244 if 'unserialize' == context:
1246 _c(' if (NULL == _aux)')
1247 _c(' return xcb_buffer_len;')
1250 _c(' if (NULL == %s) {', aux_ptr)
1251 _c(' /* allocate memory */')
1252 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1253 if 'serialize' == context:
1254 _c(' *_buffer = xcb_out;')
1258 # serialize: handle variable size fields in a loop
1259 if 'serialize' == context:
1260 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1261 if len(wire_fields)>0:
1262 _c(' *xcb_out = *_aux;')
1263 # copy variable size fields into the buffer
1264 if variable_size_fields > 0:
1266 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1267 _c(' xcb_tmp = (char*)++xcb_out;')
1268 _c(' xcb_tmp += xcb_out_pad;')
1270 _c(' xcb_tmp = xcb_out;')
1272 # variable sized fields
1273 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1274 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1275 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1276 _c(' if (0 != xcb_parts[i].iov_len)')
1277 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1280 # unserialize: assign variable size fields individually
1281 if 'unserialize' == context:
1282 _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1283 param_fields.reverse()
1284 for field in param_fields:
1285 if not field.type.fixed_size():
1286 _c(' xcb_tmp -= %s_len;', field.c_field_name)
1287 _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1288 _c(' *%s = xcb_out;', aux_ptr)
1291 _c(' return xcb_buffer_len;')
1295 def _c_iterator_get_end(field, accum):
1297 Figures out what C code is needed to find the end of a variable-length structure field.
1298 For nested structures, recurses into its last variable-sized field.
1299 For lists, calls the end function
1301 if field.type.is_container:
1302 accum = field.c_accessor_name + '(' + accum + ')'
1303 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1304 if field.type.is_list:
1305 # XXX we can always use the first way
1306 if field.type.member.is_simple:
1307 return field.c_end_name + '(' + accum + ')'
1309 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1311 def _c_iterator(self, name):
1313 Declares the iterator structure and next/end functions for a given type.
1318 _h(' * @brief %s', self.c_iterator_type)
1320 _h('typedef struct %s {', self.c_iterator_type)
1321 _h(' %s *data; /**< */', self.c_type)
1322 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1323 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1324 _h('} %s;', self.c_iterator_type)
1330 _h(' * Get the next element of the iterator')
1331 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1333 _h(' * Get the next element in the iterator. The member rem is')
1334 _h(' * decreased by one. The member data points to the next')
1335 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1339 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1340 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1343 if not self.fixed_size():
1344 _c(' %s *R = i->data;', self.c_type)
1347 # FIXME - how to determine the size of a variable size union??
1348 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1350 if self.c_need_sizeof:
1351 _c(' xcb_generic_iterator_t child;')
1352 _c(' child.data = (%s *)(((char *)R) + %s(R));',
1353 self.c_type, self.c_sizeof_name)
1354 _c(' i->index = (char *) child.data - (char *) i->data;')
1356 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1357 _c(' i->index = child.index;')
1359 _c(' i->data = (%s *) child.data;', self.c_type)
1364 _c(' i->index += sizeof(%s);', self.c_type)
1370 _h(' * Return the iterator pointing to the last element')
1371 _h(' * @param i An %s', self.c_iterator_type)
1372 _h(' * @return The iterator pointing to the last element')
1374 _h(' * Set the current element in the iterator to the last element.')
1375 _h(' * The member rem is set to 0. The member data points to the')
1376 _h(' * last element.')
1379 _hc('xcb_generic_iterator_t')
1380 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1381 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1383 _c(' xcb_generic_iterator_t ret;')
1385 if self.fixed_size():
1386 _c(' ret.data = i.data + i.rem;')
1387 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1390 _c(' while(i.rem > 0)')
1391 _c(' %s(&i);', self.c_next_name)
1392 _c(' ret.data = i.data;')
1393 _c(' ret.rem = i.rem;')
1394 _c(' ret.index = i.index;')
1399 def _c_accessor_get_length(expr, field_mapping=None):
1401 Figures out what C code is needed to get a length field.
1402 The field_mapping parameter can be used to change the absolute name of a length field.
1403 For fields that follow a variable-length field, use the accessor.
1404 Otherwise, just reference the structure field directly.
1407 lenfield_name = expr.lenfield_name
1408 if lenfield_name is not None:
1409 if field_mapping is not None:
1410 lenfield_name = field_mapping[lenfield_name][0]
1412 if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1413 # special case: variable and fixed size fields are intermixed
1414 # if the lenfield is among the fixed size fields, there is no need
1415 # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1416 return field_mapping(expr.lenfield_name)
1417 elif expr.lenfield_name is not None:
1418 return lenfield_name
1420 return str(expr.nmemb)
1422 def _c_accessor_get_expr(expr, field_mapping):
1424 Figures out what C code is needed to get the length of a list field.
1425 The field_mapping parameter can be used to change the absolute name of a length field.
1426 Recurses for math operations.
1427 Returns bitcount for value-mask fields.
1428 Otherwise, uses the value of the length field.
1430 lenexp = _c_accessor_get_length(expr, field_mapping)
1433 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1434 elif expr.op == 'popcount':
1435 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1436 elif expr.op == 'enumref':
1437 enum_name = expr.lenfield_type.name
1438 constant_name = expr.lenfield_name
1439 c_name = _n(enum_name + (constant_name,)).upper()
1441 elif expr.op == 'sumof':
1442 # locate the referenced list object
1443 list_obj = expr.lenfield_type
1445 for f in expr.lenfield_parent.fields:
1446 if f.field_name == expr.lenfield_name:
1451 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1452 list_name = field_mapping[field.c_field_name][0]
1453 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1454 # note: xcb_sumof() has only been defined for integers
1455 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1456 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1457 elif expr.op != None:
1458 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1459 ' ' + expr.op + ' ' +
1460 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1462 return 'xcb_popcount(' + lenexp + ')'
1466 def type_pad_type(type):
1471 def _c_accessors_field(self, field):
1473 Declares the accessor functions for a non-list field that follows a variable-length field.
1475 c_type = self.c_type
1477 # special case: switch
1478 switch_obj = self if self.is_switch else None
1479 if self.is_case_or_bitcase:
1480 switch_obj = self.parents[-1]
1481 if switch_obj is not None:
1482 c_type = switch_obj.c_type
1484 if field.type.is_simple:
1486 _hc('%s', field.c_field_type)
1487 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1488 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1490 if field.prev_varsized_field is None:
1491 _c(' return (%s *) (R + 1);', field.c_field_type)
1493 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1494 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1495 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1499 if field.type.is_switch and switch_obj is None:
1500 return_type = 'void *'
1502 return_type = '%s *' % field.c_field_type
1505 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1506 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1508 if field.prev_varsized_field is None:
1509 _c(' return (%s) (R + 1);', return_type)
1510 # note: the special case 'variable fields followed by fixed size fields'
1511 # is not of any consequence here, since the ordering gets
1512 # 'corrected' in the reply function
1514 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1515 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1516 return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1520 def _c_accessors_list(self, field):
1522 Declares the accessor functions for a list field.
1523 Declares a direct-accessor function only if the list members are fixed size.
1524 Declares length and get-iterator functions always.
1527 def get_align_pad(field):
1528 prev = field.prev_varsized_field
1529 prev_prev = field.prev_varsized_field.prev_varsized_field
1531 if (prev.type.is_pad and prev.type.align > 0 and prev_prev is not None):
1532 return (prev_prev, '((-prev.index) & (%d - 1))' % prev.type.align)
1538 c_type = self.c_type
1540 # special case: switch
1541 # in case of switch, 2 params have to be supplied to certain accessor functions:
1542 # 1. the anchestor object (request or reply)
1543 # 2. the (anchestor) switch object
1544 # the reason is that switch is either a child of a request/reply or nested in another switch,
1545 # so whenever we need to access a length field, we might need to refer to some anchestor type
1546 switch_obj = self if self.is_switch else None
1547 if self.is_case_or_bitcase:
1548 switch_obj = self.parents[-1]
1549 if switch_obj is not None:
1550 c_type = switch_obj.c_type
1554 parents = self.parents if hasattr(self, 'parents') else [self]
1555 # 'R': parents[0] is always the 'toplevel' container type
1556 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1557 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1558 # auxiliary object for 'R' parameters
1561 if switch_obj is not None:
1562 # now look where the fields are defined that are needed to evaluate
1563 # the switch expr, and store the parent objects in accessor_params and
1564 # the fields in switch_fields
1566 # 'S': name for the 'toplevel' switch
1567 toplevel_switch = parents[1]
1568 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1569 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1571 # initialize prefix for everything "below" S
1572 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1573 prefix = [(prefix_str, '->', toplevel_switch)]
1575 # look for fields in the remaining containers
1576 for p in parents[2:] + [self]:
1577 # the separator between parent and child is always '.' here,
1578 # because of nested switch statements
1579 if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
1580 prefix.append((p.name[-1], '.', p))
1581 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1583 # auxiliary object for 'S' parameter
1588 if list.member.fixed_size():
1589 idx = 1 if switch_obj is not None else 0
1591 _hc('%s *', field.c_field_type)
1593 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1594 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1597 if switch_obj is not None:
1598 _c(' return %s;', fields[field.c_field_name][0])
1599 elif field.prev_varsized_field is None:
1600 _c(' return (%s *) (R + 1);', field.c_field_type)
1602 (prev_varsized_field, align_pad) = get_align_pad(field)
1604 if align_pad is None:
1605 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
1606 type_pad_type(field.first_field_after_varsized.type.c_type))
1608 _c(' xcb_generic_iterator_t prev = %s;',
1609 _c_iterator_get_end(prev_varsized_field, 'R'))
1610 _c(' return (%s *) ((char *) prev.data + %s + %d);',
1611 field.c_field_type, align_pad, field.prev_varsized_offset)
1616 if switch_obj is not None:
1617 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1618 spacing = ' '*(len(field.c_length_name)+2)
1619 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1620 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1621 length = _c_accessor_get_expr(field.type.expr, fields)
1623 _h('%s (const %s *R /**< */);', field.c_length_name, c_type)
1624 _c('%s (const %s *R /**< */)', field.c_length_name, c_type)
1625 length = _c_accessor_get_expr(field.type.expr, fields)
1627 _c(' return %s;', length)
1630 if field.type.member.is_simple:
1632 _hc('xcb_generic_iterator_t')
1633 if switch_obj is not None:
1634 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1635 spacing = ' '*(len(field.c_end_name)+2)
1636 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1637 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1639 _h('%s (const %s *R /**< */);', field.c_end_name, c_type)
1640 _c('%s (const %s *R /**< */)', field.c_end_name, c_type)
1642 _c(' xcb_generic_iterator_t i;')
1644 param = 'R' if switch_obj is None else 'S'
1645 if switch_obj is not None:
1646 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1647 _c_accessor_get_expr(field.type.expr, fields))
1648 elif field.prev_varsized_field == None:
1649 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1650 _c_accessor_get_expr(field.type.expr, fields))
1652 _c(' xcb_generic_iterator_t child = %s;',
1653 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1654 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1655 _c_accessor_get_expr(field.type.expr, fields))
1658 _c(' i.index = (char *) i.data - (char *) %s;', param)
1664 _hc('%s', field.c_iterator_type)
1665 if switch_obj is not None:
1666 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1667 spacing = ' '*(len(field.c_iterator_name)+2)
1668 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1669 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1671 _h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
1672 _c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
1674 _c(' %s i;', field.c_iterator_type)
1676 if switch_obj is not None:
1677 _c(' i.data = %s;', fields[field.c_field_name][0])
1678 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1679 elif field.prev_varsized_field == None:
1680 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1682 (prev_varsized_field, align_pad) = get_align_pad(field)
1684 if align_pad is None:
1685 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
1686 type_pad_type(field.c_field_type))
1688 _c(' xcb_generic_iterator_t prev = %s;',
1689 _c_iterator_get_end(prev_varsized_field, 'R'))
1690 _c(' i.data = (%s *) ((char *) prev.data + %s);',
1691 field.c_field_type, align_pad)
1693 if switch_obj is None:
1694 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1695 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1699 def _c_accessors(self, name, base):
1701 Declares the accessor functions for the fields of a structure.
1703 # no accessors for switch itself -
1704 # switch always needs to be unpacked explicitly
1705 # if self.is_switch:
1709 for field in self.fields:
1710 if not field.type.is_pad:
1711 if field.type.is_list and not field.type.fixed_size():
1712 _c_accessors_list(self, field)
1713 elif field.prev_varsized_field is not None or not field.type.fixed_size():
1714 _c_accessors_field(self, field)
1716 def c_simple(self, name):
1718 Exported function that handles cardinal type declarations.
1719 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1721 _c_type_setup(self, name, ())
1723 if (self.name != name):
1728 _h('typedef %s %s;', _t(self.name), my_name)
1731 _c_iterator(self, name)
1733 def _c_complex(self, force_packed = False):
1735 Helper function for handling all structure types.
1736 Called for all structs, requests, replies, events, errors.
1741 _h(' * @brief %s', self.c_type)
1743 _h('typedef %s %s {', self.c_container, self.c_type)
1749 for field in self.fields:
1750 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1751 varfield = field.c_field_name
1754 struct_fields.append(field)
1756 for field in struct_fields:
1757 length = len(field.c_field_type)
1758 # account for '*' pointer_spec
1759 if not field.type.fixed_size() and not self.is_union:
1761 maxtypelen = max(maxtypelen, length)
1763 def _c_complex_field(self, field, space=''):
1764 if (field.type.fixed_size() or self.is_union or
1765 # in case of switch with switch children, don't make the field a pointer
1766 # necessary for unserialize to work
1767 (self.is_switch and field.type.is_switch)):
1768 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1769 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1771 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1772 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1774 if not self.is_switch:
1775 for field in struct_fields:
1776 _c_complex_field(self, field)
1778 for b in self.bitcases:
1781 _h(' struct _%s {', b.c_field_name)
1783 for field in b.type.fields:
1784 _c_complex_field(self, field, space)
1786 _h(' } %s;', b.c_field_name)
1788 _h('} %s%s;', 'XCB_PACKED ' if force_packed else '', self.c_type)
1790 def c_struct(self, name):
1792 Exported function that handles structure declarations.
1794 _c_type_setup(self, name, ())
1796 _c_accessors(self, name, name)
1797 _c_iterator(self, name)
1799 def c_union(self, name):
1801 Exported function that handles union declarations.
1803 _c_type_setup(self, name, ())
1805 _c_iterator(self, name)
1807 def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_fds=False):
1809 Declares a request function.
1812 # Four stunningly confusing possibilities here:
1815 # ------------------------------
1817 # 0 flag CHECKED flag Normal Mode
1818 # void_cookie req_cookie
1819 # ------------------------------
1820 # "req_checked" "req_unchecked"
1821 # CHECKED flag 0 flag Abnormal Mode
1822 # void_cookie req_cookie
1823 # ------------------------------
1826 # Whether we are _checked or _unchecked
1827 checked = void and not regular
1828 unchecked = not void and not regular
1830 # What kind of cookie we return
1831 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1833 # What flag is passed to xcb_request
1834 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1837 if func_flags == '0':
1838 func_flags = 'XCB_REQUEST_REPLY_FDS'
1840 func_flags = func_flags + '|XCB_REQUEST_REPLY_FDS'
1842 # Global extension id variable or NULL for xproto
1843 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1845 # What our function name is
1846 func_name = self.c_request_name if not aux else self.c_aux_name
1848 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1850 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1854 maxtypelen = len('xcb_connection_t')
1856 # special case: list with variable size elements
1857 list_with_var_size_elems = False
1859 for field in self.fields:
1861 # The field should appear as a call parameter
1862 param_fields.append(field)
1863 if field.wire and not field.auto:
1864 # We need to set the field up in the structure
1865 wire_fields.append(field)
1866 if field.type.c_need_serialize or field.type.c_need_sizeof:
1867 serial_fields.append(field)
1869 for field in param_fields:
1870 c_field_const_type = field.c_field_const_type
1871 if field.type.c_need_serialize and not aux:
1872 c_field_const_type = "const void"
1873 if len(c_field_const_type) > maxtypelen:
1874 maxtypelen = len(c_field_const_type)
1875 if field.type.is_list and not field.type.member.fixed_size():
1876 list_with_var_size_elems = True
1882 if hasattr(self, "doc") and self.doc:
1884 _h(' * @brief ' + self.doc.brief)
1886 _h(' * No brief doc yet')
1889 _h(' * @param c The connection')
1890 param_names = [f.c_field_name for f in param_fields]
1891 if hasattr(self, "doc") and self.doc:
1892 for field in param_fields:
1893 # XXX: hard-coded until we fix xproto.xml
1894 base_func_name = self.c_request_name if not aux else self.c_aux_name
1895 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
1897 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
1899 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
1902 # XXX: why the 'xcb' prefix?
1903 key = ('xcb', field.enum)
1906 if namecount[tname] > 1:
1907 tname = _t(key + ('enum',))
1908 _h(' * @param %s A bitmask of #%s values.' % (field.c_field_name, tname))
1910 if self.doc and field.field_name in self.doc.fields:
1911 desc = self.doc.fields[field.field_name]
1912 for name in param_names:
1913 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1914 desc = desc.split("\n")
1915 desc = [line if line != '' else '\\n' for line in desc]
1916 _h(' * @param %s %s' % (field.c_field_name, "\n * ".join(desc)))
1917 # If there is no documentation yet, we simply don't generate an
1918 # @param tag. Doxygen will then warn about missing documentation.
1920 _h(' * @return A cookie')
1923 if hasattr(self, "doc") and self.doc:
1924 if self.doc.description:
1925 desc = self.doc.description
1926 for name in param_names:
1927 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1928 desc = desc.split("\n")
1929 _h(' * ' + "\n * ".join(desc))
1931 _h(' * No description yet')
1933 _h(' * Delivers a request to the X server.')
1936 _h(' * This form can be used only if the request will not cause')
1937 _h(' * a reply to be generated. Any returned error will be')
1938 _h(' * saved for handling by xcb_request_check().')
1940 _h(' * This form can be used only if the request will cause')
1941 _h(' * a reply to be generated. Any returned error will be')
1942 _h(' * placed in the event queue.')
1945 _hc('%s', cookie_type)
1947 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1948 comma = ',' if len(param_fields) else ');'
1949 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1950 comma = ',' if len(param_fields) else ')'
1951 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1953 func_spacing = ' ' * (len(func_name) + 2)
1954 count = len(param_fields)
1955 for field in param_fields:
1957 c_field_const_type = field.c_field_const_type
1958 c_pointer = field.c_pointer
1959 if field.type.c_need_serialize and not aux:
1960 c_field_const_type = "const void"
1962 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1963 comma = ',' if count else ');'
1964 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1965 spacing, c_pointer, field.c_field_name, comma)
1966 comma = ',' if count else ')'
1967 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1968 spacing, c_pointer, field.c_field_name, comma)
1971 if not self.c_var_followed_by_fixed_fields:
1972 for field in param_fields:
1973 if not field.type.fixed_size():
1975 if field.type.c_need_serialize:
1976 # _serialize() keeps track of padding automatically
1978 dimension = count + 2
1981 _c(' static const xcb_protocol_request_t xcb_req = {')
1982 _c(' /* count */ %d,', count)
1983 _c(' /* ext */ %s,', func_ext_global)
1984 _c(' /* opcode */ %s,', self.c_request_name.upper())
1985 _c(' /* isvoid */ %d', 1 if void else 0)
1989 _c(' struct iovec xcb_parts[%d];', dimension)
1990 _c(' %s xcb_ret;', func_cookie)
1991 _c(' %s xcb_out;', self.c_type)
1992 if self.c_var_followed_by_fixed_fields:
1993 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
1994 _c(' void *xcb_aux = 0;')
1997 for idx, f in enumerate(serial_fields):
1999 _c(' void *xcb_aux%d = 0;' % (idx))
2000 if list_with_var_size_elems:
2001 _c(' unsigned int i;')
2002 _c(' unsigned int xcb_tmp_len;')
2003 _c(' char *xcb_tmp;')
2005 # simple request call tracing
2006 # _c(' printf("in function %s\\n");' % func_name)
2009 for field in wire_fields:
2010 if field.type.fixed_size():
2011 if field.type.is_expr:
2012 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
2013 elif field.type.is_pad:
2014 if field.type.nmemb == 1:
2015 _c(' xcb_out.%s = 0;', field.c_field_name)
2017 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
2019 if field.type.nmemb == 1:
2020 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
2022 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
2024 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
2025 serialize_args = get_serialize_params(context, type_obj,
2028 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
2030 # calls in order to free dyn. all. memory
2034 if not self.c_var_followed_by_fixed_fields:
2035 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2036 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
2037 _c(' xcb_parts[3].iov_base = 0;')
2038 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2042 for field in param_fields:
2043 if not field.type.fixed_size():
2044 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
2045 # default: simple cast to char *
2046 if not field.type.c_need_serialize and not field.type.c_need_sizeof:
2047 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2048 if field.type.is_list:
2049 if field.type.member.fixed_size():
2050 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
2051 _c_accessor_get_expr(field.type.expr, None),
2052 field.type.member.c_wiretype)
2054 list_length = _c_accessor_get_expr(field.type.expr, None)
2057 _c(" xcb_parts[%d].iov_len = 0;" % count)
2058 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2059 _c(" for(i=0; i<%s; i++) {" % list_length)
2060 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2061 (field.type.c_sizeof_name))
2062 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2063 _c(" xcb_tmp += xcb_tmp_len;")
2066 # not supposed to happen
2067 raise Exception("unhandled variable size field %s" % field.c_field_name)
2070 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2071 idx = serial_fields.index(field)
2072 aux_var = '&xcb_aux%d' % idx
2073 context = 'serialize' if aux else 'sizeof'
2074 _c(' xcb_parts[%d].iov_len =', count)
2076 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2077 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2078 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2079 free_calls.append(' free(xcb_aux%d);' % idx)
2081 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2082 func_name = field.type.c_sizeof_name
2083 _c(' %s (%s);', func_name, serialize_args)
2086 if not (field.type.c_need_serialize or field.type.c_need_sizeof):
2087 # the _serialize() function keeps track of padding automatically
2088 _c(' xcb_parts[%d].iov_base = 0;', count)
2089 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2092 # elif self.c_var_followed_by_fixed_fields:
2094 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2095 # request header: opcodes + length
2096 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2099 buffer_var = '&xcb_aux'
2100 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2101 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2102 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2103 free_calls.append(' free(xcb_aux);')
2104 # no padding necessary - _serialize() keeps track of padding automatically
2107 for field in param_fields:
2109 _c(' xcb_send_fd(c, %s);', field.c_field_name)
2111 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2113 # free dyn. all. data, if any
2114 for f in free_calls:
2116 _c(' return xcb_ret;')
2119 def _c_reply(self, name):
2121 Declares the function that returns the reply structure.
2123 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2124 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2125 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2127 # check if _unserialize() has to be called for any field
2128 def look_for_special_cases(complex_obj):
2129 unserialize_fields = []
2130 # no unserialize call in case of switch
2131 if not complex_obj.is_switch:
2132 for field in complex_obj.fields:
2133 # three cases: 1. field with special case
2134 # 2. container that contains special case field
2135 # 3. list with special case elements
2136 if field.type.c_var_followed_by_fixed_fields:
2137 unserialize_fields.append(field)
2138 elif field.type.is_container:
2139 unserialize_fields += look_for_special_cases(field.type)
2140 elif field.type.is_list:
2141 if field.type.member.c_var_followed_by_fixed_fields:
2142 unserialize_fields.append(field)
2143 if field.type.member.is_container:
2144 unserialize_fields += look_for_special_cases(field.type.member)
2145 return unserialize_fields
2147 unserialize_fields = look_for_special_cases(self.reply)
2151 _h(' * Return the reply')
2152 _h(' * @param c The connection')
2153 _h(' * @param cookie The cookie')
2154 _h(' * @param e The xcb_generic_error_t supplied')
2156 _h(' * Returns the reply of the request asked by')
2158 _h(' * The parameter @p e supplied to this function must be NULL if')
2159 _h(' * %s(). is used.', self.c_unchecked_name)
2160 _h(' * Otherwise, it stores the error if any.')
2162 _h(' * The returned value must be freed by the caller using free().')
2165 _hc('%s *', self.c_reply_type)
2166 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2167 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2168 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2169 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2172 if len(unserialize_fields)>0:
2173 # certain variable size fields need to be unserialized explicitly
2174 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2175 self.c_reply_type, self.c_reply_type)
2177 for field in unserialize_fields:
2178 if field.type.is_list:
2179 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2180 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2181 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2183 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2184 # call _unserialize(), using the reply as source and target buffer
2185 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2186 for field in unserialize_fields:
2187 if field.type.is_list:
2188 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2189 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2190 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2191 field.c_field_name, field.c_field_name)
2192 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2194 # return the transformed reply
2195 _c(' return reply;')
2198 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2202 def _c_reply_has_fds(self):
2203 for field in self.fields:
2208 def _c_reply_fds(self, name):
2210 Declares the function that returns fds related to the reply.
2212 spacing1 = ' ' * (len(self.c_reply_type) - len('xcb_connection_t'))
2213 spacing3 = ' ' * (len(self.c_reply_fds_name) + 2)
2216 _h(' * Return the reply fds')
2217 _h(' * @param c The connection')
2218 _h(' * @param reply The reply')
2220 _h(' * Returns the array of reply fds of the request asked by')
2222 _h(' * The returned value must be freed by the caller using free().')
2226 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_fds_name, spacing1)
2227 _h('%s%s *reply /**< */);', spacing3, self.c_reply_type)
2228 _c('%s%s *reply /**< */)', spacing3, self.c_reply_type)
2231 _c(' return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
2236 def _c_opcode(name, opcode):
2238 Declares the opcode define for requests, events, and errors.
2242 _h('/** Opcode for %s. */', _n(name))
2243 _h('#define %s %s', _n(name).upper(), opcode)
2245 def _c_cookie(self, name):
2247 Declares the cookie type for a non-void request.
2252 _h(' * @brief %s', self.c_cookie_type)
2254 _h('typedef struct %s {', self.c_cookie_type)
2255 _h(' unsigned int sequence; /**< */')
2256 _h('} %s;', self.c_cookie_type)
2258 def _man_request(self, name, cookie_type, void, aux):
2259 param_fields = [f for f in self.fields if f.visible]
2261 func_name = self.c_request_name if not aux else self.c_aux_name
2263 def create_link(linkname):
2264 name = 'man/%s.%s' % (linkname, section)
2266 sys.stdout.write(name)
2268 f.write('.so man%s/%s.%s' % (section, func_name, section))
2272 sys.stdout.write('man/%s.%s ' % (func_name, section))
2273 # Our CWD is src/, so this will end up in src/man/
2274 f = open('man/%s.%s' % (func_name, section), 'w')
2275 f.write('.TH %s %s "%s" "%s" "XCB Requests"\n' % (func_name, section, center_footer, left_footer))
2276 # Left-adjust instead of adjusting to both sides
2278 f.write('.SH NAME\n')
2279 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2280 f.write('%s \\- %s\n' % (func_name, brief))
2281 f.write('.SH SYNOPSIS\n')
2282 # Don't split words (hyphenate)
2284 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2286 # function prototypes
2288 count = len(param_fields)
2289 for field in param_fields:
2291 c_field_const_type = field.c_field_const_type
2292 c_pointer = field.c_pointer
2293 if c_pointer == ' ':
2295 if field.type.c_need_serialize and not aux:
2296 c_field_const_type = "const void"
2298 comma = ', ' if count else ');'
2299 prototype += '%s\\ %s\\fI%s\\fP%s' % (c_field_const_type, c_pointer, field.c_field_name, comma)
2301 f.write('.SS Request function\n')
2303 base_func_name = self.c_request_name if not aux else self.c_aux_name
2304 f.write('%s \\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\n' % (cookie_type, base_func_name, prototype))
2305 create_link('%s_%s' % (base_func_name, ('checked' if void else 'unchecked')))
2308 f.write('.SS Reply datastructure\n')
2311 f.write('typedef %s %s {\n' % (self.reply.c_container, self.reply.c_type))
2315 for field in self.reply.fields:
2316 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2319 struct_fields.append(field)
2321 for field in struct_fields:
2322 length = len(field.c_field_type)
2323 # account for '*' pointer_spec
2324 if not field.type.fixed_size():
2326 maxtypelen = max(maxtypelen, length)
2328 def _c_complex_field(self, field, space=''):
2329 if (field.type.fixed_size() or
2330 # in case of switch with switch children, don't make the field a pointer
2331 # necessary for unserialize to work
2332 (self.is_switch and field.type.is_switch)):
2333 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2334 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2336 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
2337 f.write('ELSE %s = %s\n' % (field.c_field_type, field.c_field_name))
2338 #_h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2340 if not self.is_switch:
2341 for field in struct_fields:
2342 _c_complex_field(self, field)
2344 for b in self.bitcases:
2348 for field in b.type.fields:
2349 _c_complex_field(self, field, space)
2351 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2354 f.write('} \\fB%s\\fP;\n' % self.reply.c_type)
2357 f.write('.SS Reply function\n')
2359 f.write(('%s *\\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\\ '
2360 '\\fIcookie\\fP, xcb_generic_error_t\\ **\\fIe\\fP);\n') %
2361 (self.c_reply_type, self.c_reply_name, self.c_cookie_type))
2362 create_link('%s' % self.c_reply_name)
2364 has_accessors = False
2365 for field in self.reply.fields:
2366 if field.type.is_list and not field.type.fixed_size():
2367 has_accessors = True
2368 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2369 has_accessors = True
2372 f.write('.SS Reply accessors\n')
2374 def _c_accessors_field(self, field):
2376 Declares the accessor functions for a non-list field that follows a variable-length field.
2378 c_type = self.c_type
2380 # special case: switch
2381 switch_obj = self if self.is_switch else None
2382 if self.is_case_or_bitcase:
2383 switch_obj = self.parents[-1]
2384 if switch_obj is not None:
2385 c_type = switch_obj.c_type
2387 if field.type.is_simple:
2388 f.write('%s %s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2389 create_link('%s' % field.c_accessor_name)
2391 f.write('%s *%s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2392 create_link('%s' % field.c_accessor_name)
2394 def _c_accessors_list(self, field):
2396 Declares the accessor functions for a list field.
2397 Declares a direct-accessor function only if the list members are fixed size.
2398 Declares length and get-iterator functions always.
2401 c_type = self.reply.c_type
2403 # special case: switch
2404 # in case of switch, 2 params have to be supplied to certain accessor functions:
2405 # 1. the anchestor object (request or reply)
2406 # 2. the (anchestor) switch object
2407 # the reason is that switch is either a child of a request/reply or nested in another switch,
2408 # so whenever we need to access a length field, we might need to refer to some anchestor type
2409 switch_obj = self if self.is_switch else None
2410 if self.is_case_or_bitcase:
2411 switch_obj = self.parents[-1]
2412 if switch_obj is not None:
2413 c_type = switch_obj.c_type
2417 parents = self.parents if hasattr(self, 'parents') else [self]
2418 # 'R': parents[0] is always the 'toplevel' container type
2419 params.append(('const %s *\\fIreply\\fP' % parents[0].c_type, parents[0]))
2420 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
2421 # auxiliary object for 'R' parameters
2424 if switch_obj is not None:
2425 # now look where the fields are defined that are needed to evaluate
2426 # the switch expr, and store the parent objects in accessor_params and
2427 # the fields in switch_fields
2429 # 'S': name for the 'toplevel' switch
2430 toplevel_switch = parents[1]
2431 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
2432 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
2434 # initialize prefix for everything "below" S
2435 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
2436 prefix = [(prefix_str, '->', toplevel_switch)]
2438 # look for fields in the remaining containers
2439 for p in parents[2:] + [self]:
2440 # the separator between parent and child is always '.' here,
2441 # because of nested switch statements
2442 if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
2443 prefix.append((p.name[-1], '.', p))
2444 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
2446 # auxiliary object for 'S' parameter
2449 if list.member.fixed_size():
2450 idx = 1 if switch_obj is not None else 0
2452 f.write('%s *\\fB%s\\fP(%s);\n' %
2453 (field.c_field_type, field.c_accessor_name, params[idx][0]))
2454 create_link('%s' % field.c_accessor_name)
2457 f.write('int \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2458 (field.c_length_name, c_type))
2459 create_link('%s' % field.c_length_name)
2461 if field.type.member.is_simple:
2463 f.write('xcb_generic_iterator_t \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2464 (field.c_end_name, c_type))
2465 create_link('%s' % field.c_end_name)
2468 f.write('%s \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2469 (field.c_iterator_type, field.c_iterator_name,
2471 create_link('%s' % field.c_iterator_name)
2473 for field in self.reply.fields:
2474 if field.type.is_list and not field.type.fixed_size():
2475 _c_accessors_list(self, field)
2476 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2477 _c_accessors_field(self, field)
2481 # Re-enable hyphenation and adjusting to both sides
2484 # argument reference
2485 f.write('.SH REQUEST ARGUMENTS\n')
2486 f.write('.IP \\fI%s\\fP 1i\n' % 'conn')
2487 f.write('The XCB connection to X11.\n')
2488 for field in param_fields:
2489 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2490 printed_enum = False
2491 # XXX: hard-coded until we fix xproto.xml
2492 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
2494 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
2496 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
2498 if hasattr(field, "enum") and field.enum:
2499 # XXX: why the 'xcb' prefix?
2500 key = ('xcb', field.enum)
2502 f.write('One of the following values:\n')
2505 count = len(enum.values)
2506 for (enam, eval) in enum.values:
2508 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2509 if hasattr(enum, "doc") and enum.doc and enam in enum.doc.fields:
2510 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2511 f.write('%s\n' % desc)
2513 f.write('TODO: NOT YET DOCUMENTED.\n')
2518 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2519 desc = self.doc.fields[field.field_name]
2520 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2523 f.write('%s\n' % desc)
2525 f.write('TODO: NOT YET DOCUMENTED.\n')
2531 f.write('.SH REPLY FIELDS\n')
2532 # These fields are present in every reply:
2533 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2534 f.write(('The type of this reply, in this case \\fI%s\\fP. This field '
2535 'is also present in the \\fIxcb_generic_reply_t\\fP and can '
2536 'be used to tell replies apart from each other.\n') %
2537 _n(self.reply.name).upper())
2538 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2539 f.write('The sequence number of the last request processed by the X11 server.\n')
2540 f.write('.IP \\fI%s\\fP 1i\n' % 'length')
2541 f.write('The length of the reply, in words (a word is 4 bytes).\n')
2542 for field in self.reply.fields:
2543 if (field.c_field_name in frozenset(['response_type', 'sequence', 'length']) or
2544 field.c_field_name.startswith('pad')):
2547 if field.type.is_list and not field.type.fixed_size():
2549 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2551 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2552 printed_enum = False
2553 if hasattr(field, "enum") and field.enum:
2554 # XXX: why the 'xcb' prefix?
2555 key = ('xcb', field.enum)
2557 f.write('One of the following values:\n')
2560 count = len(enum.values)
2561 for (enam, eval) in enum.values:
2563 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2564 if enum.doc and enam in enum.doc.fields:
2565 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2566 f.write('%s\n' % desc)
2568 f.write('TODO: NOT YET DOCUMENTED.\n')
2573 if hasattr(self.reply, "doc") and self.reply.doc and field.field_name in self.reply.doc.fields:
2574 desc = self.reply.doc.fields[field.field_name]
2575 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2578 f.write('%s\n' % desc)
2580 f.write('TODO: NOT YET DOCUMENTED.\n')
2587 f.write('.SH DESCRIPTION\n')
2588 if hasattr(self, "doc") and self.doc and self.doc.description:
2589 desc = self.doc.description
2590 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2591 lines = desc.split('\n')
2592 f.write('\n'.join(lines) + '\n')
2594 f.write('.SH RETURN VALUE\n')
2596 f.write(('Returns an \\fIxcb_void_cookie_t\\fP. Errors (if any) '
2597 'have to be handled in the event loop.\n\nIf you want to '
2598 'handle errors directly with \\fIxcb_request_check\\fP '
2599 'instead, use \\fI%s_checked\\fP. See '
2600 '\\fBxcb-requests(%s)\\fP for details.\n') % (base_func_name, section))
2602 f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
2603 'calling the reply function \\fI%s\\fP.\n\nIf you want to '
2604 'handle errors in the event loop instead, use '
2605 '\\fI%s_unchecked\\fP. See \\fBxcb-requests(%s)\\fP for '
2607 (cookie_type, self.c_reply_name, base_func_name, section))
2608 f.write('.SH ERRORS\n')
2609 if hasattr(self, "doc") and self.doc:
2610 for errtype, errtext in sorted(self.doc.errors.items()):
2611 f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
2612 errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
2613 f.write('%s\n' % (errtext))
2614 if not hasattr(self, "doc") or not self.doc or len(self.doc.errors) == 0:
2615 f.write('This request does never generate any errors.\n')
2616 if hasattr(self, "doc") and self.doc and self.doc.example:
2617 f.write('.SH EXAMPLE\n')
2620 lines = self.doc.example.split('\n')
2621 f.write('\n'.join(lines) + '\n')
2623 f.write('.SH SEE ALSO\n')
2624 if hasattr(self, "doc") and self.doc:
2625 see = ['.BR %s (%s)' % ('xcb-requests', section)]
2626 if self.doc.example:
2627 see.append('.BR %s (%s)' % ('xcb-examples', section))
2628 for seename, seetype in sorted(self.doc.see.items()):
2629 if seetype == 'program':
2630 see.append('.BR %s (1)' % seename)
2631 elif seetype == 'event':
2632 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2633 elif seetype == 'request':
2634 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2635 elif seetype == 'function':
2636 see.append('.BR %s (%s)' % (seename, section))
2638 see.append('TODO: %s (type %s)' % (seename, seetype))
2639 f.write(',\n'.join(see) + '\n')
2640 f.write('.SH AUTHOR\n')
2641 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2644 def _man_event(self, name):
2646 sys.stdout.write('man/%s.%s ' % (self.c_type, section))
2647 # Our CWD is src/, so this will end up in src/man/
2648 f = open('man/%s.%s' % (self.c_type, section), 'w')
2649 f.write('.TH %s %s "%s" "%s" "XCB Events"\n' % (self.c_type, section, center_footer, left_footer))
2650 # Left-adjust instead of adjusting to both sides
2652 f.write('.SH NAME\n')
2653 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2654 f.write('%s \\- %s\n' % (self.c_type, brief))
2655 f.write('.SH SYNOPSIS\n')
2656 # Don't split words (hyphenate)
2658 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2661 f.write('.SS Event datastructure\n')
2664 f.write('typedef %s %s {\n' % (self.c_container, self.c_type))
2668 for field in self.fields:
2669 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2672 struct_fields.append(field)
2674 for field in struct_fields:
2675 length = len(field.c_field_type)
2676 # account for '*' pointer_spec
2677 if not field.type.fixed_size():
2679 maxtypelen = max(maxtypelen, length)
2681 def _c_complex_field(self, field, space=''):
2682 if (field.type.fixed_size() or
2683 # in case of switch with switch children, don't make the field a pointer
2684 # necessary for unserialize to work
2685 (self.is_switch and field.type.is_switch)):
2686 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2687 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2689 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2691 if not self.is_switch:
2692 for field in struct_fields:
2693 _c_complex_field(self, field)
2695 for b in self.bitcases:
2699 for field in b.type.fields:
2700 _c_complex_field(self, field, space)
2702 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2705 f.write('} \\fB%s\\fP;\n' % self.c_type)
2710 # Re-enable hyphenation and adjusting to both sides
2713 # argument reference
2714 f.write('.SH EVENT FIELDS\n')
2715 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2716 f.write(('The type of this event, in this case \\fI%s\\fP. This field is '
2717 'also present in the \\fIxcb_generic_event_t\\fP and can be used '
2718 'to tell events apart from each other.\n') % _n(name).upper())
2719 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2720 f.write('The sequence number of the last request processed by the X11 server.\n')
2722 if not self.is_switch:
2723 for field in struct_fields:
2724 # Skip the fields which every event has, we already documented
2726 if field.c_field_name in ('response_type', 'sequence'):
2728 if isinstance(field.type, PadType):
2730 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2731 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2732 desc = self.doc.fields[field.field_name]
2733 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2734 f.write('%s\n' % desc)
2736 f.write('NOT YET DOCUMENTED.\n')
2739 f.write('.SH DESCRIPTION\n')
2740 if hasattr(self, "doc") and self.doc and self.doc.description:
2741 desc = self.doc.description
2742 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2743 lines = desc.split('\n')
2744 f.write('\n'.join(lines) + '\n')
2746 if hasattr(self, "doc") and self.doc and self.doc.example:
2747 f.write('.SH EXAMPLE\n')
2750 lines = self.doc.example.split('\n')
2751 f.write('\n'.join(lines) + '\n')
2753 f.write('.SH SEE ALSO\n')
2754 if hasattr(self, "doc") and self.doc:
2755 see = ['.BR %s (%s)' % ('xcb_generic_event_t', section)]
2756 if self.doc.example:
2757 see.append('.BR %s (%s)' % ('xcb-examples', section))
2758 for seename, seetype in sorted(self.doc.see.items()):
2759 if seetype == 'program':
2760 see.append('.BR %s (1)' % seename)
2761 elif seetype == 'event':
2762 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2763 elif seetype == 'request':
2764 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2765 elif seetype == 'function':
2766 see.append('.BR %s (%s)' % (seename, section))
2768 see.append('TODO: %s (type %s)' % (seename, seetype))
2769 f.write(',\n'.join(see) + '\n')
2770 f.write('.SH AUTHOR\n')
2771 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2775 def c_request(self, name):
2777 Exported function that handles request declarations.
2779 _c_type_setup(self, name, ('request',))
2782 # Cookie type declaration
2783 _c_cookie(self, name)
2786 _c_opcode(name, self.opcode)
2788 # Request structure declaration
2792 _c_type_setup(self.reply, name, ('reply',))
2793 # Reply structure definition
2794 _c_complex(self.reply)
2795 # Request prototypes
2796 has_fds = _c_reply_has_fds(self.reply)
2797 _c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds)
2798 _c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds)
2800 _c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds)
2801 _c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds)
2803 _c_accessors(self.reply, name + ('reply',), name)
2804 _c_reply(self, name)
2806 _c_reply_fds(self, name)
2808 # Request prototypes
2809 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2810 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2812 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2813 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2815 # We generate the manpage afterwards because _c_type_setup has been called.
2816 # TODO: what about aux helpers?
2817 cookie_type = self.c_cookie_type if self.reply else 'xcb_void_cookie_t'
2818 _man_request(self, name, cookie_type, not self.reply, False)
2820 def c_event(self, name):
2822 Exported function that handles event declarations.
2825 # The generic event structure xcb_ge_event_t has the full_sequence field
2826 # at the 32byte boundary. That's why we've to inject this field into GE
2827 # events while generating the structure for them. Otherwise we would read
2828 # garbage (the internal full_sequence) when accessing normal event fields
2830 force_packed = False
2831 if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
2833 for field in self.fields:
2834 if field.type.size != None and field.type.nmemb != None:
2835 event_size += field.type.size * field.type.nmemb
2836 if event_size == 32:
2837 full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
2838 idx = self.fields.index(field)
2839 self.fields.insert(idx + 1, full_sequence)
2841 # If the event contains any 64-bit extended fields, they need
2842 # to remain aligned on a 64-bit boundary. Adding full_sequence
2843 # would normally break that; force the struct to be packed.
2844 force_packed = any(f.type.size == 8 and f.type.is_simple for f in self.fields[(idx+1):])
2847 _c_type_setup(self, name, ('event',))
2850 _c_opcode(name, self.opcodes[name])
2852 if self.name == name:
2853 # Structure definition
2854 _c_complex(self, force_packed)
2858 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2860 _man_event(self, name)
2862 def c_error(self, name):
2864 Exported function that handles error declarations.
2866 _c_type_setup(self, name, ('error',))
2869 _c_opcode(name, self.opcodes[name])
2871 if self.name == name:
2872 # Structure definition
2877 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2880 # Main routine starts here
2882 # Must create an "output" dictionary before any xcbgen imports.
2883 output = {'open' : c_open,
2885 'simple' : c_simple,
2887 'struct' : c_struct,
2889 'request' : c_request,
2894 # Boilerplate below this point
2896 # Check for the argument that specifies path to the xcbgen python package.
2898 opts, args = getopt.getopt(sys.argv[1:], 'c:l:s:p:m')
2899 except getopt.GetoptError as err:
2901 print('Usage: c_client.py -c center_footer -l left_footer -s section [-p path] file.xml')
2904 for (opt, arg) in opts:
2912 sys.path.insert(1, arg)
2915 sys.stdout.write('man_MANS = ')
2917 # Import the module class
2919 from xcbgen.state import Module
2920 from xcbgen.xtypes import *
2923 Failed to load the xcbgen Python package!
2924 Make sure that xcb/proto installed it on your Python path.
2925 If not, you will need to create a .pth file or define $PYTHONPATH
2927 Refer to the README file in xcb/proto for more info.
2931 # Ensure the man subdirectory exists
2934 except OSError as e:
2935 if e.errno != errno.EEXIST:
2938 # Parse the xml header
2939 module = Module(args[0], output)
2941 # Build type-registry and resolve type dependencies