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.need_aux = False
309 self.need_serialize = False
310 self.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.var_followed_by_fixed_fields = False
324 self.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.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
361 elif not field.type.fixed_size() and not field.type.is_bitcase:
362 self.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.need_serialize = True
383 self.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.var_followed_by_fixed_fields:
390 if field.type.fixed_size():
391 field.prev_varsized_field = None
393 if self.need_serialize:
394 # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
395 self.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_bitcase:
411 if self.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.var_followed_by_fixed_fields:
420 _c_serialize('unserialize', self)
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_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_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_bitcase) else '->'
497 # exception: 'toplevel' object (switch as well!) always have sep '->'
498 sep = '->' if idx<1 else sep
499 if not obj.is_bitcase or (obj.is_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)
692 for n, expr in enumerate(b.type.expr):
693 bitcase_expr = _c_accessor_get_expr(expr, None)
694 # only one <enumref> in the <bitcase>
696 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
697 # multiple <enumref> in the <bitcase>
699 code_lines.append(' if((%s & %s) ||' % (switch_expr, bitcase_expr))
700 elif len_expr == (n + 1): # last
701 code_lines.append(' (%s & %s)) {' % (switch_expr, bitcase_expr))
702 else: # between first and last
703 code_lines.append(' (%s & %s) ||' % (switch_expr, bitcase_expr))
707 b_prefix = prefix + [(b.c_field_name, '.', b.type)]
709 count += _c_serialize_helper_fields(context, b.type,
710 code_lines, temp_vars,
714 code_lines.append(' }')
716 # if 'serialize' == context:
717 # count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
718 # elif context in ('unserialize', 'unpack', 'sizeof'):
720 # code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
721 # code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
724 # _c_serialize_helper_switch
726 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
728 handle switch by calling _serialize() or _unpack(), depending on context
730 # switch is handled by this function as a special case
731 param_fields, wire_fields, params = get_serialize_params(context, self)
732 field_mapping = _c_helper_field_mapping(self, prefix)
733 prefix_str = _c_helper_absolute_name(prefix)
735 # find the parameters that need to be passed to _serialize()/_unpack():
736 # all switch expr fields must be given as parameters
737 args = get_expr_fields(field.type)
738 # length fields for variable size types in switch, normally only some of need
739 # need to be passed as parameters
740 switch_len_fields = resolve_expr_fields(field.type)
742 # a switch field at this point _must_ be a bitcase field
743 # we require that bitcases are "self-contiguous"
744 bitcase_unresolved = resolve_expr_fields(self)
745 if len(bitcase_unresolved) != 0:
746 raise Exception('unresolved fields within bitcase is not supported at this point')
748 # get the C names for the parameters
750 for a in switch_len_fields:
751 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
753 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
755 # call _serialize()/_unpack() to determine the actual size
756 if 'serialize' == context:
757 length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
758 c_field_names, prefix_str, field.c_field_name)
759 elif context in ('unserialize', 'unpack'):
760 length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
761 c_field_names, prefix_str, field.c_field_name)
764 # _c_serialize_helper_switch_field()
766 def _c_serialize_helper_list_field(context, self, field,
767 code_lines, temp_vars,
770 helper function to cope with lists of variable length
772 expr = field.type.expr
773 prefix_str = _c_helper_absolute_name(prefix)
774 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
775 param_names = [p[2] for p in params]
777 expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
778 resolved = list(filter(lambda x: x in param_names, expr_fields_names))
779 unresolved = list(filter(lambda x: x not in param_names, expr_fields_names))
783 field_mapping[r] = (r, None)
785 if len(unresolved)>0:
787 if len(tmp_prefix)==0:
788 raise Exception("found an empty prefix while resolving expr field names for list %s",
791 field_mapping.update(_c_helper_resolve_field_names(prefix))
792 resolved += list(filter(lambda x: x in field_mapping, unresolved))
793 unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
794 if len(unresolved)>0:
795 raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
797 list_length = _c_accessor_get_expr(expr, field_mapping)
799 # default: list with fixed size elements
800 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
802 # list with variable-sized elements
803 if not field.type.member.fixed_size():
805 if context in ('unserialize', 'sizeof', 'unpack'):
806 int_i = ' unsigned int i;'
807 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
808 if int_i not in temp_vars:
809 temp_vars.append(int_i)
810 if xcb_tmp_len not in temp_vars:
811 temp_vars.append(xcb_tmp_len)
812 # loop over all list elements and call sizeof repeatedly
813 # this should be a bit faster than using the iterators
814 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
815 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
816 (space, field.type.c_sizeof_name))
817 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
818 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
819 code_lines.append("%s }" % space)
821 elif 'serialize' == context:
822 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
823 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
824 code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length))
825 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
826 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
827 code_lines.append('%s }' % space)
828 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
831 # _c_serialize_helper_list_field()
833 def _c_serialize_helper_fields_fixed_size(context, self, field,
834 code_lines, temp_vars,
836 # keep the C code a bit more readable by giving the field name
837 if not self.is_bitcase:
838 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
840 scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
841 typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
842 code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
844 abs_field_name = _c_helper_absolute_name(prefix, field)
845 # default for simple cases: call sizeof()
846 length = "sizeof(%s)" % field.c_field_type
848 if context in ('unserialize', 'unpack', 'sizeof'):
849 # default: simple cast
850 value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
852 # padding - we could probably just ignore it
853 if field.type.is_pad and field.type.nmemb > 1:
855 for i in range(field.type.nmemb):
856 code_lines.append('%s %s[%d] = *(%s *)xcb_tmp;' %
857 (space, abs_field_name, i, field.c_field_type))
858 # total padding = sizeof(pad0) * nmemb
859 length += " * %d" % field.type.nmemb
861 if field.type.is_list:
862 # no such case in the protocol, cannot be tested and therefore ignored for now
863 raise Exception('list with fixed number of elemens unhandled in _unserialize()')
865 elif 'serialize' == context:
866 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
868 if field.type.is_expr:
869 # need to register a temporary variable for the expression in case we know its type
870 if field.type.c_type is None:
871 raise Exception("type for field '%s' (expression '%s') unkown" %
872 (field.field_name, _c_accessor_get_expr(field.type.expr)))
874 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
875 _c_accessor_get_expr(field.type.expr, prefix)))
876 value += "&xcb_expr_%s;" % _cpp(field.field_name)
878 elif field.type.is_pad:
879 if field.type.nmemb == 1:
882 # we could also set it to 0, see definition of xcb_send_request()
883 value = ' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
884 length += "*%d" % field.type.nmemb
887 # non-list type with fixed size
888 if field.type.nmemb == 1:
889 value += "&%s;" % (abs_field_name)
891 # list with nmemb (fixed size) elements
893 value += '%s;' % (abs_field_name)
894 length = '%d' % field.type.nmemb
896 return (value, length)
897 # _c_serialize_helper_fields_fixed_size()
899 def _c_serialize_helper_fields_variable_size(context, self, field,
900 code_lines, temp_vars,
902 prefix_str = _c_helper_absolute_name(prefix)
904 if context in ('unserialize', 'unpack', 'sizeof'):
906 var_field_name = 'xcb_tmp'
908 # special case: intermixed fixed and variable size fields
909 if self.var_followed_by_fixed_fields and 'unserialize' == context:
910 value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
911 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
912 # special case: switch
913 if 'unpack' == context:
914 value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
916 elif 'serialize' == context:
917 # variable size fields appear as parameters to _serialize() if the
918 # 'toplevel' container is not a switch
919 prefix_string = prefix_str if prefix[0][2].is_switch else ''
920 var_field_name = "%s%s" % (prefix_string, field.c_field_name)
921 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
925 code_lines.append('%s /* %s */' % (space, field.c_field_name))
927 if field.type.is_list:
929 # in any context, list is already a pointer, so the default assignment is ok
930 code_lines.append("%s%s" % (space, value))
932 length = _c_serialize_helper_list_field(context, self, field,
933 code_lines, temp_vars,
936 elif field.type.is_switch:
938 if context == 'serialize':
939 # the _serialize() function allocates the correct amount memory if given a NULL pointer
940 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
941 length = _c_serialize_helper_switch_field(context, self, field,
942 'xcb_parts[xcb_parts_idx].iov_base',
946 # in all remaining special cases - call _sizeof()
947 length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
949 return (value, length)
950 # _c_serialize_helper_fields_variable_size
952 def _c_serialize_helper_fields(context, self,
953 code_lines, temp_vars,
954 space, prefix, is_bitcase):
957 prev_field_was_variable = False
959 for field in self.fields:
960 if not field.visible:
961 if not ((field.wire and not field.auto) or 'unserialize' == context):
964 # switch/bitcase: fixed size fields must be considered explicitly
965 if field.type.fixed_size():
966 if self.is_bitcase or self.var_followed_by_fixed_fields:
967 if prev_field_was_variable and need_padding:
969 # count += _c_serialize_helper_insert_padding(context, code_lines, space,
970 # self.var_followed_by_fixed_fields)
971 prev_field_was_variable = False
973 # prefix for fixed size fields
974 fixed_prefix = prefix
976 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
977 code_lines, temp_vars,
982 # fields with variable size
984 if field.type.is_pad:
985 # Variable length pad is <pad align= />
986 code_lines.append('%s xcb_align_to = %d;' % (space, field.type.align))
987 count += _c_serialize_helper_insert_padding(context, code_lines, space,
988 self.var_followed_by_fixed_fields)
991 # switch/bitcase: always calculate padding before and after variable sized fields
992 if need_padding or is_bitcase:
993 count += _c_serialize_helper_insert_padding(context, code_lines, space,
994 self.var_followed_by_fixed_fields)
996 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
997 code_lines, temp_vars,
999 prev_field_was_variable = True
1001 # save (un)serialization C code
1003 code_lines.append('%s%s' % (space, value))
1005 if field.type.fixed_size():
1006 if is_bitcase or self.var_followed_by_fixed_fields:
1007 # keep track of (un)serialized object's size
1008 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1009 if context in ('unserialize', 'unpack', 'sizeof'):
1010 code_lines.append('%s xcb_tmp += %s;' % (space, length))
1012 # variable size objects or bitcase:
1013 # value & length might have been inserted earlier for special cases
1015 # special case: intermixed fixed and variable size fields
1016 if (not field.type.fixed_size() and
1017 self.var_followed_by_fixed_fields and 'unserialize' == context):
1018 temp_vars.append(' int %s_len;' % field.c_field_name)
1019 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
1020 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
1021 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
1023 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1024 # increase pointer into the byte stream accordingly
1025 if context in ('unserialize', 'sizeof', 'unpack'):
1026 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1028 if 'serialize' == context:
1030 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
1031 code_lines.append('%s xcb_parts_idx++;' % space)
1034 code_lines.append('%s xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type))
1037 if self.var_followed_by_fixed_fields:
1038 need_padding = False
1041 # _c_serialize_helper_fields()
1043 def _c_serialize_helper(context, complex_type,
1044 code_lines, temp_vars,
1045 space='', prefix=[]):
1046 # count tracks the number of fields to serialize
1049 if hasattr(complex_type, 'type'):
1050 self = complex_type.type
1051 complex_name = complex_type.name
1054 if self.var_followed_by_fixed_fields and 'unserialize' == context:
1055 complex_name = 'xcb_out'
1057 complex_name = '_aux'
1059 # special case: switch is serialized by evaluating each bitcase separately
1061 count += _c_serialize_helper_switch(context, self, complex_name,
1062 code_lines, temp_vars,
1065 # all other data types can be evaluated one field a time
1067 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1068 if context in ('unserialize', 'unpack', 'sizeof') and not self.var_followed_by_fixed_fields:
1069 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1070 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1071 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
1072 code_lines.append('%s xcb_block_len = 0;' % space)
1074 count += _c_serialize_helper_fields(context, self,
1075 code_lines, temp_vars,
1076 space, prefix, False)
1078 count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
1081 # _c_serialize_helper()
1083 def _c_serialize(context, self):
1085 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1086 for the ComplexType variable self
1092 # _serialize() returns the buffer size
1095 if self.is_switch and 'unserialize' == context:
1098 cases = { 'serialize' : self.c_serialize_name,
1099 'unserialize' : self.c_unserialize_name,
1100 'unpack' : self.c_unpack_name,
1101 'sizeof' : self.c_sizeof_name }
1102 func_name = cases[context]
1104 param_fields, wire_fields, params = get_serialize_params(context, self)
1105 variable_size_fields = 0
1106 # maximum space required for type definition of function arguments
1109 # determine N(variable_fields)
1110 for field in param_fields:
1111 # if self.is_switch, treat all fields as if they are variable sized
1112 if not field.type.fixed_size() or self.is_switch:
1113 variable_size_fields += 1
1114 # determine maxtypelen
1116 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1119 indent = ' '*(len(func_name)+2)
1122 typespec, pointerspec, field_name = p
1123 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1124 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1125 # insert function name
1126 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1127 param_str = list(map(lambda x: "%s," % x, param_str))
1128 for s in param_str[:-1]:
1130 _h("%s);" % param_str[-1].rstrip(','))
1131 _c("%s)" % param_str[-1].rstrip(','))
1138 if 'serialize' == context:
1139 if not self.is_switch and not self.var_followed_by_fixed_fields:
1140 _c(' %s *xcb_out = *_buffer;', self.c_type)
1141 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1142 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1143 _c(' unsigned int xcb_align_to = 0;')
1145 _c(' char *xcb_out = *_buffer;')
1146 _c(' unsigned int xcb_buffer_len = 0;')
1147 _c(' unsigned int xcb_align_to = 0;')
1148 prefix = [('_aux', '->', self)]
1151 elif context in ('unserialize', 'unpack'):
1152 _c(' char *xcb_tmp = (char *)_buffer;')
1153 if not self.is_switch:
1154 if not self.var_followed_by_fixed_fields:
1155 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1156 prefix = [('_aux', '->', self)]
1158 _c(' %s xcb_out;', self.c_type)
1159 prefix = [('xcb_out', '.', self)]
1161 aux_var = '_aux' # default for unpack: single pointer
1162 # note: unserialize not generated for switch
1163 if 'unserialize' == context:
1164 aux_var = '(*_aux)' # unserialize: double pointer (!)
1165 prefix = [(aux_var, '->', self)]
1167 _c(' unsigned int xcb_buffer_len = 0;')
1168 _c(' unsigned int xcb_block_len = 0;')
1169 _c(' unsigned int xcb_pad = 0;')
1170 _c(' unsigned int xcb_align_to = 0;')
1172 elif 'sizeof' == context:
1173 param_names = [p[2] for p in params]
1175 # switch: call _unpack()
1176 _c(' %s _aux;', self.c_type)
1177 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1180 elif self.var_followed_by_fixed_fields:
1181 # special case: call _unserialize()
1182 _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1186 _c(' char *xcb_tmp = (char *)_buffer;')
1187 prefix = [('_aux', '->', self)]
1189 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1190 # update variable size fields (only important for context=='serialize'
1191 variable_size_fields = count
1192 if 'serialize' == context:
1193 temp_vars.append(' unsigned int xcb_pad = 0;')
1194 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1195 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1196 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1197 temp_vars.append(' unsigned int xcb_block_len = 0;')
1198 temp_vars.append(' unsigned int i;')
1199 temp_vars.append(' char *xcb_tmp;')
1200 elif 'sizeof' == context:
1201 # neither switch nor intermixed fixed and variable size fields:
1202 # evaluate parameters directly
1203 if not (self.is_switch or self.var_followed_by_fixed_fields):
1205 # look if we have to declare an '_aux' variable at all
1206 if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
1207 if not self.var_followed_by_fixed_fields:
1208 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1210 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1212 _c(' unsigned int xcb_buffer_len = 0;')
1213 _c(' unsigned int xcb_block_len = 0;')
1214 _c(' unsigned int xcb_pad = 0;')
1215 _c(' unsigned int xcb_align_to = 0;')
1221 for l in code_lines:
1224 # variable sized fields have been collected, now
1225 # allocate memory and copy everything into a continuous memory area
1226 # note: this is not necessary in case of unpack
1227 if context in ('serialize', 'unserialize'):
1228 # unserialize: check for sizeof-only invocation
1229 if 'unserialize' == context:
1231 _c(' if (NULL == _aux)')
1232 _c(' return xcb_buffer_len;')
1235 _c(' if (NULL == %s) {', aux_ptr)
1236 _c(' /* allocate memory */')
1237 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1238 if 'serialize' == context:
1239 _c(' *_buffer = xcb_out;')
1243 # serialize: handle variable size fields in a loop
1244 if 'serialize' == context:
1245 if not self.is_switch and not self.var_followed_by_fixed_fields:
1246 if len(wire_fields)>0:
1247 _c(' *xcb_out = *_aux;')
1248 # copy variable size fields into the buffer
1249 if variable_size_fields > 0:
1251 if not self.is_switch and not self.var_followed_by_fixed_fields:
1252 _c(' xcb_tmp = (char*)++xcb_out;')
1253 _c(' xcb_tmp += xcb_out_pad;')
1255 _c(' xcb_tmp = xcb_out;')
1257 # variable sized fields
1258 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1259 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1260 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1261 _c(' if (0 != xcb_parts[i].iov_len)')
1262 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1265 # unserialize: assign variable size fields individually
1266 if 'unserialize' == context:
1267 _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1268 param_fields.reverse()
1269 for field in param_fields:
1270 if not field.type.fixed_size():
1271 _c(' xcb_tmp -= %s_len;', field.c_field_name)
1272 _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1273 _c(' *%s = xcb_out;', aux_ptr)
1276 _c(' return xcb_buffer_len;')
1280 def _c_iterator_get_end(field, accum):
1282 Figures out what C code is needed to find the end of a variable-length structure field.
1283 For nested structures, recurses into its last variable-sized field.
1284 For lists, calls the end function
1286 if field.type.is_container:
1287 accum = field.c_accessor_name + '(' + accum + ')'
1288 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1289 if field.type.is_list:
1290 # XXX we can always use the first way
1291 if field.type.member.is_simple:
1292 return field.c_end_name + '(' + accum + ')'
1294 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1296 def _c_iterator(self, name):
1298 Declares the iterator structure and next/end functions for a given type.
1303 _h(' * @brief %s', self.c_iterator_type)
1305 _h('typedef struct %s {', self.c_iterator_type)
1306 _h(' %s *data; /**< */', self.c_type)
1307 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1308 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1309 _h('} %s;', self.c_iterator_type)
1315 _h(' * Get the next element of the iterator')
1316 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1318 _h(' * Get the next element in the iterator. The member rem is')
1319 _h(' * decreased by one. The member data points to the next')
1320 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1324 _hc('/*****************************************************************************')
1326 _hc(' ** void %s', self.c_next_name)
1328 _hc(' ** @param %s *i', self.c_iterator_type)
1329 _hc(' ** @returns void')
1331 _hc(' *****************************************************************************/')
1334 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1335 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1338 if not self.fixed_size():
1339 _c(' %s *R = i->data;', self.c_type)
1342 # FIXME - how to determine the size of a variable size union??
1343 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1345 if self.need_sizeof:
1346 _c(' xcb_generic_iterator_t child;')
1347 _c(' child.data = (%s *)(((char *)R) + %s(R));',
1348 self.c_type, self.c_sizeof_name)
1349 _c(' i->index = (char *) child.data - (char *) i->data;')
1351 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1352 _c(' i->index = child.index;')
1354 _c(' i->data = (%s *) child.data;', self.c_type)
1359 _c(' i->index += sizeof(%s);', self.c_type)
1365 _h(' * Return the iterator pointing to the last element')
1366 _h(' * @param i An %s', self.c_iterator_type)
1367 _h(' * @return The iterator pointing to the last element')
1369 _h(' * Set the current element in the iterator to the last element.')
1370 _h(' * The member rem is set to 0. The member data points to the')
1371 _h(' * last element.')
1375 _hc('/*****************************************************************************')
1377 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1379 _hc(' ** @param %s i', self.c_iterator_type)
1380 _hc(' ** @returns xcb_generic_iterator_t')
1382 _hc(' *****************************************************************************/')
1384 _hc('xcb_generic_iterator_t')
1385 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1386 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1388 _c(' xcb_generic_iterator_t ret;')
1390 if self.fixed_size():
1391 _c(' ret.data = i.data + i.rem;')
1392 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1395 _c(' while(i.rem > 0)')
1396 _c(' %s(&i);', self.c_next_name)
1397 _c(' ret.data = i.data;')
1398 _c(' ret.rem = i.rem;')
1399 _c(' ret.index = i.index;')
1404 def _c_accessor_get_length(expr, field_mapping=None):
1406 Figures out what C code is needed to get a length field.
1407 The field_mapping parameter can be used to change the absolute name of a length field.
1408 For fields that follow a variable-length field, use the accessor.
1409 Otherwise, just reference the structure field directly.
1412 lenfield_name = expr.lenfield_name
1413 if lenfield_name is not None:
1414 if field_mapping is not None:
1415 lenfield_name = field_mapping[lenfield_name][0]
1417 if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1418 # special case: variable and fixed size fields are intermixed
1419 # if the lenfield is among the fixed size fields, there is no need
1420 # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1421 return field_mapping(expr.lenfield_name)
1422 elif expr.lenfield_name is not None:
1423 return lenfield_name
1425 return str(expr.nmemb)
1427 def _c_accessor_get_expr(expr, field_mapping):
1429 Figures out what C code is needed to get the length of a list field.
1430 The field_mapping parameter can be used to change the absolute name of a length field.
1431 Recurses for math operations.
1432 Returns bitcount for value-mask fields.
1433 Otherwise, uses the value of the length field.
1435 lenexp = _c_accessor_get_length(expr, field_mapping)
1438 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1439 elif expr.op == 'popcount':
1440 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1441 elif expr.op == 'enumref':
1442 enum_name = expr.lenfield_type.name
1443 constant_name = expr.lenfield_name
1444 c_name = _n(enum_name + (constant_name,)).upper()
1446 elif expr.op == 'sumof':
1447 # locate the referenced list object
1448 list_obj = expr.lenfield_type
1450 for f in expr.lenfield_parent.fields:
1451 if f.field_name == expr.lenfield_name:
1456 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1457 list_name = field_mapping[field.c_field_name][0]
1458 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1459 # note: xcb_sumof() has only been defined for integers
1460 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1461 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1462 elif expr.op != None:
1463 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1464 ' ' + expr.op + ' ' +
1465 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1467 return 'xcb_popcount(' + lenexp + ')'
1471 def type_pad_type(type):
1476 def _c_accessors_field(self, field):
1478 Declares the accessor functions for a non-list field that follows a variable-length field.
1480 c_type = self.c_type
1482 # special case: switch
1483 switch_obj = self if self.is_switch else None
1485 switch_obj = self.parents[-1]
1486 if switch_obj is not None:
1487 c_type = switch_obj.c_type
1489 if field.type.is_simple:
1492 _hc('/*****************************************************************************')
1494 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1496 _hc(' ** @param const %s *R', c_type)
1497 _hc(' ** @returns %s', field.c_field_type)
1499 _hc(' *****************************************************************************/')
1501 _hc('%s', field.c_field_type)
1502 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1503 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1505 if field.prev_varsized_field is None:
1506 _c(' return (%s *) (R + 1);', field.c_field_type)
1508 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1509 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1510 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1515 _hc('/*****************************************************************************')
1517 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1519 _hc(' ** @param const %s *R', c_type)
1520 _hc(' ** @returns %s *', field.c_field_type)
1522 _hc(' *****************************************************************************/')
1524 if field.type.is_switch and switch_obj is None:
1525 return_type = 'void *'
1527 return_type = '%s *' % field.c_field_type
1530 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1531 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1533 if field.prev_varsized_field is None:
1534 _c(' return (%s) (R + 1);', return_type)
1535 # note: the special case 'variable fields followed by fixed size fields'
1536 # is not of any consequence here, since the ordering gets
1537 # 'corrected' in the reply function
1539 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1540 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1541 return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1545 def _c_accessors_list(self, field):
1547 Declares the accessor functions for a list field.
1548 Declares a direct-accessor function only if the list members are fixed size.
1549 Declares length and get-iterator functions always.
1552 def get_align_pad(field):
1553 prev = field.prev_varsized_field
1554 prev_prev = field.prev_varsized_field.prev_varsized_field
1556 if (prev.type.is_pad and prev.type.align > 0 and prev_prev is not None):
1557 return (prev_prev, '((-prev.index) & (%d - 1))' % prev.type.align)
1563 c_type = self.c_type
1565 # special case: switch
1566 # in case of switch, 2 params have to be supplied to certain accessor functions:
1567 # 1. the anchestor object (request or reply)
1568 # 2. the (anchestor) switch object
1569 # the reason is that switch is either a child of a request/reply or nested in another switch,
1570 # so whenever we need to access a length field, we might need to refer to some anchestor type
1571 switch_obj = self if self.is_switch else None
1573 switch_obj = self.parents[-1]
1574 if switch_obj is not None:
1575 c_type = switch_obj.c_type
1579 parents = self.parents if hasattr(self, 'parents') else [self]
1580 # 'R': parents[0] is always the 'toplevel' container type
1581 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1582 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1583 # auxiliary object for 'R' parameters
1586 if switch_obj is not None:
1587 # now look where the fields are defined that are needed to evaluate
1588 # the switch expr, and store the parent objects in accessor_params and
1589 # the fields in switch_fields
1591 # 'S': name for the 'toplevel' switch
1592 toplevel_switch = parents[1]
1593 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1594 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1596 # initialize prefix for everything "below" S
1597 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1598 prefix = [(prefix_str, '->', toplevel_switch)]
1600 # look for fields in the remaining containers
1601 for p in parents[2:] + [self]:
1602 # the separator between parent and child is always '.' here,
1603 # because of nested switch statements
1604 if not p.is_bitcase or (p.is_bitcase and p.has_name):
1605 prefix.append((p.name[-1], '.', p))
1606 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1608 # auxiliary object for 'S' parameter
1613 if list.member.fixed_size():
1614 idx = 1 if switch_obj is not None else 0
1617 _hc('/*****************************************************************************')
1619 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1621 _hc(' ** @param %s', params[idx][0])
1622 _hc(' ** @returns %s *', field.c_field_type)
1624 _hc(' *****************************************************************************/')
1626 _hc('%s *', field.c_field_type)
1628 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1629 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1632 if switch_obj is not None:
1633 _c(' return %s;', fields[field.c_field_name][0])
1634 elif field.prev_varsized_field is None:
1635 _c(' return (%s *) (R + 1);', field.c_field_type)
1637 (prev_varsized_field, align_pad) = get_align_pad(field)
1639 if align_pad is None:
1640 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
1641 type_pad_type(field.first_field_after_varsized.type.c_type))
1643 _c(' xcb_generic_iterator_t prev = %s;',
1644 _c_iterator_get_end(prev_varsized_field, 'R'))
1645 _c(' return (%s *) ((char *) prev.data + %s + %d);',
1646 field.c_field_type, align_pad, field.prev_varsized_offset)
1651 _hc('/*****************************************************************************')
1653 _hc(' ** int %s', field.c_length_name)
1655 _hc(' ** @param const %s *R', c_type)
1656 _hc(' ** @returns int')
1658 _hc(' *****************************************************************************/')
1661 if switch_obj is not None:
1662 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1663 spacing = ' '*(len(field.c_length_name)+2)
1664 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1665 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1666 length = _c_accessor_get_expr(field.type.expr, fields)
1668 _h('%s (const %s *R /**< */);', field.c_length_name, c_type)
1669 _c('%s (const %s *R /**< */)', field.c_length_name, c_type)
1670 length = _c_accessor_get_expr(field.type.expr, fields)
1672 _c(' return %s;', length)
1675 if field.type.member.is_simple:
1678 _hc('/*****************************************************************************')
1680 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1682 _hc(' ** @param const %s *R', c_type)
1683 _hc(' ** @returns xcb_generic_iterator_t')
1685 _hc(' *****************************************************************************/')
1687 _hc('xcb_generic_iterator_t')
1688 if switch_obj is not None:
1689 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1690 spacing = ' '*(len(field.c_end_name)+2)
1691 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1692 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1694 _h('%s (const %s *R /**< */);', field.c_end_name, c_type)
1695 _c('%s (const %s *R /**< */)', field.c_end_name, c_type)
1697 _c(' xcb_generic_iterator_t i;')
1699 param = 'R' if switch_obj is None else 'S'
1700 if switch_obj is not None:
1701 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1702 _c_accessor_get_expr(field.type.expr, fields))
1703 elif field.prev_varsized_field == None:
1704 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1705 _c_accessor_get_expr(field.type.expr, fields))
1707 _c(' xcb_generic_iterator_t child = %s;',
1708 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1709 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1710 _c_accessor_get_expr(field.type.expr, fields))
1713 _c(' i.index = (char *) i.data - (char *) %s;', param)
1720 _hc('/*****************************************************************************')
1722 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1724 _hc(' ** @param const %s *R', c_type)
1725 _hc(' ** @returns %s', field.c_iterator_type)
1727 _hc(' *****************************************************************************/')
1730 _hc('%s', field.c_iterator_type)
1731 if switch_obj is not None:
1732 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1733 spacing = ' '*(len(field.c_iterator_name)+2)
1734 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1735 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1737 _h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
1738 _c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
1740 _c(' %s i;', field.c_iterator_type)
1742 if switch_obj is not None:
1743 _c(' i.data = %s;', fields[field.c_field_name][0])
1744 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1745 elif field.prev_varsized_field == None:
1746 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1748 (prev_varsized_field, align_pad) = get_align_pad(field)
1750 if align_pad is None:
1751 align_pad = ('XCB_TYPE_PAD(%s, prev.index)' %
1752 type_pad_type(field.c_field_type))
1754 _c(' xcb_generic_iterator_t prev = %s;',
1755 _c_iterator_get_end(prev_varsized_field, 'R'))
1756 _c(' i.data = (%s *) ((char *) prev.data + %s);',
1757 field.c_field_type, align_pad)
1759 if switch_obj is None:
1760 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1761 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1765 def _c_accessors(self, name, base):
1767 Declares the accessor functions for the fields of a structure.
1769 # no accessors for switch itself -
1770 # switch always needs to be unpacked explicitly
1771 # if self.is_switch:
1775 for field in self.fields:
1776 if not field.type.is_pad:
1777 if field.type.is_list and not field.type.fixed_size():
1778 _c_accessors_list(self, field)
1779 elif field.prev_varsized_field is not None or not field.type.fixed_size():
1780 _c_accessors_field(self, field)
1782 def c_simple(self, name):
1784 Exported function that handles cardinal type declarations.
1785 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1787 _c_type_setup(self, name, ())
1789 if (self.name != name):
1794 _h('typedef %s %s;', _t(self.name), my_name)
1797 _c_iterator(self, name)
1799 def _c_complex(self, force_packed = False):
1801 Helper function for handling all structure types.
1802 Called for all structs, requests, replies, events, errors.
1807 _h(' * @brief %s', self.c_type)
1809 _h('typedef %s %s {', self.c_container, self.c_type)
1815 for field in self.fields:
1816 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1817 varfield = field.c_field_name
1820 struct_fields.append(field)
1822 for field in struct_fields:
1823 length = len(field.c_field_type)
1824 # account for '*' pointer_spec
1825 if not field.type.fixed_size() and not self.is_union:
1827 maxtypelen = max(maxtypelen, length)
1829 def _c_complex_field(self, field, space=''):
1830 if (field.type.fixed_size() or self.is_union or
1831 # in case of switch with switch children, don't make the field a pointer
1832 # necessary for unserialize to work
1833 (self.is_switch and field.type.is_switch)):
1834 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1835 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1837 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1838 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1840 if not self.is_switch:
1841 for field in struct_fields:
1842 _c_complex_field(self, field)
1844 for b in self.bitcases:
1847 _h(' struct _%s {', b.c_field_name)
1849 for field in b.type.fields:
1850 _c_complex_field(self, field, space)
1852 _h(' } %s;', b.c_field_name)
1854 _h('} %s%s;', 'XCB_PACKED ' if force_packed else '', self.c_type)
1856 def c_struct(self, name):
1858 Exported function that handles structure declarations.
1860 _c_type_setup(self, name, ())
1862 _c_accessors(self, name, name)
1863 _c_iterator(self, name)
1865 def c_union(self, name):
1867 Exported function that handles union declarations.
1869 _c_type_setup(self, name, ())
1871 _c_iterator(self, name)
1873 def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_fds=False):
1875 Declares a request function.
1878 # Four stunningly confusing possibilities here:
1881 # ------------------------------
1883 # 0 flag CHECKED flag Normal Mode
1884 # void_cookie req_cookie
1885 # ------------------------------
1886 # "req_checked" "req_unchecked"
1887 # CHECKED flag 0 flag Abnormal Mode
1888 # void_cookie req_cookie
1889 # ------------------------------
1892 # Whether we are _checked or _unchecked
1893 checked = void and not regular
1894 unchecked = not void and not regular
1896 # What kind of cookie we return
1897 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1899 # What flag is passed to xcb_request
1900 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1903 if func_flags == '0':
1904 func_flags = 'XCB_REQUEST_REPLY_FDS'
1906 func_flags = func_flags + '|XCB_REQUEST_REPLY_FDS'
1908 # Global extension id variable or NULL for xproto
1909 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1911 # What our function name is
1912 func_name = self.c_request_name if not aux else self.c_aux_name
1914 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1916 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1920 maxtypelen = len('xcb_connection_t')
1922 # special case: list with variable size elements
1923 list_with_var_size_elems = False
1925 for field in self.fields:
1927 # The field should appear as a call parameter
1928 param_fields.append(field)
1929 if field.wire and not field.auto:
1930 # We need to set the field up in the structure
1931 wire_fields.append(field)
1932 if field.type.need_serialize or field.type.need_sizeof:
1933 serial_fields.append(field)
1935 for field in param_fields:
1936 c_field_const_type = field.c_field_const_type
1937 if field.type.need_serialize and not aux:
1938 c_field_const_type = "const void"
1939 if len(c_field_const_type) > maxtypelen:
1940 maxtypelen = len(c_field_const_type)
1941 if field.type.is_list and not field.type.member.fixed_size():
1942 list_with_var_size_elems = True
1948 if hasattr(self, "doc") and self.doc:
1950 _h(' * @brief ' + self.doc.brief)
1952 _h(' * No brief doc yet')
1955 _h(' * @param c The connection')
1956 param_names = [f.c_field_name for f in param_fields]
1957 if hasattr(self, "doc") and self.doc:
1958 for field in param_fields:
1959 # XXX: hard-coded until we fix xproto.xml
1960 base_func_name = self.c_request_name if not aux else self.c_aux_name
1961 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
1963 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
1965 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
1968 # XXX: why the 'xcb' prefix?
1969 key = ('xcb', field.enum)
1972 if namecount[tname] > 1:
1973 tname = _t(key + ('enum',))
1974 _h(' * @param %s A bitmask of #%s values.' % (field.c_field_name, tname))
1976 if self.doc and field.field_name in self.doc.fields:
1977 desc = self.doc.fields[field.field_name]
1978 for name in param_names:
1979 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1980 desc = desc.split("\n")
1981 desc = [line if line != '' else '\\n' for line in desc]
1982 _h(' * @param %s %s' % (field.c_field_name, "\n * ".join(desc)))
1983 # If there is no documentation yet, we simply don't generate an
1984 # @param tag. Doxygen will then warn about missing documentation.
1986 _h(' * @return A cookie')
1989 if hasattr(self, "doc") and self.doc:
1990 if self.doc.description:
1991 desc = self.doc.description
1992 for name in param_names:
1993 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1994 desc = desc.split("\n")
1995 _h(' * ' + "\n * ".join(desc))
1997 _h(' * No description yet')
1999 _h(' * Delivers a request to the X server.')
2002 _h(' * This form can be used only if the request will not cause')
2003 _h(' * a reply to be generated. Any returned error will be')
2004 _h(' * saved for handling by xcb_request_check().')
2006 _h(' * This form can be used only if the request will cause')
2007 _h(' * a reply to be generated. Any returned error will be')
2008 _h(' * placed in the event queue.')
2012 _hc('/*****************************************************************************')
2014 _hc(' ** %s %s', cookie_type, func_name)
2017 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
2018 _hc(' ** @param xcb_connection_t%s *c', spacing)
2020 for field in param_fields:
2021 c_field_const_type = field.c_field_const_type
2022 if field.type.need_serialize and not aux:
2023 c_field_const_type = "const void"
2024 spacing = ' ' * (maxtypelen - len(c_field_const_type))
2025 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
2027 _hc(' ** @returns %s', cookie_type)
2029 _hc(' *****************************************************************************/')
2031 _hc('%s', cookie_type)
2033 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
2034 comma = ',' if len(param_fields) else ');'
2035 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
2036 comma = ',' if len(param_fields) else ')'
2037 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
2039 func_spacing = ' ' * (len(func_name) + 2)
2040 count = len(param_fields)
2041 for field in param_fields:
2043 c_field_const_type = field.c_field_const_type
2044 c_pointer = field.c_pointer
2045 if field.type.need_serialize and not aux:
2046 c_field_const_type = "const void"
2048 spacing = ' ' * (maxtypelen - len(c_field_const_type))
2049 comma = ',' if count else ');'
2050 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
2051 spacing, c_pointer, field.c_field_name, comma)
2052 comma = ',' if count else ')'
2053 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
2054 spacing, c_pointer, field.c_field_name, comma)
2057 if not self.var_followed_by_fixed_fields:
2058 for field in param_fields:
2059 if not field.type.fixed_size():
2061 if field.type.need_serialize:
2062 # _serialize() keeps track of padding automatically
2064 dimension = count + 2
2067 _c(' static const xcb_protocol_request_t xcb_req = {')
2068 _c(' /* count */ %d,', count)
2069 _c(' /* ext */ %s,', func_ext_global)
2070 _c(' /* opcode */ %s,', self.c_request_name.upper())
2071 _c(' /* isvoid */ %d', 1 if void else 0)
2075 _c(' struct iovec xcb_parts[%d];', dimension)
2076 _c(' %s xcb_ret;', func_cookie)
2077 _c(' %s xcb_out;', self.c_type)
2078 if self.var_followed_by_fixed_fields:
2079 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
2080 _c(' void *xcb_aux = 0;')
2083 for idx, f in enumerate(serial_fields):
2085 _c(' void *xcb_aux%d = 0;' % (idx))
2086 if list_with_var_size_elems:
2087 _c(' unsigned int i;')
2088 _c(' unsigned int xcb_tmp_len;')
2089 _c(' char *xcb_tmp;')
2091 # simple request call tracing
2092 # _c(' printf("in function %s\\n");' % func_name)
2095 for field in wire_fields:
2096 if field.type.fixed_size():
2097 if field.type.is_expr:
2098 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
2099 elif field.type.is_pad:
2100 if field.type.nmemb == 1:
2101 _c(' xcb_out.%s = 0;', field.c_field_name)
2103 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
2105 if field.type.nmemb == 1:
2106 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
2108 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
2110 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
2111 serialize_args = get_serialize_params(context, type_obj,
2114 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
2116 # calls in order to free dyn. all. memory
2120 if not self.var_followed_by_fixed_fields:
2121 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2122 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
2123 _c(' xcb_parts[3].iov_base = 0;')
2124 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2128 for field in param_fields:
2129 if not field.type.fixed_size():
2130 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
2131 # default: simple cast to char *
2132 if not field.type.need_serialize and not field.type.need_sizeof:
2133 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2134 if field.type.is_list:
2135 if field.type.member.fixed_size():
2136 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
2137 _c_accessor_get_expr(field.type.expr, None),
2138 field.type.member.c_wiretype)
2140 list_length = _c_accessor_get_expr(field.type.expr, None)
2143 _c(" xcb_parts[%d].iov_len = 0;" % count)
2144 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2145 _c(" for(i=0; i<%s; i++) {" % list_length)
2146 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2147 (field.type.c_sizeof_name))
2148 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2149 _c(" xcb_tmp += xcb_tmp_len;")
2152 # not supposed to happen
2153 raise Exception("unhandled variable size field %s" % field.c_field_name)
2156 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2157 idx = serial_fields.index(field)
2158 aux_var = '&xcb_aux%d' % idx
2159 context = 'serialize' if aux else 'sizeof'
2160 _c(' xcb_parts[%d].iov_len = ', count)
2162 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2163 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2164 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2165 free_calls.append(' free(xcb_aux%d);' % idx)
2167 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2168 func_name = field.type.c_sizeof_name
2169 _c(' %s (%s);', func_name, serialize_args)
2172 if not (field.type.need_serialize or field.type.need_sizeof):
2173 # the _serialize() function keeps track of padding automatically
2174 _c(' xcb_parts[%d].iov_base = 0;', count)
2175 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2178 # elif self.var_followed_by_fixed_fields:
2180 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2181 # request header: opcodes + length
2182 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2185 buffer_var = '&xcb_aux'
2186 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2187 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2188 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2189 free_calls.append(' free(xcb_aux);')
2190 # no padding necessary - _serialize() keeps track of padding automatically
2193 for field in param_fields:
2195 _c(' xcb_send_fd(c, %s);', field.c_field_name)
2197 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2199 # free dyn. all. data, if any
2200 for f in free_calls:
2202 _c(' return xcb_ret;')
2205 def _c_reply(self, name):
2207 Declares the function that returns the reply structure.
2209 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2210 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2211 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2213 # check if _unserialize() has to be called for any field
2214 def look_for_special_cases(complex_obj):
2215 unserialize_fields = []
2216 # no unserialize call in case of switch
2217 if not complex_obj.is_switch:
2218 for field in complex_obj.fields:
2219 # three cases: 1. field with special case
2220 # 2. container that contains special case field
2221 # 3. list with special case elements
2222 if field.type.var_followed_by_fixed_fields:
2223 unserialize_fields.append(field)
2224 elif field.type.is_container:
2225 unserialize_fields += look_for_special_cases(field.type)
2226 elif field.type.is_list:
2227 if field.type.member.var_followed_by_fixed_fields:
2228 unserialize_fields.append(field)
2229 if field.type.member.is_container:
2230 unserialize_fields += look_for_special_cases(field.type.member)
2231 return unserialize_fields
2233 unserialize_fields = look_for_special_cases(self.reply)
2237 _h(' * Return the reply')
2238 _h(' * @param c The connection')
2239 _h(' * @param cookie The cookie')
2240 _h(' * @param e The xcb_generic_error_t supplied')
2242 _h(' * Returns the reply of the request asked by')
2244 _h(' * The parameter @p e supplied to this function must be NULL if')
2245 _h(' * %s(). is used.', self.c_unchecked_name)
2246 _h(' * Otherwise, it stores the error if any.')
2248 _h(' * The returned value must be freed by the caller using free().')
2252 _hc('/*****************************************************************************')
2254 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
2256 _hc(' ** @param xcb_connection_t%s *c', spacing1)
2257 _hc(' ** @param %s cookie', self.c_cookie_type)
2258 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
2259 _hc(' ** @returns %s *', self.c_reply_type)
2261 _hc(' *****************************************************************************/')
2263 _hc('%s *', self.c_reply_type)
2264 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2265 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2266 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2267 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2270 if len(unserialize_fields)>0:
2271 # certain variable size fields need to be unserialized explicitly
2272 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2273 self.c_reply_type, self.c_reply_type)
2275 for field in unserialize_fields:
2276 if field.type.is_list:
2277 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2278 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2279 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2281 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2282 # call _unserialize(), using the reply as source and target buffer
2283 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2284 for field in unserialize_fields:
2285 if field.type.is_list:
2286 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2287 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2288 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2289 field.c_field_name, field.c_field_name)
2290 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2292 # return the transformed reply
2293 _c(' return reply;')
2296 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2300 def _c_reply_has_fds(self):
2301 for field in self.fields:
2306 def _c_reply_fds(self, name):
2308 Declares the function that returns fds related to the reply.
2310 spacing1 = ' ' * (len(self.c_reply_type) - len('xcb_connection_t'))
2311 spacing3 = ' ' * (len(self.c_reply_fds_name) + 2)
2314 _h(' * Return the reply fds')
2315 _h(' * @param c The connection')
2316 _h(' * @param reply The reply')
2318 _h(' * Returns the array of reply fds of the request asked by')
2320 _h(' * The returned value must be freed by the caller using free().')
2324 _hc('/*****************************************************************************')
2326 _hc(' ** int * %s', self.c_reply_fds_name)
2328 _hc(' ** @param xcb_connection_t%s *c', spacing1)
2329 _hc(' ** @param %s *reply', self.c_reply_type)
2330 _hc(' ** @returns int *')
2332 _hc(' *****************************************************************************/')
2335 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_fds_name, spacing1)
2336 _h('%s%s *reply /**< */);', spacing3, self.c_reply_type)
2337 _c('%s%s *reply /**< */)', spacing3, self.c_reply_type)
2340 _c(' return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
2345 def _c_opcode(name, opcode):
2347 Declares the opcode define for requests, events, and errors.
2351 _h('/** Opcode for %s. */', _n(name))
2352 _h('#define %s %s', _n(name).upper(), opcode)
2354 def _c_cookie(self, name):
2356 Declares the cookie type for a non-void request.
2361 _h(' * @brief %s', self.c_cookie_type)
2363 _h('typedef struct %s {', self.c_cookie_type)
2364 _h(' unsigned int sequence; /**< */')
2365 _h('} %s;', self.c_cookie_type)
2367 def _man_request(self, name, cookie_type, void, aux):
2368 param_fields = [f for f in self.fields if f.visible]
2370 func_name = self.c_request_name if not aux else self.c_aux_name
2372 def create_link(linkname):
2373 name = 'man/%s.%s' % (linkname, section)
2375 sys.stdout.write(name)
2377 f.write('.so man%s/%s.%s' % (section, func_name, section))
2381 sys.stdout.write('man/%s.%s ' % (func_name, section))
2382 # Our CWD is src/, so this will end up in src/man/
2383 f = open('man/%s.%s' % (func_name, section), 'w')
2384 f.write('.TH %s %s "%s" "%s" "XCB Requests"\n' % (func_name, section, center_footer, left_footer))
2385 # Left-adjust instead of adjusting to both sides
2387 f.write('.SH NAME\n')
2388 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2389 f.write('%s \\- %s\n' % (func_name, brief))
2390 f.write('.SH SYNOPSIS\n')
2391 # Don't split words (hyphenate)
2393 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2395 # function prototypes
2397 count = len(param_fields)
2398 for field in param_fields:
2400 c_field_const_type = field.c_field_const_type
2401 c_pointer = field.c_pointer
2402 if c_pointer == ' ':
2404 if field.type.need_serialize and not aux:
2405 c_field_const_type = "const void"
2407 comma = ', ' if count else ');'
2408 prototype += '%s\\ %s\\fI%s\\fP%s' % (c_field_const_type, c_pointer, field.c_field_name, comma)
2410 f.write('.SS Request function\n')
2412 base_func_name = self.c_request_name if not aux else self.c_aux_name
2413 f.write('%s \\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\n' % (cookie_type, base_func_name, prototype))
2414 create_link('%s_%s' % (base_func_name, ('checked' if void else 'unchecked')))
2417 f.write('.SS Reply datastructure\n')
2420 f.write('typedef %s %s {\n' % (self.reply.c_container, self.reply.c_type))
2424 for field in self.reply.fields:
2425 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2428 struct_fields.append(field)
2430 for field in struct_fields:
2431 length = len(field.c_field_type)
2432 # account for '*' pointer_spec
2433 if not field.type.fixed_size():
2435 maxtypelen = max(maxtypelen, length)
2437 def _c_complex_field(self, field, space=''):
2438 if (field.type.fixed_size() or
2439 # in case of switch with switch children, don't make the field a pointer
2440 # necessary for unserialize to work
2441 (self.is_switch and field.type.is_switch)):
2442 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2443 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2445 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
2446 f.write('ELSE %s = %s\n' % (field.c_field_type, field.c_field_name))
2447 #_h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2449 if not self.is_switch:
2450 for field in struct_fields:
2451 _c_complex_field(self, field)
2453 for b in self.bitcases:
2457 for field in b.type.fields:
2458 _c_complex_field(self, field, space)
2460 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2463 f.write('} \\fB%s\\fP;\n' % self.reply.c_type)
2466 f.write('.SS Reply function\n')
2468 f.write(('%s *\\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\\ '
2469 '\\fIcookie\\fP, xcb_generic_error_t\\ **\\fIe\\fP);\n') %
2470 (self.c_reply_type, self.c_reply_name, self.c_cookie_type))
2471 create_link('%s' % self.c_reply_name)
2473 has_accessors = False
2474 for field in self.reply.fields:
2475 if field.type.is_list and not field.type.fixed_size():
2476 has_accessors = True
2477 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2478 has_accessors = True
2481 f.write('.SS Reply accessors\n')
2483 def _c_accessors_field(self, field):
2485 Declares the accessor functions for a non-list field that follows a variable-length field.
2487 c_type = self.c_type
2489 # special case: switch
2490 switch_obj = self if self.is_switch else None
2492 switch_obj = self.parents[-1]
2493 if switch_obj is not None:
2494 c_type = switch_obj.c_type
2496 if field.type.is_simple:
2497 f.write('%s %s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2498 create_link('%s' % field.c_accessor_name)
2500 f.write('%s *%s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2501 create_link('%s' % field.c_accessor_name)
2503 def _c_accessors_list(self, field):
2505 Declares the accessor functions for a list field.
2506 Declares a direct-accessor function only if the list members are fixed size.
2507 Declares length and get-iterator functions always.
2510 c_type = self.reply.c_type
2512 # special case: switch
2513 # in case of switch, 2 params have to be supplied to certain accessor functions:
2514 # 1. the anchestor object (request or reply)
2515 # 2. the (anchestor) switch object
2516 # the reason is that switch is either a child of a request/reply or nested in another switch,
2517 # so whenever we need to access a length field, we might need to refer to some anchestor type
2518 switch_obj = self if self.is_switch else None
2520 switch_obj = self.parents[-1]
2521 if switch_obj is not None:
2522 c_type = switch_obj.c_type
2526 parents = self.parents if hasattr(self, 'parents') else [self]
2527 # 'R': parents[0] is always the 'toplevel' container type
2528 params.append(('const %s *\\fIreply\\fP' % parents[0].c_type, parents[0]))
2529 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
2530 # auxiliary object for 'R' parameters
2533 if switch_obj is not None:
2534 # now look where the fields are defined that are needed to evaluate
2535 # the switch expr, and store the parent objects in accessor_params and
2536 # the fields in switch_fields
2538 # 'S': name for the 'toplevel' switch
2539 toplevel_switch = parents[1]
2540 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
2541 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
2543 # initialize prefix for everything "below" S
2544 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
2545 prefix = [(prefix_str, '->', toplevel_switch)]
2547 # look for fields in the remaining containers
2548 for p in parents[2:] + [self]:
2549 # the separator between parent and child is always '.' here,
2550 # because of nested switch statements
2551 if not p.is_bitcase or (p.is_bitcase and p.has_name):
2552 prefix.append((p.name[-1], '.', p))
2553 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
2555 # auxiliary object for 'S' parameter
2558 if list.member.fixed_size():
2559 idx = 1 if switch_obj is not None else 0
2561 f.write('%s *\\fB%s\\fP(%s);\n' %
2562 (field.c_field_type, field.c_accessor_name, params[idx][0]))
2563 create_link('%s' % field.c_accessor_name)
2566 f.write('int \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2567 (field.c_length_name, c_type))
2568 create_link('%s' % field.c_length_name)
2570 if field.type.member.is_simple:
2572 f.write('xcb_generic_iterator_t \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2573 (field.c_end_name, c_type))
2574 create_link('%s' % field.c_end_name)
2577 f.write('%s \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2578 (field.c_iterator_type, field.c_iterator_name,
2580 create_link('%s' % field.c_iterator_name)
2582 for field in self.reply.fields:
2583 if field.type.is_list and not field.type.fixed_size():
2584 _c_accessors_list(self, field)
2585 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2586 _c_accessors_field(self, field)
2590 # Re-enable hyphenation and adjusting to both sides
2593 # argument reference
2594 f.write('.SH REQUEST ARGUMENTS\n')
2595 f.write('.IP \\fI%s\\fP 1i\n' % 'conn')
2596 f.write('The XCB connection to X11.\n')
2597 for field in param_fields:
2598 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2599 printed_enum = False
2600 # XXX: hard-coded until we fix xproto.xml
2601 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
2603 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
2605 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
2607 if hasattr(field, "enum") and field.enum:
2608 # XXX: why the 'xcb' prefix?
2609 key = ('xcb', field.enum)
2611 f.write('One of the following values:\n')
2614 count = len(enum.values)
2615 for (enam, eval) in enum.values:
2617 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2618 if hasattr(enum, "doc") and enum.doc and enam in enum.doc.fields:
2619 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2620 f.write('%s\n' % desc)
2622 f.write('TODO: NOT YET DOCUMENTED.\n')
2627 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2628 desc = self.doc.fields[field.field_name]
2629 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2632 f.write('%s\n' % desc)
2634 f.write('TODO: NOT YET DOCUMENTED.\n')
2640 f.write('.SH REPLY FIELDS\n')
2641 # These fields are present in every reply:
2642 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2643 f.write(('The type of this reply, in this case \\fI%s\\fP. This field '
2644 'is also present in the \\fIxcb_generic_reply_t\\fP and can '
2645 'be used to tell replies apart from each other.\n') %
2646 _n(self.reply.name).upper())
2647 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2648 f.write('The sequence number of the last request processed by the X11 server.\n')
2649 f.write('.IP \\fI%s\\fP 1i\n' % 'length')
2650 f.write('The length of the reply, in words (a word is 4 bytes).\n')
2651 for field in self.reply.fields:
2652 if (field.c_field_name in frozenset(['response_type', 'sequence', 'length']) or
2653 field.c_field_name.startswith('pad')):
2656 if field.type.is_list and not field.type.fixed_size():
2658 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2660 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2661 printed_enum = False
2662 if hasattr(field, "enum") and field.enum:
2663 # XXX: why the 'xcb' prefix?
2664 key = ('xcb', field.enum)
2666 f.write('One of the following values:\n')
2669 count = len(enum.values)
2670 for (enam, eval) in enum.values:
2672 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2673 if enum.doc and enam in enum.doc.fields:
2674 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2675 f.write('%s\n' % desc)
2677 f.write('TODO: NOT YET DOCUMENTED.\n')
2682 if hasattr(self.reply, "doc") and self.reply.doc and field.field_name in self.reply.doc.fields:
2683 desc = self.reply.doc.fields[field.field_name]
2684 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2687 f.write('%s\n' % desc)
2689 f.write('TODO: NOT YET DOCUMENTED.\n')
2696 f.write('.SH DESCRIPTION\n')
2697 if hasattr(self, "doc") and self.doc and self.doc.description:
2698 desc = self.doc.description
2699 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2700 lines = desc.split('\n')
2701 f.write('\n'.join(lines) + '\n')
2703 f.write('.SH RETURN VALUE\n')
2705 f.write(('Returns an \\fIxcb_void_cookie_t\\fP. Errors (if any) '
2706 'have to be handled in the event loop.\n\nIf you want to '
2707 'handle errors directly with \\fIxcb_request_check\\fP '
2708 'instead, use \\fI%s_checked\\fP. See '
2709 '\\fBxcb-requests(%s)\\fP for details.\n') % (base_func_name, section))
2711 f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
2712 'calling the reply function \\fI%s\\fP.\n\nIf you want to '
2713 'handle errors in the event loop instead, use '
2714 '\\fI%s_unchecked\\fP. See \\fBxcb-requests(%s)\\fP for '
2716 (cookie_type, self.c_reply_name, base_func_name, section))
2717 f.write('.SH ERRORS\n')
2718 if hasattr(self, "doc") and self.doc:
2719 for errtype, errtext in self.doc.errors.items():
2720 f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
2721 errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
2722 f.write('%s\n' % (errtext))
2723 if not hasattr(self, "doc") or not self.doc or len(self.doc.errors) == 0:
2724 f.write('This request does never generate any errors.\n')
2725 if hasattr(self, "doc") and self.doc and self.doc.example:
2726 f.write('.SH EXAMPLE\n')
2729 lines = self.doc.example.split('\n')
2730 f.write('\n'.join(lines) + '\n')
2732 f.write('.SH SEE ALSO\n')
2733 if hasattr(self, "doc") and self.doc:
2734 see = ['.BR %s (%s)' % ('xcb-requests', section)]
2735 if self.doc.example:
2736 see.append('.BR %s (%s)' % ('xcb-examples', section))
2737 for seename, seetype in self.doc.see.items():
2738 if seetype == 'program':
2739 see.append('.BR %s (1)' % seename)
2740 elif seetype == 'event':
2741 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2742 elif seetype == 'request':
2743 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2744 elif seetype == 'function':
2745 see.append('.BR %s (%s)' % (seename, section))
2747 see.append('TODO: %s (type %s)' % (seename, seetype))
2748 f.write(',\n'.join(see) + '\n')
2749 f.write('.SH AUTHOR\n')
2750 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2753 def _man_event(self, name):
2755 sys.stdout.write('man/%s.%s ' % (self.c_type, section))
2756 # Our CWD is src/, so this will end up in src/man/
2757 f = open('man/%s.%s' % (self.c_type, section), 'w')
2758 f.write('.TH %s %s "%s" "%s" "XCB Events"\n' % (self.c_type, section, center_footer, left_footer))
2759 # Left-adjust instead of adjusting to both sides
2761 f.write('.SH NAME\n')
2762 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2763 f.write('%s \\- %s\n' % (self.c_type, brief))
2764 f.write('.SH SYNOPSIS\n')
2765 # Don't split words (hyphenate)
2767 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2770 f.write('.SS Event datastructure\n')
2773 f.write('typedef %s %s {\n' % (self.c_container, self.c_type))
2777 for field in self.fields:
2778 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2781 struct_fields.append(field)
2783 for field in struct_fields:
2784 length = len(field.c_field_type)
2785 # account for '*' pointer_spec
2786 if not field.type.fixed_size():
2788 maxtypelen = max(maxtypelen, length)
2790 def _c_complex_field(self, field, space=''):
2791 if (field.type.fixed_size() or
2792 # in case of switch with switch children, don't make the field a pointer
2793 # necessary for unserialize to work
2794 (self.is_switch and field.type.is_switch)):
2795 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2796 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2798 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2800 if not self.is_switch:
2801 for field in struct_fields:
2802 _c_complex_field(self, field)
2804 for b in self.bitcases:
2808 for field in b.type.fields:
2809 _c_complex_field(self, field, space)
2811 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2814 f.write('} \\fB%s\\fP;\n' % self.c_type)
2819 # Re-enable hyphenation and adjusting to both sides
2822 # argument reference
2823 f.write('.SH EVENT FIELDS\n')
2824 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2825 f.write(('The type of this event, in this case \\fI%s\\fP. This field is '
2826 'also present in the \\fIxcb_generic_event_t\\fP and can be used '
2827 'to tell events apart from each other.\n') % _n(name).upper())
2828 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2829 f.write('The sequence number of the last request processed by the X11 server.\n')
2831 if not self.is_switch:
2832 for field in struct_fields:
2833 # Skip the fields which every event has, we already documented
2835 if field.c_field_name in ('response_type', 'sequence'):
2837 if isinstance(field.type, PadType):
2839 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2840 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2841 desc = self.doc.fields[field.field_name]
2842 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2843 f.write('%s\n' % desc)
2845 f.write('NOT YET DOCUMENTED.\n')
2848 f.write('.SH DESCRIPTION\n')
2849 if hasattr(self, "doc") and self.doc and self.doc.description:
2850 desc = self.doc.description
2851 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2852 lines = desc.split('\n')
2853 f.write('\n'.join(lines) + '\n')
2855 if hasattr(self, "doc") and self.doc and self.doc.example:
2856 f.write('.SH EXAMPLE\n')
2859 lines = self.doc.example.split('\n')
2860 f.write('\n'.join(lines) + '\n')
2862 f.write('.SH SEE ALSO\n')
2863 if hasattr(self, "doc") and self.doc:
2864 see = ['.BR %s (%s)' % ('xcb_generic_event_t', section)]
2865 if self.doc.example:
2866 see.append('.BR %s (%s)' % ('xcb-examples', section))
2867 for seename, seetype in self.doc.see.items():
2868 if seetype == 'program':
2869 see.append('.BR %s (1)' % seename)
2870 elif seetype == 'event':
2871 see.append('.BR %s (%s)' % (_t(('xcb', seename, 'event')), section))
2872 elif seetype == 'request':
2873 see.append('.BR %s (%s)' % (_n(('xcb', seename)), section))
2874 elif seetype == 'function':
2875 see.append('.BR %s (%s)' % (seename, section))
2877 see.append('TODO: %s (type %s)' % (seename, seetype))
2878 f.write(',\n'.join(see) + '\n')
2879 f.write('.SH AUTHOR\n')
2880 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2884 def c_request(self, name):
2886 Exported function that handles request declarations.
2888 _c_type_setup(self, name, ('request',))
2891 # Cookie type declaration
2892 _c_cookie(self, name)
2895 _c_opcode(name, self.opcode)
2897 # Request structure declaration
2901 _c_type_setup(self.reply, name, ('reply',))
2902 # Reply structure definition
2903 _c_complex(self.reply)
2904 # Request prototypes
2905 has_fds = _c_reply_has_fds(self.reply)
2906 _c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds)
2907 _c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds)
2909 _c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds)
2910 _c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds)
2912 _c_accessors(self.reply, name + ('reply',), name)
2913 _c_reply(self, name)
2915 _c_reply_fds(self, name)
2917 # Request prototypes
2918 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2919 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2921 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2922 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2924 # We generate the manpage afterwards because _c_type_setup has been called.
2925 # TODO: what about aux helpers?
2926 cookie_type = self.c_cookie_type if self.reply else 'xcb_void_cookie_t'
2927 _man_request(self, name, cookie_type, not self.reply, False)
2929 def c_event(self, name):
2931 Exported function that handles event declarations.
2934 # The generic event structure xcb_ge_event_t has the full_sequence field
2935 # at the 32byte boundary. That's why we've to inject this field into GE
2936 # events while generating the structure for them. Otherwise we would read
2937 # garbage (the internal full_sequence) when accessing normal event fields
2939 force_packed = False
2940 if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
2942 for field in self.fields:
2943 if field.type.size != None and field.type.nmemb != None:
2944 event_size += field.type.size * field.type.nmemb
2945 if event_size == 32:
2946 full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
2947 idx = self.fields.index(field)
2948 self.fields.insert(idx + 1, full_sequence)
2950 # If the event contains any 64-bit extended fields, they need
2951 # to remain aligned on a 64-bit boundary. Adding full_sequence
2952 # would normally break that; force the struct to be packed.
2953 force_packed = any(f.type.size == 8 and f.type.is_simple for f in self.fields[(idx+1):])
2956 _c_type_setup(self, name, ('event',))
2959 _c_opcode(name, self.opcodes[name])
2961 if self.name == name:
2962 # Structure definition
2963 _c_complex(self, force_packed)
2967 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2969 _man_event(self, name)
2971 def c_error(self, name):
2973 Exported function that handles error declarations.
2975 _c_type_setup(self, name, ('error',))
2978 _c_opcode(name, self.opcodes[name])
2980 if self.name == name:
2981 # Structure definition
2986 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2989 # Main routine starts here
2991 # Must create an "output" dictionary before any xcbgen imports.
2992 output = {'open' : c_open,
2994 'simple' : c_simple,
2996 'struct' : c_struct,
2998 'request' : c_request,
3003 # Boilerplate below this point
3005 # Check for the argument that specifies path to the xcbgen python package.
3007 opts, args = getopt.getopt(sys.argv[1:], 'c:l:s:p:m')
3008 except getopt.GetoptError as err:
3010 print('Usage: c_client.py -c center_footer -l left_footer -s section [-p path] file.xml')
3013 for (opt, arg) in opts:
3021 sys.path.insert(1, arg)
3024 sys.stdout.write('man_MANS = ')
3026 # Import the module class
3028 from xcbgen.state import Module
3029 from xcbgen.xtypes import *
3032 Failed to load the xcbgen Python package!
3033 Make sure that xcb/proto installed it on your Python path.
3034 If not, you will need to create a .pth file or define $PYTHONPATH
3036 Refer to the README file in xcb/proto for more info.
3040 # Ensure the man subdirectory exists
3043 except OSError as e:
3044 if e.errno != errno.EEXIST:
3047 # Parse the xml header
3048 module = Module(args[0], output)
3050 # Build type-registry and resolve type dependencies