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 if field.type.is_list:
873 # no such case in the protocol, cannot be tested and therefore ignored for now
874 raise Exception('list with fixed number of elemens unhandled in _unserialize()')
876 elif 'serialize' == context:
877 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
879 if field.type.is_expr:
880 # need to register a temporary variable for the expression in case we know its type
881 if field.type.c_type is None:
882 raise Exception("type for field '%s' (expression '%s') unkown" %
883 (field.field_name, _c_accessor_get_expr(field.type.expr)))
885 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
886 _c_accessor_get_expr(field.type.expr, prefix)))
887 value += "&xcb_expr_%s;" % _cpp(field.field_name)
889 elif field.type.is_pad:
890 if field.type.nmemb == 1:
893 # we could also set it to 0, see definition of xcb_send_request()
894 value = ' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
895 length += "*%d" % field.type.nmemb
898 # non-list type with fixed size
899 if field.type.nmemb == 1:
900 value += "&%s;" % (abs_field_name)
902 # list with nmemb (fixed size) elements
904 value += '%s;' % (abs_field_name)
905 length = '%d' % field.type.nmemb
907 return (value, length)
908 # _c_serialize_helper_fields_fixed_size()
910 def _c_serialize_helper_fields_variable_size(context, self, field,
911 code_lines, temp_vars,
913 prefix_str = _c_helper_absolute_name(prefix)
915 if context in ('unserialize', 'unpack', 'sizeof'):
917 var_field_name = 'xcb_tmp'
919 # special case: intermixed fixed and variable size fields
920 if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
921 value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
922 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
923 # special case: switch
924 if 'unpack' == context:
925 value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
927 elif 'serialize' == context:
928 # variable size fields appear as parameters to _serialize() if the
929 # 'toplevel' container is not a switch
930 prefix_string = prefix_str if prefix[0][2].is_switch else ''
931 var_field_name = "%s%s" % (prefix_string, field.c_field_name)
932 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
936 code_lines.append('%s /* %s */' % (space, field.c_field_name))
938 if field.type.is_list:
940 # in any context, list is already a pointer, so the default assignment is ok
941 code_lines.append("%s%s" % (space, value))
943 length = _c_serialize_helper_list_field(context, self, field,
944 code_lines, temp_vars,
947 elif field.type.is_switch:
949 if context == 'serialize':
950 # the _serialize() function allocates the correct amount memory if given a NULL pointer
951 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
952 length = _c_serialize_helper_switch_field(context, self, field,
953 'xcb_parts[xcb_parts_idx].iov_base',
957 # in all remaining special cases - call _sizeof()
958 length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
960 return (value, length)
961 # _c_serialize_helper_fields_variable_size
963 def _c_serialize_helper_fields(context, self,
964 code_lines, temp_vars,
965 space, prefix, is_case_or_bitcase):
968 prev_field_was_variable = False
970 for field in self.fields:
971 if not field.visible:
972 if not ((field.wire and not field.auto) or 'unserialize' == context):
975 # switch/bitcase: fixed size fields must be considered explicitly
976 if field.type.fixed_size():
977 if self.is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
978 if prev_field_was_variable and need_padding:
980 # count += _c_serialize_helper_insert_padding(context, code_lines, space,
981 # self.c_var_followed_by_fixed_fields)
982 prev_field_was_variable = False
984 # prefix for fixed size fields
985 fixed_prefix = prefix
987 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
988 code_lines, temp_vars,
993 # fields with variable size
995 if field.type.is_pad:
996 # Variable length pad is <pad align= />
997 code_lines.append('%s xcb_align_to = %d;' % (space, field.type.align))
998 count += _c_serialize_helper_insert_padding(context, code_lines, space,
999 self.c_var_followed_by_fixed_fields)
1002 # switch/bitcase: always calculate padding before and after variable sized fields
1003 if need_padding or is_case_or_bitcase:
1004 count += _c_serialize_helper_insert_padding(context, code_lines, space,
1005 self.c_var_followed_by_fixed_fields)
1007 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
1008 code_lines, temp_vars,
1010 prev_field_was_variable = True
1012 # save (un)serialization C code
1014 code_lines.append('%s%s' % (space, value))
1016 if field.type.fixed_size():
1017 if is_case_or_bitcase or self.c_var_followed_by_fixed_fields:
1018 # keep track of (un)serialized object's size
1019 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1020 if context in ('unserialize', 'unpack', 'sizeof'):
1021 code_lines.append('%s xcb_tmp += %s;' % (space, length))
1023 # variable size objects or bitcase:
1024 # value & length might have been inserted earlier for special cases
1026 # special case: intermixed fixed and variable size fields
1027 if (not field.type.fixed_size() and
1028 self.c_var_followed_by_fixed_fields and 'unserialize' == context):
1029 temp_vars.append(' int %s_len;' % field.c_field_name)
1030 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
1031 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
1032 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
1034 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1035 # increase pointer into the byte stream accordingly
1036 if context in ('unserialize', 'sizeof', 'unpack'):
1037 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1039 if 'serialize' == context:
1041 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
1042 code_lines.append('%s xcb_parts_idx++;' % space)
1045 code_lines.append('%s xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type))
1048 if self.c_var_followed_by_fixed_fields:
1049 need_padding = False
1052 # _c_serialize_helper_fields()
1054 def _c_serialize_helper(context, complex_type,
1055 code_lines, temp_vars,
1056 space='', prefix=[]):
1057 # count tracks the number of fields to serialize
1060 if hasattr(complex_type, 'type'):
1061 self = complex_type.type
1062 complex_name = complex_type.name
1065 if self.c_var_followed_by_fixed_fields and 'unserialize' == context:
1066 complex_name = 'xcb_out'
1068 complex_name = '_aux'
1070 # special case: switch is serialized by evaluating each bitcase separately
1072 count += _c_serialize_helper_switch(context, self, complex_name,
1073 code_lines, temp_vars,
1076 # all other data types can be evaluated one field a time
1078 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1079 if context in ('unserialize', 'unpack', 'sizeof') and not self.c_var_followed_by_fixed_fields:
1080 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1081 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1082 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
1083 code_lines.append('%s xcb_block_len = 0;' % space)
1085 count += _c_serialize_helper_fields(context, self,
1086 code_lines, temp_vars,
1087 space, prefix, False)
1089 count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
1092 # _c_serialize_helper()
1094 def _c_serialize(context, self):
1096 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1097 for the ComplexType variable self
1103 # _serialize() returns the buffer size
1106 if self.is_switch and 'unserialize' == context:
1109 cases = { 'serialize' : self.c_serialize_name,
1110 'unserialize' : self.c_unserialize_name,
1111 'unpack' : self.c_unpack_name,
1112 'sizeof' : self.c_sizeof_name }
1113 func_name = cases[context]
1115 param_fields, wire_fields, params = get_serialize_params(context, self)
1116 variable_size_fields = 0
1117 # maximum space required for type definition of function arguments
1120 # determine N(variable_fields)
1121 for field in param_fields:
1122 # if self.is_switch, treat all fields as if they are variable sized
1123 if not field.type.fixed_size() or self.is_switch:
1124 variable_size_fields += 1
1125 # determine maxtypelen
1127 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1130 indent = ' '*(len(func_name)+2)
1133 typespec, pointerspec, field_name = p
1134 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1135 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1136 # insert function name
1137 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1138 param_str = list(map(lambda x: "%s," % x, param_str))
1139 for s in param_str[:-1]:
1141 _h("%s);" % param_str[-1].rstrip(','))
1142 _c("%s)" % param_str[-1].rstrip(','))
1149 if 'serialize' == context:
1150 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1151 _c(' %s *xcb_out = *_buffer;', self.c_type)
1152 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1153 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1154 _c(' unsigned int xcb_align_to = 0;')
1156 _c(' char *xcb_out = *_buffer;')
1157 _c(' unsigned int xcb_buffer_len = 0;')
1158 _c(' unsigned int xcb_align_to = 0;')
1159 prefix = [('_aux', '->', self)]
1162 elif context in ('unserialize', 'unpack'):
1163 _c(' char *xcb_tmp = (char *)_buffer;')
1164 if not self.is_switch:
1165 if not self.c_var_followed_by_fixed_fields:
1166 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1167 prefix = [('_aux', '->', self)]
1169 _c(' %s xcb_out;', self.c_type)
1170 prefix = [('xcb_out', '.', self)]
1172 aux_var = '_aux' # default for unpack: single pointer
1173 # note: unserialize not generated for switch
1174 if 'unserialize' == context:
1175 aux_var = '(*_aux)' # unserialize: double pointer (!)
1176 prefix = [(aux_var, '->', self)]
1178 _c(' unsigned int xcb_buffer_len = 0;')
1179 _c(' unsigned int xcb_block_len = 0;')
1180 _c(' unsigned int xcb_pad = 0;')
1181 _c(' unsigned int xcb_align_to = 0;')
1183 elif 'sizeof' == context:
1184 param_names = [p[2] for p in params]
1186 # switch: call _unpack()
1187 _c(' %s _aux;', self.c_type)
1188 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1191 elif self.c_var_followed_by_fixed_fields:
1192 # special case: call _unserialize()
1193 _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1197 _c(' char *xcb_tmp = (char *)_buffer;')
1198 prefix = [('_aux', '->', self)]
1200 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1201 # update variable size fields (only important for context=='serialize'
1202 variable_size_fields = count
1203 if 'serialize' == context:
1204 temp_vars.append(' unsigned int xcb_pad = 0;')
1205 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1206 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1207 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1208 temp_vars.append(' unsigned int xcb_block_len = 0;')
1209 temp_vars.append(' unsigned int i;')
1210 temp_vars.append(' char *xcb_tmp;')
1211 elif 'sizeof' == context:
1212 # neither switch nor intermixed fixed and variable size fields:
1213 # evaluate parameters directly
1214 if not (self.is_switch or self.c_var_followed_by_fixed_fields):
1216 # look if we have to declare an '_aux' variable at all
1217 if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
1218 if not self.c_var_followed_by_fixed_fields:
1219 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1221 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1223 _c(' unsigned int xcb_buffer_len = 0;')
1224 _c(' unsigned int xcb_block_len = 0;')
1225 _c(' unsigned int xcb_pad = 0;')
1226 _c(' unsigned int xcb_align_to = 0;')
1232 for l in code_lines:
1235 # variable sized fields have been collected, now
1236 # allocate memory and copy everything into a continuous memory area
1237 # note: this is not necessary in case of unpack
1238 if context in ('serialize', 'unserialize'):
1239 # unserialize: check for sizeof-only invocation
1240 if 'unserialize' == context:
1242 _c(' if (NULL == _aux)')
1243 _c(' return xcb_buffer_len;')
1246 _c(' if (NULL == %s) {', aux_ptr)
1247 _c(' /* allocate memory */')
1248 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1249 if 'serialize' == context:
1250 _c(' *_buffer = xcb_out;')
1254 # serialize: handle variable size fields in a loop
1255 if 'serialize' == context:
1256 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1257 if len(wire_fields)>0:
1258 _c(' *xcb_out = *_aux;')
1259 # copy variable size fields into the buffer
1260 if variable_size_fields > 0:
1262 if not self.is_switch and not self.c_var_followed_by_fixed_fields:
1263 _c(' xcb_tmp = (char*)++xcb_out;')
1264 _c(' xcb_tmp += xcb_out_pad;')
1266 _c(' xcb_tmp = xcb_out;')
1268 # variable sized fields
1269 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1270 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1271 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1272 _c(' if (0 != xcb_parts[i].iov_len)')
1273 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1276 # unserialize: assign variable size fields individually
1277 if 'unserialize' == context:
1278 _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1279 param_fields.reverse()
1280 for field in param_fields:
1281 if not field.type.fixed_size():
1282 _c(' xcb_tmp -= %s_len;', field.c_field_name)
1283 _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1284 _c(' *%s = xcb_out;', aux_ptr)
1287 _c(' return xcb_buffer_len;')
1291 def _c_iterator_get_end(field, accum):
1293 Figures out what C code is needed to find the end of a variable-length structure field.
1294 For nested structures, recurses into its last variable-sized field.
1295 For lists, calls the end function
1297 if field.type.is_container:
1298 accum = field.c_accessor_name + '(' + accum + ')'
1299 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1300 if field.type.is_list:
1301 # XXX we can always use the first way
1302 if field.type.member.is_simple:
1303 return field.c_end_name + '(' + accum + ')'
1305 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1307 def _c_iterator(self, name):
1309 Declares the iterator structure and next/end functions for a given type.
1314 _h(' * @brief %s', self.c_iterator_type)
1316 _h('typedef struct %s {', self.c_iterator_type)
1317 _h(' %s *data; /**< */', self.c_type)
1318 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1319 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1320 _h('} %s;', self.c_iterator_type)
1326 _h(' * Get the next element of the iterator')
1327 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1329 _h(' * Get the next element in the iterator. The member rem is')
1330 _h(' * decreased by one. The member data points to the next')
1331 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1335 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1336 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1339 if not self.fixed_size():
1340 _c(' %s *R = i->data;', self.c_type)
1343 # FIXME - how to determine the size of a variable size union??
1344 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1346 if self.c_need_sizeof:
1347 _c(' xcb_generic_iterator_t child;')
1348 _c(' child.data = (%s *)(((char *)R) + %s(R));',
1349 self.c_type, self.c_sizeof_name)
1350 _c(' i->index = (char *) child.data - (char *) i->data;')
1352 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1353 _c(' i->index = child.index;')
1355 _c(' i->data = (%s *) child.data;', self.c_type)
1360 _c(' i->index += sizeof(%s);', self.c_type)
1366 _h(' * Return the iterator pointing to the last element')
1367 _h(' * @param i An %s', self.c_iterator_type)
1368 _h(' * @return The iterator pointing to the last element')
1370 _h(' * Set the current element in the iterator to the last element.')
1371 _h(' * The member rem is set to 0. The member data points to the')
1372 _h(' * last element.')
1375 _hc('xcb_generic_iterator_t')
1376 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1377 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1379 _c(' xcb_generic_iterator_t ret;')
1381 if self.fixed_size():
1382 _c(' ret.data = i.data + i.rem;')
1383 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1386 _c(' while(i.rem > 0)')
1387 _c(' %s(&i);', self.c_next_name)
1388 _c(' ret.data = i.data;')
1389 _c(' ret.rem = i.rem;')
1390 _c(' ret.index = i.index;')
1395 def _c_accessor_get_length(expr, field_mapping=None):
1397 Figures out what C code is needed to get a length field.
1398 The field_mapping parameter can be used to change the absolute name of a length field.
1399 For fields that follow a variable-length field, use the accessor.
1400 Otherwise, just reference the structure field directly.
1403 lenfield_name = expr.lenfield_name
1404 if lenfield_name is not None:
1405 if field_mapping is not None:
1406 lenfield_name = field_mapping[lenfield_name][0]
1408 if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1409 # special case: variable and fixed size fields are intermixed
1410 # if the lenfield is among the fixed size fields, there is no need
1411 # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1412 return field_mapping(expr.lenfield_name)
1413 elif expr.lenfield_name is not None:
1414 return lenfield_name
1416 return str(expr.nmemb)
1418 def _c_accessor_get_expr(expr, field_mapping):
1420 Figures out what C code is needed to get the length of a list field.
1421 The field_mapping parameter can be used to change the absolute name of a length field.
1422 Recurses for math operations.
1423 Returns bitcount for value-mask fields.
1424 Otherwise, uses the value of the length field.
1426 lenexp = _c_accessor_get_length(expr, field_mapping)
1429 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1430 elif expr.op == 'popcount':
1431 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1432 elif expr.op == 'enumref':
1433 enum_name = expr.lenfield_type.name
1434 constant_name = expr.lenfield_name
1435 c_name = _n(enum_name + (constant_name,)).upper()
1437 elif expr.op == 'sumof':
1438 # locate the referenced list object
1439 list_obj = expr.lenfield_type
1441 for f in expr.lenfield_parent.fields:
1442 if f.field_name == expr.lenfield_name:
1447 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1448 list_name = field_mapping[field.c_field_name][0]
1449 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1450 # note: xcb_sumof() has only been defined for integers
1451 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1452 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1453 elif expr.op != None:
1454 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1455 ' ' + expr.op + ' ' +
1456 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1458 return 'xcb_popcount(' + lenexp + ')'
1462 def type_pad_type(type):
1467 def _c_accessors_field(self, field):
1469 Declares the accessor functions for a non-list field that follows a variable-length field.
1471 c_type = self.c_type
1473 # special case: switch
1474 switch_obj = self if self.is_switch else None
1475 if self.is_case_or_bitcase:
1476 switch_obj = self.parents[-1]
1477 if switch_obj is not None:
1478 c_type = switch_obj.c_type
1480 if field.type.is_simple:
1482 _hc('%s', field.c_field_type)
1483 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1484 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1486 if field.prev_varsized_field is None:
1487 _c(' return (%s *) (R + 1);', field.c_field_type)
1489 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1490 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1491 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1495 if field.type.is_switch and switch_obj is None:
1496 return_type = 'void *'
1498 return_type = '%s *' % field.c_field_type
1501 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1502 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1504 if field.prev_varsized_field is None:
1505 _c(' return (%s) (R + 1);', return_type)
1506 # note: the special case 'variable fields followed by fixed size fields'
1507 # is not of any consequence here, since the ordering gets
1508 # 'corrected' in the reply function
1510 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1511 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1512 return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1516 def _c_accessors_list(self, field):
1518 Declares the accessor functions for a list field.
1519 Declares a direct-accessor function only if the list members are fixed size.
1520 Declares length and get-iterator functions always.
1523 def get_align_pad(field):
1524 prev = field.prev_varsized_field
1525 prev_prev = field.prev_varsized_field.prev_varsized_field
1527 if (prev.type.is_pad and prev.type.align > 0 and prev_prev is not None):
1528 return (prev_prev, '((-prev.index) & (%d - 1))' % prev.type.align)
1534 c_type = self.c_type
1536 # special case: switch
1537 # in case of switch, 2 params have to be supplied to certain accessor functions:
1538 # 1. the anchestor object (request or reply)
1539 # 2. the (anchestor) switch object
1540 # the reason is that switch is either a child of a request/reply or nested in another switch,
1541 # so whenever we need to access a length field, we might need to refer to some anchestor type
1542 switch_obj = self if self.is_switch else None
1543 if self.is_case_or_bitcase:
1544 switch_obj = self.parents[-1]
1545 if switch_obj is not None:
1546 c_type = switch_obj.c_type
1550 parents = self.parents if hasattr(self, 'parents') else [self]
1551 # 'R': parents[0] is always the 'toplevel' container type
1552 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1553 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1554 # auxiliary object for 'R' parameters
1557 if switch_obj is not None:
1558 # now look where the fields are defined that are needed to evaluate
1559 # the switch expr, and store the parent objects in accessor_params and
1560 # the fields in switch_fields
1562 # 'S': name for the 'toplevel' switch
1563 toplevel_switch = parents[1]
1564 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1565 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1567 # initialize prefix for everything "below" S
1568 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1569 prefix = [(prefix_str, '->', toplevel_switch)]
1571 # look for fields in the remaining containers
1572 for p in parents[2:] + [self]:
1573 # the separator between parent and child is always '.' here,
1574 # because of nested switch statements
1575 if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
1576 prefix.append((p.name[-1], '.', p))
1577 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1579 # auxiliary object for 'S' parameter
1584 if list.member.fixed_size():
1585 idx = 1 if switch_obj is not None else 0
1587 _hc('%s *', field.c_field_type)
1589 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1590 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1593 if switch_obj is not None:
1594 _c(' return %s;', fields[field.c_field_name][0])
1595 elif field.prev_varsized_field is None:
1596 _c(' return (%s *) (R + 1);', field.c_field_type)
1598 (prev_varsized_field, align_pad) = get_align_pad(field)
1600 if align_pad is None:
1601 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
1602 type_pad_type(field.first_field_after_varsized.type.c_type))
1604 _c(' xcb_generic_iterator_t prev = %s;',
1605 _c_iterator_get_end(prev_varsized_field, 'R'))
1606 _c(' return (%s *) ((char *) prev.data + %s + %d);',
1607 field.c_field_type, align_pad, field.prev_varsized_offset)
1612 if switch_obj is not None:
1613 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1614 spacing = ' '*(len(field.c_length_name)+2)
1615 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1616 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1617 length = _c_accessor_get_expr(field.type.expr, fields)
1619 _h('%s (const %s *R /**< */);', field.c_length_name, c_type)
1620 _c('%s (const %s *R /**< */)', field.c_length_name, c_type)
1621 length = _c_accessor_get_expr(field.type.expr, fields)
1623 _c(' return %s;', length)
1626 if field.type.member.is_simple:
1628 _hc('xcb_generic_iterator_t')
1629 if switch_obj is not None:
1630 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1631 spacing = ' '*(len(field.c_end_name)+2)
1632 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1633 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1635 _h('%s (const %s *R /**< */);', field.c_end_name, c_type)
1636 _c('%s (const %s *R /**< */)', field.c_end_name, c_type)
1638 _c(' xcb_generic_iterator_t i;')
1640 param = 'R' if switch_obj is None else 'S'
1641 if switch_obj is not None:
1642 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1643 _c_accessor_get_expr(field.type.expr, fields))
1644 elif field.prev_varsized_field == None:
1645 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1646 _c_accessor_get_expr(field.type.expr, fields))
1648 _c(' xcb_generic_iterator_t child = %s;',
1649 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1650 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1651 _c_accessor_get_expr(field.type.expr, fields))
1654 _c(' i.index = (char *) i.data - (char *) %s;', param)
1660 _hc('%s', field.c_iterator_type)
1661 if switch_obj is not None:
1662 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1663 spacing = ' '*(len(field.c_iterator_name)+2)
1664 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1665 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1667 _h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
1668 _c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
1670 _c(' %s i;', field.c_iterator_type)
1672 if switch_obj is not None:
1673 _c(' i.data = %s;', fields[field.c_field_name][0])
1674 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1675 elif field.prev_varsized_field == None:
1676 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1678 (prev_varsized_field, align_pad) = get_align_pad(field)
1680 if align_pad is None:
1681 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
1682 type_pad_type(field.c_field_type))
1684 _c(' xcb_generic_iterator_t prev = %s;',
1685 _c_iterator_get_end(prev_varsized_field, 'R'))
1686 _c(' i.data = (%s *) ((char *) prev.data + %s);',
1687 field.c_field_type, align_pad)
1689 if switch_obj is None:
1690 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1691 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1695 def _c_accessors(self, name, base):
1697 Declares the accessor functions for the fields of a structure.
1699 # no accessors for switch itself -
1700 # switch always needs to be unpacked explicitly
1701 # if self.is_switch:
1705 for field in self.fields:
1706 if not field.type.is_pad:
1707 if field.type.is_list and not field.type.fixed_size():
1708 _c_accessors_list(self, field)
1709 elif field.prev_varsized_field is not None or not field.type.fixed_size():
1710 _c_accessors_field(self, field)
1712 def c_simple(self, name):
1714 Exported function that handles cardinal type declarations.
1715 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1717 _c_type_setup(self, name, ())
1719 if (self.name != name):
1724 _h('typedef %s %s;', _t(self.name), my_name)
1727 _c_iterator(self, name)
1729 def _c_complex(self, force_packed = False):
1731 Helper function for handling all structure types.
1732 Called for all structs, requests, replies, events, errors.
1737 _h(' * @brief %s', self.c_type)
1739 _h('typedef %s %s {', self.c_container, self.c_type)
1745 for field in self.fields:
1746 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1747 varfield = field.c_field_name
1750 struct_fields.append(field)
1752 for field in struct_fields:
1753 length = len(field.c_field_type)
1754 # account for '*' pointer_spec
1755 if not field.type.fixed_size() and not self.is_union:
1757 maxtypelen = max(maxtypelen, length)
1759 def _c_complex_field(self, field, space=''):
1760 if (field.type.fixed_size() or self.is_union or
1761 # in case of switch with switch children, don't make the field a pointer
1762 # necessary for unserialize to work
1763 (self.is_switch and field.type.is_switch)):
1764 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1765 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1767 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1768 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1770 if not self.is_switch:
1771 for field in struct_fields:
1772 _c_complex_field(self, field)
1774 for b in self.bitcases:
1777 _h(' struct _%s {', b.c_field_name)
1779 for field in b.type.fields:
1780 _c_complex_field(self, field, space)
1782 _h(' } %s;', b.c_field_name)
1784 _h('} %s%s;', 'XCB_PACKED ' if force_packed else '', self.c_type)
1786 def c_struct(self, name):
1788 Exported function that handles structure declarations.
1790 _c_type_setup(self, name, ())
1792 _c_accessors(self, name, name)
1793 _c_iterator(self, name)
1795 def c_union(self, name):
1797 Exported function that handles union declarations.
1799 _c_type_setup(self, name, ())
1801 _c_iterator(self, name)
1803 def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_fds=False):
1805 Declares a request function.
1808 # Four stunningly confusing possibilities here:
1811 # ------------------------------
1813 # 0 flag CHECKED flag Normal Mode
1814 # void_cookie req_cookie
1815 # ------------------------------
1816 # "req_checked" "req_unchecked"
1817 # CHECKED flag 0 flag Abnormal Mode
1818 # void_cookie req_cookie
1819 # ------------------------------
1822 # Whether we are _checked or _unchecked
1823 checked = void and not regular
1824 unchecked = not void and not regular
1826 # What kind of cookie we return
1827 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1829 # What flag is passed to xcb_request
1830 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1833 if func_flags == '0':
1834 func_flags = 'XCB_REQUEST_REPLY_FDS'
1836 func_flags = func_flags + '|XCB_REQUEST_REPLY_FDS'
1838 # Global extension id variable or NULL for xproto
1839 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1841 # What our function name is
1842 func_name = self.c_request_name if not aux else self.c_aux_name
1844 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1846 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1850 maxtypelen = len('xcb_connection_t')
1852 # special case: list with variable size elements
1853 list_with_var_size_elems = False
1855 for field in self.fields:
1857 # The field should appear as a call parameter
1858 param_fields.append(field)
1859 if field.wire and not field.auto:
1860 # We need to set the field up in the structure
1861 wire_fields.append(field)
1862 if field.type.c_need_serialize or field.type.c_need_sizeof:
1863 serial_fields.append(field)
1865 for field in param_fields:
1866 c_field_const_type = field.c_field_const_type
1867 if field.type.c_need_serialize and not aux:
1868 c_field_const_type = "const void"
1869 if len(c_field_const_type) > maxtypelen:
1870 maxtypelen = len(c_field_const_type)
1871 if field.type.is_list and not field.type.member.fixed_size():
1872 list_with_var_size_elems = True
1878 if hasattr(self, "doc") and self.doc:
1880 _h(' * @brief ' + self.doc.brief)
1882 _h(' * No brief doc yet')
1885 _h(' * @param c The connection')
1886 param_names = [f.c_field_name for f in param_fields]
1887 if hasattr(self, "doc") and self.doc:
1888 for field in param_fields:
1889 # XXX: hard-coded until we fix xproto.xml
1890 base_func_name = self.c_request_name if not aux else self.c_aux_name
1891 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
1893 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
1895 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
1898 # XXX: why the 'xcb' prefix?
1899 key = ('xcb', field.enum)
1902 if namecount[tname] > 1:
1903 tname = _t(key + ('enum',))
1904 _h(' * @param %s A bitmask of #%s values.' % (field.c_field_name, tname))
1906 if self.doc and field.field_name in self.doc.fields:
1907 desc = self.doc.fields[field.field_name]
1908 for name in param_names:
1909 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1910 desc = desc.split("\n")
1911 desc = [line if line != '' else '\\n' for line in desc]
1912 _h(' * @param %s %s' % (field.c_field_name, "\n * ".join(desc)))
1913 # If there is no documentation yet, we simply don't generate an
1914 # @param tag. Doxygen will then warn about missing documentation.
1916 _h(' * @return A cookie')
1919 if hasattr(self, "doc") and self.doc:
1920 if self.doc.description:
1921 desc = self.doc.description
1922 for name in param_names:
1923 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1924 desc = desc.split("\n")
1925 _h(' * ' + "\n * ".join(desc))
1927 _h(' * No description yet')
1929 _h(' * Delivers a request to the X server.')
1932 _h(' * This form can be used only if the request will not cause')
1933 _h(' * a reply to be generated. Any returned error will be')
1934 _h(' * saved for handling by xcb_request_check().')
1936 _h(' * This form can be used only if the request will cause')
1937 _h(' * a reply to be generated. Any returned error will be')
1938 _h(' * placed in the event queue.')
1941 _hc('%s', cookie_type)
1943 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1944 comma = ',' if len(param_fields) else ');'
1945 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1946 comma = ',' if len(param_fields) else ')'
1947 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1949 func_spacing = ' ' * (len(func_name) + 2)
1950 count = len(param_fields)
1951 for field in param_fields:
1953 c_field_const_type = field.c_field_const_type
1954 c_pointer = field.c_pointer
1955 if field.type.c_need_serialize and not aux:
1956 c_field_const_type = "const void"
1958 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1959 comma = ',' if count else ');'
1960 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1961 spacing, c_pointer, field.c_field_name, comma)
1962 comma = ',' if count else ')'
1963 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1964 spacing, c_pointer, field.c_field_name, comma)
1967 if not self.c_var_followed_by_fixed_fields:
1968 for field in param_fields:
1969 if not field.type.fixed_size():
1971 if field.type.c_need_serialize:
1972 # _serialize() keeps track of padding automatically
1974 dimension = count + 2
1977 _c(' static const xcb_protocol_request_t xcb_req = {')
1978 _c(' /* count */ %d,', count)
1979 _c(' /* ext */ %s,', func_ext_global)
1980 _c(' /* opcode */ %s,', self.c_request_name.upper())
1981 _c(' /* isvoid */ %d', 1 if void else 0)
1985 _c(' struct iovec xcb_parts[%d];', dimension)
1986 _c(' %s xcb_ret;', func_cookie)
1987 _c(' %s xcb_out;', self.c_type)
1988 if self.c_var_followed_by_fixed_fields:
1989 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
1990 _c(' void *xcb_aux = 0;')
1993 for idx, f in enumerate(serial_fields):
1995 _c(' void *xcb_aux%d = 0;' % (idx))
1996 if list_with_var_size_elems:
1997 _c(' unsigned int i;')
1998 _c(' unsigned int xcb_tmp_len;')
1999 _c(' char *xcb_tmp;')
2001 # simple request call tracing
2002 # _c(' printf("in function %s\\n");' % func_name)
2005 for field in wire_fields:
2006 if field.type.fixed_size():
2007 if field.type.is_expr:
2008 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
2009 elif field.type.is_pad:
2010 if field.type.nmemb == 1:
2011 _c(' xcb_out.%s = 0;', field.c_field_name)
2013 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
2015 if field.type.nmemb == 1:
2016 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
2018 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
2020 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
2021 serialize_args = get_serialize_params(context, type_obj,
2024 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
2026 # calls in order to free dyn. all. memory
2030 if not self.c_var_followed_by_fixed_fields:
2031 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2032 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
2033 _c(' xcb_parts[3].iov_base = 0;')
2034 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2038 for field in param_fields:
2039 if not field.type.fixed_size():
2040 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
2041 # default: simple cast to char *
2042 if not field.type.c_need_serialize and not field.type.c_need_sizeof:
2043 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2044 if field.type.is_list:
2045 if field.type.member.fixed_size():
2046 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
2047 _c_accessor_get_expr(field.type.expr, None),
2048 field.type.member.c_wiretype)
2050 list_length = _c_accessor_get_expr(field.type.expr, None)
2053 _c(" xcb_parts[%d].iov_len = 0;" % count)
2054 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2055 _c(" for(i=0; i<%s; i++) {" % list_length)
2056 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2057 (field.type.c_sizeof_name))
2058 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2059 _c(" xcb_tmp += xcb_tmp_len;")
2062 # not supposed to happen
2063 raise Exception("unhandled variable size field %s" % field.c_field_name)
2066 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2067 idx = serial_fields.index(field)
2068 aux_var = '&xcb_aux%d' % idx
2069 context = 'serialize' if aux else 'sizeof'
2070 _c(' xcb_parts[%d].iov_len =', count)
2072 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2073 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2074 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2075 free_calls.append(' free(xcb_aux%d);' % idx)
2077 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2078 func_name = field.type.c_sizeof_name
2079 _c(' %s (%s);', func_name, serialize_args)
2082 if not (field.type.c_need_serialize or field.type.c_need_sizeof):
2083 # the _serialize() function keeps track of padding automatically
2084 _c(' xcb_parts[%d].iov_base = 0;', count)
2085 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2088 # elif self.c_var_followed_by_fixed_fields:
2090 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2091 # request header: opcodes + length
2092 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2095 buffer_var = '&xcb_aux'
2096 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2097 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2098 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2099 free_calls.append(' free(xcb_aux);')
2100 # no padding necessary - _serialize() keeps track of padding automatically
2103 for field in param_fields:
2105 _c(' xcb_send_fd(c, %s);', field.c_field_name)
2107 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2109 # free dyn. all. data, if any
2110 for f in free_calls:
2112 _c(' return xcb_ret;')
2115 def _c_reply(self, name):
2117 Declares the function that returns the reply structure.
2119 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2120 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2121 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2123 # check if _unserialize() has to be called for any field
2124 def look_for_special_cases(complex_obj):
2125 unserialize_fields = []
2126 # no unserialize call in case of switch
2127 if not complex_obj.is_switch:
2128 for field in complex_obj.fields:
2129 # three cases: 1. field with special case
2130 # 2. container that contains special case field
2131 # 3. list with special case elements
2132 if field.type.c_var_followed_by_fixed_fields:
2133 unserialize_fields.append(field)
2134 elif field.type.is_container:
2135 unserialize_fields += look_for_special_cases(field.type)
2136 elif field.type.is_list:
2137 if field.type.member.c_var_followed_by_fixed_fields:
2138 unserialize_fields.append(field)
2139 if field.type.member.is_container:
2140 unserialize_fields += look_for_special_cases(field.type.member)
2141 return unserialize_fields
2143 unserialize_fields = look_for_special_cases(self.reply)
2147 _h(' * Return the reply')
2148 _h(' * @param c The connection')
2149 _h(' * @param cookie The cookie')
2150 _h(' * @param e The xcb_generic_error_t supplied')
2152 _h(' * Returns the reply of the request asked by')
2154 _h(' * The parameter @p e supplied to this function must be NULL if')
2155 _h(' * %s(). is used.', self.c_unchecked_name)
2156 _h(' * Otherwise, it stores the error if any.')
2158 _h(' * The returned value must be freed by the caller using free().')
2161 _hc('%s *', self.c_reply_type)
2162 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2163 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2164 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2165 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2168 if len(unserialize_fields)>0:
2169 # certain variable size fields need to be unserialized explicitly
2170 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2171 self.c_reply_type, self.c_reply_type)
2173 for field in unserialize_fields:
2174 if field.type.is_list:
2175 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2176 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2177 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2179 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2180 # call _unserialize(), using the reply as source and target buffer
2181 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2182 for field in unserialize_fields:
2183 if field.type.is_list:
2184 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2185 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2186 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2187 field.c_field_name, field.c_field_name)
2188 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2190 # return the transformed reply
2191 _c(' return reply;')
2194 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2198 def _c_reply_has_fds(self):
2199 for field in self.fields:
2204 def _c_reply_fds(self, name):
2206 Declares the function that returns fds related to the reply.
2208 spacing1 = ' ' * (len(self.c_reply_type) - len('xcb_connection_t'))
2209 spacing3 = ' ' * (len(self.c_reply_fds_name) + 2)
2212 _h(' * Return the reply fds')
2213 _h(' * @param c The connection')
2214 _h(' * @param reply The reply')
2216 _h(' * Returns the array of reply fds of the request asked by')
2218 _h(' * The returned value must be freed by the caller using free().')
2222 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_fds_name, spacing1)
2223 _h('%s%s *reply /**< */);', spacing3, self.c_reply_type)
2224 _c('%s%s *reply /**< */)', spacing3, self.c_reply_type)
2227 _c(' return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
2232 def _c_opcode(name, opcode):
2234 Declares the opcode define for requests, events, and errors.
2238 _h('/** Opcode for %s. */', _n(name))
2239 _h('#define %s %s', _n(name).upper(), opcode)
2241 def _c_cookie(self, name):
2243 Declares the cookie type for a non-void request.
2248 _h(' * @brief %s', self.c_cookie_type)
2250 _h('typedef struct %s {', self.c_cookie_type)
2251 _h(' unsigned int sequence; /**< */')
2252 _h('} %s;', self.c_cookie_type)
2254 def _man_request(self, name, cookie_type, void, aux):
2255 param_fields = [f for f in self.fields if f.visible]
2257 func_name = self.c_request_name if not aux else self.c_aux_name
2259 def create_link(linkname):
2260 name = 'man/%s.%s' % (linkname, section)
2262 sys.stdout.write(name)
2264 f.write('.so man%s/%s.%s' % (section, func_name, section))
2268 sys.stdout.write('man/%s.%s ' % (func_name, section))
2269 # Our CWD is src/, so this will end up in src/man/
2270 f = open('man/%s.%s' % (func_name, section), 'w')
2271 f.write('.TH %s %s "%s" "%s" "XCB Requests"\n' % (func_name, section, center_footer, left_footer))
2272 # Left-adjust instead of adjusting to both sides
2274 f.write('.SH NAME\n')
2275 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2276 f.write('%s \\- %s\n' % (func_name, brief))
2277 f.write('.SH SYNOPSIS\n')
2278 # Don't split words (hyphenate)
2280 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2282 # function prototypes
2284 count = len(param_fields)
2285 for field in param_fields:
2287 c_field_const_type = field.c_field_const_type
2288 c_pointer = field.c_pointer
2289 if c_pointer == ' ':
2291 if field.type.c_need_serialize and not aux:
2292 c_field_const_type = "const void"
2294 comma = ', ' if count else ');'
2295 prototype += '%s\\ %s\\fI%s\\fP%s' % (c_field_const_type, c_pointer, field.c_field_name, comma)
2297 f.write('.SS Request function\n')
2299 base_func_name = self.c_request_name if not aux else self.c_aux_name
2300 f.write('%s \\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\n' % (cookie_type, base_func_name, prototype))
2301 create_link('%s_%s' % (base_func_name, ('checked' if void else 'unchecked')))
2304 f.write('.SS Reply datastructure\n')
2307 f.write('typedef %s %s {\n' % (self.reply.c_container, self.reply.c_type))
2311 for field in self.reply.fields:
2312 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2315 struct_fields.append(field)
2317 for field in struct_fields:
2318 length = len(field.c_field_type)
2319 # account for '*' pointer_spec
2320 if not field.type.fixed_size():
2322 maxtypelen = max(maxtypelen, length)
2324 def _c_complex_field(self, field, space=''):
2325 if (field.type.fixed_size() or
2326 # in case of switch with switch children, don't make the field a pointer
2327 # necessary for unserialize to work
2328 (self.is_switch and field.type.is_switch)):
2329 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2330 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2332 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
2333 f.write('ELSE %s = %s\n' % (field.c_field_type, field.c_field_name))
2334 #_h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2336 if not self.is_switch:
2337 for field in struct_fields:
2338 _c_complex_field(self, field)
2340 for b in self.bitcases:
2344 for field in b.type.fields:
2345 _c_complex_field(self, field, space)
2347 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2350 f.write('} \\fB%s\\fP;\n' % self.reply.c_type)
2353 f.write('.SS Reply function\n')
2355 f.write(('%s *\\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\\ '
2356 '\\fIcookie\\fP, xcb_generic_error_t\\ **\\fIe\\fP);\n') %
2357 (self.c_reply_type, self.c_reply_name, self.c_cookie_type))
2358 create_link('%s' % self.c_reply_name)
2360 has_accessors = False
2361 for field in self.reply.fields:
2362 if field.type.is_list and not field.type.fixed_size():
2363 has_accessors = True
2364 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2365 has_accessors = True
2368 f.write('.SS Reply accessors\n')
2370 def _c_accessors_field(self, field):
2372 Declares the accessor functions for a non-list field that follows a variable-length field.
2374 c_type = self.c_type
2376 # special case: switch
2377 switch_obj = self if self.is_switch else None
2378 if self.is_case_or_bitcase:
2379 switch_obj = self.parents[-1]
2380 if switch_obj is not None:
2381 c_type = switch_obj.c_type
2383 if field.type.is_simple:
2384 f.write('%s %s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2385 create_link('%s' % field.c_accessor_name)
2387 f.write('%s *%s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2388 create_link('%s' % field.c_accessor_name)
2390 def _c_accessors_list(self, field):
2392 Declares the accessor functions for a list field.
2393 Declares a direct-accessor function only if the list members are fixed size.
2394 Declares length and get-iterator functions always.
2397 c_type = self.reply.c_type
2399 # special case: switch
2400 # in case of switch, 2 params have to be supplied to certain accessor functions:
2401 # 1. the anchestor object (request or reply)
2402 # 2. the (anchestor) switch object
2403 # the reason is that switch is either a child of a request/reply or nested in another switch,
2404 # so whenever we need to access a length field, we might need to refer to some anchestor type
2405 switch_obj = self if self.is_switch else None
2406 if self.is_case_or_bitcase:
2407 switch_obj = self.parents[-1]
2408 if switch_obj is not None:
2409 c_type = switch_obj.c_type
2413 parents = self.parents if hasattr(self, 'parents') else [self]
2414 # 'R': parents[0] is always the 'toplevel' container type
2415 params.append(('const %s *\\fIreply\\fP' % parents[0].c_type, parents[0]))
2416 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
2417 # auxiliary object for 'R' parameters
2420 if switch_obj is not None:
2421 # now look where the fields are defined that are needed to evaluate
2422 # the switch expr, and store the parent objects in accessor_params and
2423 # the fields in switch_fields
2425 # 'S': name for the 'toplevel' switch
2426 toplevel_switch = parents[1]
2427 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
2428 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
2430 # initialize prefix for everything "below" S
2431 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
2432 prefix = [(prefix_str, '->', toplevel_switch)]
2434 # look for fields in the remaining containers
2435 for p in parents[2:] + [self]:
2436 # the separator between parent and child is always '.' here,
2437 # because of nested switch statements
2438 if not p.is_case_or_bitcase or (p.is_case_or_bitcase and p.has_name):
2439 prefix.append((p.name[-1], '.', p))
2440 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
2442 # auxiliary object for 'S' parameter
2445 if list.member.fixed_size():
2446 idx = 1 if switch_obj is not None else 0
2448 f.write('%s *\\fB%s\\fP(%s);\n' %
2449 (field.c_field_type, field.c_accessor_name, params[idx][0]))
2450 create_link('%s' % field.c_accessor_name)
2453 f.write('int \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2454 (field.c_length_name, c_type))
2455 create_link('%s' % field.c_length_name)
2457 if field.type.member.is_simple:
2459 f.write('xcb_generic_iterator_t \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2460 (field.c_end_name, c_type))
2461 create_link('%s' % field.c_end_name)
2464 f.write('%s \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2465 (field.c_iterator_type, field.c_iterator_name,
2467 create_link('%s' % field.c_iterator_name)
2469 for field in self.reply.fields:
2470 if field.type.is_list and not field.type.fixed_size():
2471 _c_accessors_list(self, field)
2472 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2473 _c_accessors_field(self, field)
2477 # Re-enable hyphenation and adjusting to both sides
2480 # argument reference
2481 f.write('.SH REQUEST ARGUMENTS\n')
2482 f.write('.IP \\fI%s\\fP 1i\n' % 'conn')
2483 f.write('The XCB connection to X11.\n')
2484 for field in param_fields:
2485 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2486 printed_enum = False
2487 # XXX: hard-coded until we fix xproto.xml
2488 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
2490 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
2492 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
2494 if hasattr(field, "enum") and field.enum:
2495 # XXX: why the 'xcb' prefix?
2496 key = ('xcb', field.enum)
2498 f.write('One of the following values:\n')
2501 count = len(enum.values)
2502 for (enam, eval) in enum.values:
2504 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2505 if hasattr(enum, "doc") and enum.doc and enam in enum.doc.fields:
2506 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2507 f.write('%s\n' % desc)
2509 f.write('TODO: NOT YET DOCUMENTED.\n')
2514 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2515 desc = self.doc.fields[field.field_name]
2516 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2519 f.write('%s\n' % desc)
2521 f.write('TODO: NOT YET DOCUMENTED.\n')
2527 f.write('.SH REPLY FIELDS\n')
2528 # These fields are present in every reply:
2529 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2530 f.write(('The type of this reply, in this case \\fI%s\\fP. This field '
2531 'is also present in the \\fIxcb_generic_reply_t\\fP and can '
2532 'be used to tell replies apart from each other.\n') %
2533 _n(self.reply.name).upper())
2534 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2535 f.write('The sequence number of the last request processed by the X11 server.\n')
2536 f.write('.IP \\fI%s\\fP 1i\n' % 'length')
2537 f.write('The length of the reply, in words (a word is 4 bytes).\n')
2538 for field in self.reply.fields:
2539 if (field.c_field_name in frozenset(['response_type', 'sequence', 'length']) or
2540 field.c_field_name.startswith('pad')):
2543 if field.type.is_list and not field.type.fixed_size():
2545 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2547 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2548 printed_enum = False
2549 if hasattr(field, "enum") and field.enum:
2550 # XXX: why the 'xcb' prefix?
2551 key = ('xcb', field.enum)
2553 f.write('One of the following values:\n')
2556 count = len(enum.values)
2557 for (enam, eval) in enum.values:
2559 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2560 if enum.doc and enam in enum.doc.fields:
2561 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2562 f.write('%s\n' % desc)
2564 f.write('TODO: NOT YET DOCUMENTED.\n')
2569 if hasattr(self.reply, "doc") and self.reply.doc and field.field_name in self.reply.doc.fields:
2570 desc = self.reply.doc.fields[field.field_name]
2571 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2574 f.write('%s\n' % desc)
2576 f.write('TODO: NOT YET DOCUMENTED.\n')
2583 f.write('.SH DESCRIPTION\n')
2584 if hasattr(self, "doc") and self.doc and self.doc.description:
2585 desc = self.doc.description
2586 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2587 lines = desc.split('\n')
2588 f.write('\n'.join(lines) + '\n')
2590 f.write('.SH RETURN VALUE\n')
2592 f.write(('Returns an \\fIxcb_void_cookie_t\\fP. Errors (if any) '
2593 'have to be handled in the event loop.\n\nIf you want to '
2594 'handle errors directly with \\fIxcb_request_check\\fP '
2595 'instead, use \\fI%s_checked\\fP. See '
2596 '\\fBxcb-requests(%s)\\fP for details.\n') % (base_func_name, section))
2598 f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
2599 'calling the reply function \\fI%s\\fP.\n\nIf you want to '
2600 'handle errors in the event loop instead, use '
2601 '\\fI%s_unchecked\\fP. See \\fBxcb-requests(%s)\\fP for '
2603 (cookie_type, self.c_reply_name, base_func_name, section))
2604 f.write('.SH ERRORS\n')
2605 if hasattr(self, "doc") and self.doc:
2606 for errtype, errtext in sorted(self.doc.errors.items()):
2607 f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
2608 errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
2609 f.write('%s\n' % (errtext))
2610 if not hasattr(self, "doc") or not self.doc or len(self.doc.errors) == 0:
2611 f.write('This request does never generate any errors.\n')
2612 if hasattr(self, "doc") and self.doc and self.doc.example:
2613 f.write('.SH EXAMPLE\n')
2616 lines = self.doc.example.split('\n')
2617 f.write('\n'.join(lines) + '\n')
2619 f.write('.SH SEE ALSO\n')
2620 if hasattr(self, "doc") and self.doc:
2621 see = ['.BR %s (%s)' % ('xcb-requests', section)]
2622 if self.doc.example:
2623 see.append('.BR %s (%s)' % ('xcb-examples', section))
2624 for seename, seetype in sorted(self.doc.see.items()):
2625 if seetype == 'program':
2626 see.append('.BR %s (1)' % seename)
2627 elif seetype == 'event':
2628 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2629 elif seetype == 'request':
2630 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2631 elif seetype == 'function':
2632 see.append('.BR %s (%s)' % (seename, section))
2634 see.append('TODO: %s (type %s)' % (seename, seetype))
2635 f.write(',\n'.join(see) + '\n')
2636 f.write('.SH AUTHOR\n')
2637 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2640 def _man_event(self, name):
2642 sys.stdout.write('man/%s.%s ' % (self.c_type, section))
2643 # Our CWD is src/, so this will end up in src/man/
2644 f = open('man/%s.%s' % (self.c_type, section), 'w')
2645 f.write('.TH %s %s "%s" "%s" "XCB Events"\n' % (self.c_type, section, center_footer, left_footer))
2646 # Left-adjust instead of adjusting to both sides
2648 f.write('.SH NAME\n')
2649 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2650 f.write('%s \\- %s\n' % (self.c_type, brief))
2651 f.write('.SH SYNOPSIS\n')
2652 # Don't split words (hyphenate)
2654 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2657 f.write('.SS Event datastructure\n')
2660 f.write('typedef %s %s {\n' % (self.c_container, self.c_type))
2664 for field in self.fields:
2665 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2668 struct_fields.append(field)
2670 for field in struct_fields:
2671 length = len(field.c_field_type)
2672 # account for '*' pointer_spec
2673 if not field.type.fixed_size():
2675 maxtypelen = max(maxtypelen, length)
2677 def _c_complex_field(self, field, space=''):
2678 if (field.type.fixed_size() or
2679 # in case of switch with switch children, don't make the field a pointer
2680 # necessary for unserialize to work
2681 (self.is_switch and field.type.is_switch)):
2682 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2683 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2685 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2687 if not self.is_switch:
2688 for field in struct_fields:
2689 _c_complex_field(self, field)
2691 for b in self.bitcases:
2695 for field in b.type.fields:
2696 _c_complex_field(self, field, space)
2698 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2701 f.write('} \\fB%s\\fP;\n' % self.c_type)
2706 # Re-enable hyphenation and adjusting to both sides
2709 # argument reference
2710 f.write('.SH EVENT FIELDS\n')
2711 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2712 f.write(('The type of this event, in this case \\fI%s\\fP. This field is '
2713 'also present in the \\fIxcb_generic_event_t\\fP and can be used '
2714 'to tell events apart from each other.\n') % _n(name).upper())
2715 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2716 f.write('The sequence number of the last request processed by the X11 server.\n')
2718 if not self.is_switch:
2719 for field in struct_fields:
2720 # Skip the fields which every event has, we already documented
2722 if field.c_field_name in ('response_type', 'sequence'):
2724 if isinstance(field.type, PadType):
2726 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2727 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2728 desc = self.doc.fields[field.field_name]
2729 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2730 f.write('%s\n' % desc)
2732 f.write('NOT YET DOCUMENTED.\n')
2735 f.write('.SH DESCRIPTION\n')
2736 if hasattr(self, "doc") and self.doc and self.doc.description:
2737 desc = self.doc.description
2738 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2739 lines = desc.split('\n')
2740 f.write('\n'.join(lines) + '\n')
2742 if hasattr(self, "doc") and self.doc and self.doc.example:
2743 f.write('.SH EXAMPLE\n')
2746 lines = self.doc.example.split('\n')
2747 f.write('\n'.join(lines) + '\n')
2749 f.write('.SH SEE ALSO\n')
2750 if hasattr(self, "doc") and self.doc:
2751 see = ['.BR %s (%s)' % ('xcb_generic_event_t', section)]
2752 if self.doc.example:
2753 see.append('.BR %s (%s)' % ('xcb-examples', section))
2754 for seename, seetype in sorted(self.doc.see.items()):
2755 if seetype == 'program':
2756 see.append('.BR %s (1)' % seename)
2757 elif seetype == 'event':
2758 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2759 elif seetype == 'request':
2760 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2761 elif seetype == 'function':
2762 see.append('.BR %s (%s)' % (seename, section))
2764 see.append('TODO: %s (type %s)' % (seename, seetype))
2765 f.write(',\n'.join(see) + '\n')
2766 f.write('.SH AUTHOR\n')
2767 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2771 def c_request(self, name):
2773 Exported function that handles request declarations.
2775 _c_type_setup(self, name, ('request',))
2778 # Cookie type declaration
2779 _c_cookie(self, name)
2782 _c_opcode(name, self.opcode)
2784 # Request structure declaration
2788 _c_type_setup(self.reply, name, ('reply',))
2789 # Reply structure definition
2790 _c_complex(self.reply)
2791 # Request prototypes
2792 has_fds = _c_reply_has_fds(self.reply)
2793 _c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds)
2794 _c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds)
2796 _c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds)
2797 _c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds)
2799 _c_accessors(self.reply, name + ('reply',), name)
2800 _c_reply(self, name)
2802 _c_reply_fds(self, name)
2804 # Request prototypes
2805 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2806 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2808 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2809 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2811 # We generate the manpage afterwards because _c_type_setup has been called.
2812 # TODO: what about aux helpers?
2813 cookie_type = self.c_cookie_type if self.reply else 'xcb_void_cookie_t'
2814 _man_request(self, name, cookie_type, not self.reply, False)
2816 def c_event(self, name):
2818 Exported function that handles event declarations.
2821 # The generic event structure xcb_ge_event_t has the full_sequence field
2822 # at the 32byte boundary. That's why we've to inject this field into GE
2823 # events while generating the structure for them. Otherwise we would read
2824 # garbage (the internal full_sequence) when accessing normal event fields
2826 force_packed = False
2827 if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
2829 for field in self.fields:
2830 if field.type.size != None and field.type.nmemb != None:
2831 event_size += field.type.size * field.type.nmemb
2832 if event_size == 32:
2833 full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
2834 idx = self.fields.index(field)
2835 self.fields.insert(idx + 1, full_sequence)
2837 # If the event contains any 64-bit extended fields, they need
2838 # to remain aligned on a 64-bit boundary. Adding full_sequence
2839 # would normally break that; force the struct to be packed.
2840 force_packed = any(f.type.size == 8 and f.type.is_simple for f in self.fields[(idx+1):])
2843 _c_type_setup(self, name, ('event',))
2846 _c_opcode(name, self.opcodes[name])
2848 if self.name == name:
2849 # Structure definition
2850 _c_complex(self, force_packed)
2854 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2856 _man_event(self, name)
2858 def c_error(self, name):
2860 Exported function that handles error declarations.
2862 _c_type_setup(self, name, ('error',))
2865 _c_opcode(name, self.opcodes[name])
2867 if self.name == name:
2868 # Structure definition
2873 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2876 # Main routine starts here
2878 # Must create an "output" dictionary before any xcbgen imports.
2879 output = {'open' : c_open,
2881 'simple' : c_simple,
2883 'struct' : c_struct,
2885 'request' : c_request,
2890 # Boilerplate below this point
2892 # Check for the argument that specifies path to the xcbgen python package.
2894 opts, args = getopt.getopt(sys.argv[1:], 'c:l:s:p:m')
2895 except getopt.GetoptError as err:
2897 print('Usage: c_client.py -c center_footer -l left_footer -s section [-p path] file.xml')
2900 for (opt, arg) in opts:
2908 sys.path.insert(1, arg)
2911 sys.stdout.write('man_MANS = ')
2913 # Import the module class
2915 from xcbgen.state import Module
2916 from xcbgen.xtypes import *
2919 Failed to load the xcbgen Python package!
2920 Make sure that xcb/proto installed it on your Python path.
2921 If not, you will need to create a .pth file or define $PYTHONPATH
2923 Refer to the README file in xcb/proto for more info.
2927 # Ensure the man subdirectory exists
2930 except OSError as e:
2931 if e.errno != errno.EEXIST:
2934 # Parse the xml header
2935 module = Module(args[0], output)
2937 # Build type-registry and resolve type dependencies