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.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 # switch/bitcase: always calculate padding before and after variable sized fields
985 if need_padding or is_bitcase:
986 count += _c_serialize_helper_insert_padding(context, code_lines, space,
987 self.var_followed_by_fixed_fields)
989 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
990 code_lines, temp_vars,
992 prev_field_was_variable = True
994 # save (un)serialization C code
996 code_lines.append('%s%s' % (space, value))
998 if field.type.fixed_size():
999 if is_bitcase or self.var_followed_by_fixed_fields:
1000 # keep track of (un)serialized object's size
1001 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1002 if context in ('unserialize', 'unpack', 'sizeof'):
1003 code_lines.append('%s xcb_tmp += %s;' % (space, length))
1005 # variable size objects or bitcase:
1006 # value & length might have been inserted earlier for special cases
1008 # special case: intermixed fixed and variable size fields
1009 if (not field.type.fixed_size() and
1010 self.var_followed_by_fixed_fields and 'unserialize' == context):
1011 temp_vars.append(' int %s_len;' % field.c_field_name)
1012 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
1013 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
1014 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
1016 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1017 # increase pointer into the byte stream accordingly
1018 if context in ('unserialize', 'sizeof', 'unpack'):
1019 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1021 if 'serialize' == context:
1023 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
1024 code_lines.append('%s xcb_parts_idx++;' % space)
1027 code_lines.append('%s xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type))
1030 if self.var_followed_by_fixed_fields:
1031 need_padding = False
1034 # _c_serialize_helper_fields()
1036 def _c_serialize_helper(context, complex_type,
1037 code_lines, temp_vars,
1038 space='', prefix=[]):
1039 # count tracks the number of fields to serialize
1042 if hasattr(complex_type, 'type'):
1043 self = complex_type.type
1044 complex_name = complex_type.name
1047 if self.var_followed_by_fixed_fields and 'unserialize' == context:
1048 complex_name = 'xcb_out'
1050 complex_name = '_aux'
1052 # special case: switch is serialized by evaluating each bitcase separately
1054 count += _c_serialize_helper_switch(context, self, complex_name,
1055 code_lines, temp_vars,
1058 # all other data types can be evaluated one field a time
1060 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1061 if context in ('unserialize', 'unpack', 'sizeof') and not self.var_followed_by_fixed_fields:
1062 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1063 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1064 # probably not needed
1065 #_c_serialize_helper_insert_padding(context, code_lines, space, False)
1067 count += _c_serialize_helper_fields(context, self,
1068 code_lines, temp_vars,
1069 space, prefix, False)
1071 count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
1074 # _c_serialize_helper()
1076 def _c_serialize(context, self):
1078 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1079 for the ComplexType variable self
1085 # _serialize() returns the buffer size
1088 if self.is_switch and 'unserialize' == context:
1091 cases = { 'serialize' : self.c_serialize_name,
1092 'unserialize' : self.c_unserialize_name,
1093 'unpack' : self.c_unpack_name,
1094 'sizeof' : self.c_sizeof_name }
1095 func_name = cases[context]
1097 param_fields, wire_fields, params = get_serialize_params(context, self)
1098 variable_size_fields = 0
1099 # maximum space required for type definition of function arguments
1102 # determine N(variable_fields)
1103 for field in param_fields:
1104 # if self.is_switch, treat all fields as if they are variable sized
1105 if not field.type.fixed_size() or self.is_switch:
1106 variable_size_fields += 1
1107 # determine maxtypelen
1109 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1112 indent = ' '*(len(func_name)+2)
1115 typespec, pointerspec, field_name = p
1116 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1117 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1118 # insert function name
1119 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1120 param_str = list(map(lambda x: "%s," % x, param_str))
1121 for s in param_str[:-1]:
1123 _h("%s);" % param_str[-1].rstrip(','))
1124 _c("%s)" % param_str[-1].rstrip(','))
1131 if 'serialize' == context:
1132 if not self.is_switch and not self.var_followed_by_fixed_fields:
1133 _c(' %s *xcb_out = *_buffer;', self.c_type)
1134 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1135 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1136 _c(' unsigned int xcb_align_to = 0;')
1138 _c(' char *xcb_out = *_buffer;')
1139 _c(' unsigned int xcb_buffer_len = 0;')
1140 _c(' unsigned int xcb_align_to = 0;')
1141 prefix = [('_aux', '->', self)]
1144 elif context in ('unserialize', 'unpack'):
1145 _c(' char *xcb_tmp = (char *)_buffer;')
1146 if not self.is_switch:
1147 if not self.var_followed_by_fixed_fields:
1148 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1149 prefix = [('_aux', '->', self)]
1151 _c(' %s xcb_out;', self.c_type)
1152 prefix = [('xcb_out', '.', self)]
1154 aux_var = '_aux' # default for unpack: single pointer
1155 # note: unserialize not generated for switch
1156 if 'unserialize' == context:
1157 aux_var = '(*_aux)' # unserialize: double pointer (!)
1158 prefix = [(aux_var, '->', self)]
1160 _c(' unsigned int xcb_buffer_len = 0;')
1161 _c(' unsigned int xcb_block_len = 0;')
1162 _c(' unsigned int xcb_pad = 0;')
1163 _c(' unsigned int xcb_align_to = 0;')
1165 elif 'sizeof' == context:
1166 param_names = [p[2] for p in params]
1168 # switch: call _unpack()
1169 _c(' %s _aux;', self.c_type)
1170 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1173 elif self.var_followed_by_fixed_fields:
1174 # special case: call _unserialize()
1175 _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1179 _c(' char *xcb_tmp = (char *)_buffer;')
1180 prefix = [('_aux', '->', self)]
1182 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1183 # update variable size fields (only important for context=='serialize'
1184 variable_size_fields = count
1185 if 'serialize' == context:
1186 temp_vars.append(' unsigned int xcb_pad = 0;')
1187 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1188 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1189 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1190 temp_vars.append(' unsigned int xcb_block_len = 0;')
1191 temp_vars.append(' unsigned int i;')
1192 temp_vars.append(' char *xcb_tmp;')
1193 elif 'sizeof' == context:
1194 # neither switch nor intermixed fixed and variable size fields:
1195 # evaluate parameters directly
1196 if not (self.is_switch or self.var_followed_by_fixed_fields):
1198 # look if we have to declare an '_aux' variable at all
1199 if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
1200 if not self.var_followed_by_fixed_fields:
1201 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1203 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1205 _c(' unsigned int xcb_buffer_len = 0;')
1206 _c(' unsigned int xcb_block_len = 0;')
1207 _c(' unsigned int xcb_pad = 0;')
1208 _c(' unsigned int xcb_align_to = 0;')
1214 for l in code_lines:
1217 # variable sized fields have been collected, now
1218 # allocate memory and copy everything into a continuous memory area
1219 # note: this is not necessary in case of unpack
1220 if context in ('serialize', 'unserialize'):
1221 # unserialize: check for sizeof-only invocation
1222 if 'unserialize' == context:
1224 _c(' if (NULL == _aux)')
1225 _c(' return xcb_buffer_len;')
1228 _c(' if (NULL == %s) {', aux_ptr)
1229 _c(' /* allocate memory */')
1230 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1231 if 'serialize' == context:
1232 _c(' *_buffer = xcb_out;')
1236 # serialize: handle variable size fields in a loop
1237 if 'serialize' == context:
1238 if not self.is_switch and not self.var_followed_by_fixed_fields:
1239 if len(wire_fields)>0:
1240 _c(' *xcb_out = *_aux;')
1241 # copy variable size fields into the buffer
1242 if variable_size_fields > 0:
1244 if not self.is_switch and not self.var_followed_by_fixed_fields:
1245 _c(' xcb_tmp = (char*)++xcb_out;')
1246 _c(' xcb_tmp += xcb_out_pad;')
1248 _c(' xcb_tmp = xcb_out;')
1250 # variable sized fields
1251 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1252 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1253 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1254 _c(' if (0 != xcb_parts[i].iov_len)')
1255 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1258 # unserialize: assign variable size fields individually
1259 if 'unserialize' == context:
1260 _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1261 param_fields.reverse()
1262 for field in param_fields:
1263 if not field.type.fixed_size():
1264 _c(' xcb_tmp -= %s_len;', field.c_field_name)
1265 _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1266 _c(' *%s = xcb_out;', aux_ptr)
1269 _c(' return xcb_buffer_len;')
1273 def _c_iterator_get_end(field, accum):
1275 Figures out what C code is needed to find the end of a variable-length structure field.
1276 For nested structures, recurses into its last variable-sized field.
1277 For lists, calls the end function
1279 if field.type.is_container:
1280 accum = field.c_accessor_name + '(' + accum + ')'
1281 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1282 if field.type.is_list:
1283 # XXX we can always use the first way
1284 if field.type.member.is_simple:
1285 return field.c_end_name + '(' + accum + ')'
1287 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1289 def _c_iterator(self, name):
1291 Declares the iterator structure and next/end functions for a given type.
1296 _h(' * @brief %s', self.c_iterator_type)
1298 _h('typedef struct %s {', self.c_iterator_type)
1299 _h(' %s *data; /**< */', self.c_type)
1300 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1301 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1302 _h('} %s;', self.c_iterator_type)
1308 _h(' * Get the next element of the iterator')
1309 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1311 _h(' * Get the next element in the iterator. The member rem is')
1312 _h(' * decreased by one. The member data points to the next')
1313 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1317 _hc('/*****************************************************************************')
1319 _hc(' ** void %s', self.c_next_name)
1321 _hc(' ** @param %s *i', self.c_iterator_type)
1322 _hc(' ** @returns void')
1324 _hc(' *****************************************************************************/')
1327 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1328 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1331 if not self.fixed_size():
1332 _c(' %s *R = i->data;', self.c_type)
1335 # FIXME - how to determine the size of a variable size union??
1336 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1338 if self.need_sizeof:
1339 _c(' xcb_generic_iterator_t child;')
1340 _c(' child.data = (%s *)(((char *)R) + %s(R));',
1341 self.c_type, self.c_sizeof_name)
1342 _c(' i->index = (char *) child.data - (char *) i->data;')
1344 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1345 _c(' i->index = child.index;')
1347 _c(' i->data = (%s *) child.data;', self.c_type)
1352 _c(' i->index += sizeof(%s);', self.c_type)
1358 _h(' * Return the iterator pointing to the last element')
1359 _h(' * @param i An %s', self.c_iterator_type)
1360 _h(' * @return The iterator pointing to the last element')
1362 _h(' * Set the current element in the iterator to the last element.')
1363 _h(' * The member rem is set to 0. The member data points to the')
1364 _h(' * last element.')
1368 _hc('/*****************************************************************************')
1370 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1372 _hc(' ** @param %s i', self.c_iterator_type)
1373 _hc(' ** @returns xcb_generic_iterator_t')
1375 _hc(' *****************************************************************************/')
1377 _hc('xcb_generic_iterator_t')
1378 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1379 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1381 _c(' xcb_generic_iterator_t ret;')
1383 if self.fixed_size():
1384 _c(' ret.data = i.data + i.rem;')
1385 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1388 _c(' while(i.rem > 0)')
1389 _c(' %s(&i);', self.c_next_name)
1390 _c(' ret.data = i.data;')
1391 _c(' ret.rem = i.rem;')
1392 _c(' ret.index = i.index;')
1397 def _c_accessor_get_length(expr, field_mapping=None):
1399 Figures out what C code is needed to get a length field.
1400 The field_mapping parameter can be used to change the absolute name of a length field.
1401 For fields that follow a variable-length field, use the accessor.
1402 Otherwise, just reference the structure field directly.
1405 lenfield_name = expr.lenfield_name
1406 if lenfield_name is not None:
1407 if field_mapping is not None:
1408 lenfield_name = field_mapping[lenfield_name][0]
1410 if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1411 # special case: variable and fixed size fields are intermixed
1412 # if the lenfield is among the fixed size fields, there is no need
1413 # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1414 return field_mapping(expr.lenfield_name)
1415 elif expr.lenfield_name is not None:
1416 return lenfield_name
1418 return str(expr.nmemb)
1420 def _c_accessor_get_expr(expr, field_mapping):
1422 Figures out what C code is needed to get the length of a list field.
1423 The field_mapping parameter can be used to change the absolute name of a length field.
1424 Recurses for math operations.
1425 Returns bitcount for value-mask fields.
1426 Otherwise, uses the value of the length field.
1428 lenexp = _c_accessor_get_length(expr, field_mapping)
1431 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1432 elif expr.op == 'popcount':
1433 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1434 elif expr.op == 'enumref':
1435 enum_name = expr.lenfield_type.name
1436 constant_name = expr.lenfield_name
1437 c_name = _n(enum_name + (constant_name,)).upper()
1439 elif expr.op == 'sumof':
1440 # locate the referenced list object
1441 list_obj = expr.lenfield_type
1443 for f in expr.lenfield_parent.fields:
1444 if f.field_name == expr.lenfield_name:
1449 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1450 list_name = field_mapping[field.c_field_name][0]
1451 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1452 # note: xcb_sumof() has only been defined for integers
1453 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1454 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1455 elif expr.op != None:
1456 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1457 ' ' + expr.op + ' ' +
1458 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1460 return 'xcb_popcount(' + lenexp + ')'
1464 def type_pad_type(type):
1469 def _c_accessors_field(self, field):
1471 Declares the accessor functions for a non-list field that follows a variable-length field.
1473 c_type = self.c_type
1475 # special case: switch
1476 switch_obj = self if self.is_switch else None
1478 switch_obj = self.parents[-1]
1479 if switch_obj is not None:
1480 c_type = switch_obj.c_type
1482 if field.type.is_simple:
1485 _hc('/*****************************************************************************')
1487 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1489 _hc(' ** @param const %s *R', c_type)
1490 _hc(' ** @returns %s', field.c_field_type)
1492 _hc(' *****************************************************************************/')
1494 _hc('%s', field.c_field_type)
1495 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1496 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1498 if field.prev_varsized_field is None:
1499 _c(' return (%s *) (R + 1);', field.c_field_type)
1501 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1502 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1503 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1508 _hc('/*****************************************************************************')
1510 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1512 _hc(' ** @param const %s *R', c_type)
1513 _hc(' ** @returns %s *', field.c_field_type)
1515 _hc(' *****************************************************************************/')
1517 if field.type.is_switch and switch_obj is None:
1518 return_type = 'void *'
1520 return_type = '%s *' % field.c_field_type
1523 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1524 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1526 if field.prev_varsized_field is None:
1527 _c(' return (%s) (R + 1);', return_type)
1528 # note: the special case 'variable fields followed by fixed size fields'
1529 # is not of any consequence here, since the ordering gets
1530 # 'corrected' in the reply function
1532 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1533 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1534 return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1538 def _c_accessors_list(self, field):
1540 Declares the accessor functions for a list field.
1541 Declares a direct-accessor function only if the list members are fixed size.
1542 Declares length and get-iterator functions always.
1545 c_type = self.c_type
1547 # special case: switch
1548 # in case of switch, 2 params have to be supplied to certain accessor functions:
1549 # 1. the anchestor object (request or reply)
1550 # 2. the (anchestor) switch object
1551 # the reason is that switch is either a child of a request/reply or nested in another switch,
1552 # so whenever we need to access a length field, we might need to refer to some anchestor type
1553 switch_obj = self if self.is_switch else None
1555 switch_obj = self.parents[-1]
1556 if switch_obj is not None:
1557 c_type = switch_obj.c_type
1561 parents = self.parents if hasattr(self, 'parents') else [self]
1562 # 'R': parents[0] is always the 'toplevel' container type
1563 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1564 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1565 # auxiliary object for 'R' parameters
1568 if switch_obj is not None:
1569 # now look where the fields are defined that are needed to evaluate
1570 # the switch expr, and store the parent objects in accessor_params and
1571 # the fields in switch_fields
1573 # 'S': name for the 'toplevel' switch
1574 toplevel_switch = parents[1]
1575 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1576 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1578 # initialize prefix for everything "below" S
1579 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1580 prefix = [(prefix_str, '->', toplevel_switch)]
1582 # look for fields in the remaining containers
1583 for p in parents[2:] + [self]:
1584 # the separator between parent and child is always '.' here,
1585 # because of nested switch statements
1586 if not p.is_bitcase or (p.is_bitcase and p.has_name):
1587 prefix.append((p.name[-1], '.', p))
1588 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1590 # auxiliary object for 'S' parameter
1595 if list.member.fixed_size():
1596 idx = 1 if switch_obj is not None else 0
1599 _hc('/*****************************************************************************')
1601 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1603 _hc(' ** @param %s', params[idx][0])
1604 _hc(' ** @returns %s *', field.c_field_type)
1606 _hc(' *****************************************************************************/')
1608 _hc('%s *', field.c_field_type)
1610 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1611 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1614 if switch_obj is not None:
1615 _c(' return %s;', fields[field.c_field_name][0])
1616 elif field.prev_varsized_field is None:
1617 _c(' return (%s *) (R + 1);', field.c_field_type)
1619 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1620 _c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1621 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1626 _hc('/*****************************************************************************')
1628 _hc(' ** int %s', field.c_length_name)
1630 _hc(' ** @param const %s *R', c_type)
1631 _hc(' ** @returns int')
1633 _hc(' *****************************************************************************/')
1636 if switch_obj is not None:
1637 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1638 spacing = ' '*(len(field.c_length_name)+2)
1639 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1640 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1641 length = _c_accessor_get_expr(field.type.expr, fields)
1643 _h('%s (const %s *R /**< */);', field.c_length_name, c_type)
1644 _c('%s (const %s *R /**< */)', field.c_length_name, c_type)
1645 length = _c_accessor_get_expr(field.type.expr, fields)
1647 _c(' return %s;', length)
1650 if field.type.member.is_simple:
1653 _hc('/*****************************************************************************')
1655 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1657 _hc(' ** @param const %s *R', c_type)
1658 _hc(' ** @returns xcb_generic_iterator_t')
1660 _hc(' *****************************************************************************/')
1662 _hc('xcb_generic_iterator_t')
1663 if switch_obj is not None:
1664 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1665 spacing = ' '*(len(field.c_end_name)+2)
1666 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1667 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1669 _h('%s (const %s *R /**< */);', field.c_end_name, c_type)
1670 _c('%s (const %s *R /**< */)', field.c_end_name, c_type)
1672 _c(' xcb_generic_iterator_t i;')
1674 param = 'R' if switch_obj is None else 'S'
1675 if switch_obj is not None:
1676 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1677 _c_accessor_get_expr(field.type.expr, fields))
1678 elif field.prev_varsized_field == None:
1679 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1680 _c_accessor_get_expr(field.type.expr, fields))
1682 _c(' xcb_generic_iterator_t child = %s;',
1683 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1684 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1685 _c_accessor_get_expr(field.type.expr, fields))
1688 _c(' i.index = (char *) i.data - (char *) %s;', param)
1695 _hc('/*****************************************************************************')
1697 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1699 _hc(' ** @param const %s *R', c_type)
1700 _hc(' ** @returns %s', field.c_iterator_type)
1702 _hc(' *****************************************************************************/')
1705 _hc('%s', field.c_iterator_type)
1706 if switch_obj is not None:
1707 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1708 spacing = ' '*(len(field.c_iterator_name)+2)
1709 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1710 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1712 _h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
1713 _c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
1715 _c(' %s i;', field.c_iterator_type)
1717 if switch_obj is not None:
1718 _c(' i.data = %s;', fields[field.c_field_name][0])
1719 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1720 elif field.prev_varsized_field == None:
1721 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1723 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1724 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));',
1725 field.c_field_type, type_pad_type(field.c_field_type))
1726 if switch_obj is None:
1727 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1728 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1732 def _c_accessors(self, name, base):
1734 Declares the accessor functions for the fields of a structure.
1736 # no accessors for switch itself -
1737 # switch always needs to be unpacked explicitly
1738 # if self.is_switch:
1742 for field in self.fields:
1743 if field.type.is_list and not field.type.fixed_size():
1744 _c_accessors_list(self, field)
1745 elif field.prev_varsized_field is not None or not field.type.fixed_size():
1746 _c_accessors_field(self, field)
1748 def c_simple(self, name):
1750 Exported function that handles cardinal type declarations.
1751 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1753 _c_type_setup(self, name, ())
1755 if (self.name != name):
1760 _h('typedef %s %s;', _t(self.name), my_name)
1763 _c_iterator(self, name)
1765 def _c_complex(self):
1767 Helper function for handling all structure types.
1768 Called for all structs, requests, replies, events, errors.
1773 _h(' * @brief %s', self.c_type)
1775 _h('typedef %s %s {', self.c_container, self.c_type)
1781 for field in self.fields:
1782 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1783 varfield = field.c_field_name
1786 struct_fields.append(field)
1788 for field in struct_fields:
1789 length = len(field.c_field_type)
1790 # account for '*' pointer_spec
1791 if not field.type.fixed_size() and not self.is_union:
1793 maxtypelen = max(maxtypelen, length)
1795 def _c_complex_field(self, field, space=''):
1796 if (field.type.fixed_size() or self.is_union or
1797 # in case of switch with switch children, don't make the field a pointer
1798 # necessary for unserialize to work
1799 (self.is_switch and field.type.is_switch)):
1800 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1801 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1803 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1804 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1806 if not self.is_switch:
1807 for field in struct_fields:
1808 _c_complex_field(self, field)
1810 for b in self.bitcases:
1813 _h(' struct _%s {', b.c_field_name)
1815 for field in b.type.fields:
1816 _c_complex_field(self, field, space)
1818 _h(' } %s;', b.c_field_name)
1820 _h('} %s;', self.c_type)
1822 def c_struct(self, name):
1824 Exported function that handles structure declarations.
1826 _c_type_setup(self, name, ())
1828 _c_accessors(self, name, name)
1829 _c_iterator(self, name)
1831 def c_union(self, name):
1833 Exported function that handles union declarations.
1835 _c_type_setup(self, name, ())
1837 _c_iterator(self, name)
1839 def _c_request_helper(self, name, cookie_type, void, regular, aux=False, reply_fds=False):
1841 Declares a request function.
1844 # Four stunningly confusing possibilities here:
1847 # ------------------------------
1849 # 0 flag CHECKED flag Normal Mode
1850 # void_cookie req_cookie
1851 # ------------------------------
1852 # "req_checked" "req_unchecked"
1853 # CHECKED flag 0 flag Abnormal Mode
1854 # void_cookie req_cookie
1855 # ------------------------------
1858 # Whether we are _checked or _unchecked
1859 checked = void and not regular
1860 unchecked = not void and not regular
1862 # What kind of cookie we return
1863 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1865 # What flag is passed to xcb_request
1866 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1869 if func_flags == '0':
1870 func_flags = 'XCB_REQUEST_REPLY_FDS'
1872 func_flags = func_flags + '|XCB_REQUEST_REPLY_FDS'
1874 # Global extension id variable or NULL for xproto
1875 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1877 # What our function name is
1878 func_name = self.c_request_name if not aux else self.c_aux_name
1880 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1882 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1886 maxtypelen = len('xcb_connection_t')
1888 # special case: list with variable size elements
1889 list_with_var_size_elems = False
1891 for field in self.fields:
1893 # The field should appear as a call parameter
1894 param_fields.append(field)
1895 if field.wire and not field.auto:
1896 # We need to set the field up in the structure
1897 wire_fields.append(field)
1898 if field.type.need_serialize or field.type.need_sizeof:
1899 serial_fields.append(field)
1901 for field in param_fields:
1902 c_field_const_type = field.c_field_const_type
1903 if field.type.need_serialize and not aux:
1904 c_field_const_type = "const void"
1905 if len(c_field_const_type) > maxtypelen:
1906 maxtypelen = len(c_field_const_type)
1907 if field.type.is_list and not field.type.member.fixed_size():
1908 list_with_var_size_elems = True
1914 if hasattr(self, "doc") and self.doc:
1916 _h(' * @brief ' + self.doc.brief)
1918 _h(' * No brief doc yet')
1921 _h(' * @param c The connection')
1922 param_names = [f.c_field_name for f in param_fields]
1923 if hasattr(self, "doc") and self.doc:
1924 for field in param_fields:
1925 # XXX: hard-coded until we fix xproto.xml
1926 base_func_name = self.c_request_name if not aux else self.c_aux_name
1927 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
1929 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
1931 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
1934 # XXX: why the 'xcb' prefix?
1935 key = ('xcb', field.enum)
1938 if namecount[tname] > 1:
1939 tname = _t(key + ('enum',))
1940 _h(' * @param %s A bitmask of #%s values.' % (field.c_field_name, tname))
1942 if self.doc and field.field_name in self.doc.fields:
1943 desc = self.doc.fields[field.field_name]
1944 for name in param_names:
1945 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1946 desc = desc.split("\n")
1947 desc = [line if line != '' else '\\n' for line in desc]
1948 _h(' * @param %s %s' % (field.c_field_name, "\n * ".join(desc)))
1949 # If there is no documentation yet, we simply don't generate an
1950 # @param tag. Doxygen will then warn about missing documentation.
1952 _h(' * @return A cookie')
1955 if hasattr(self, "doc") and self.doc:
1956 if self.doc.description:
1957 desc = self.doc.description
1958 for name in param_names:
1959 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1960 desc = desc.split("\n")
1961 _h(' * ' + "\n * ".join(desc))
1963 _h(' * No description yet')
1965 _h(' * Delivers a request to the X server.')
1968 _h(' * This form can be used only if the request will not cause')
1969 _h(' * a reply to be generated. Any returned error will be')
1970 _h(' * saved for handling by xcb_request_check().')
1972 _h(' * This form can be used only if the request will cause')
1973 _h(' * a reply to be generated. Any returned error will be')
1974 _h(' * placed in the event queue.')
1978 _hc('/*****************************************************************************')
1980 _hc(' ** %s %s', cookie_type, func_name)
1983 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1984 _hc(' ** @param xcb_connection_t%s *c', spacing)
1986 for field in param_fields:
1987 c_field_const_type = field.c_field_const_type
1988 if field.type.need_serialize and not aux:
1989 c_field_const_type = "const void"
1990 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1991 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1993 _hc(' ** @returns %s', cookie_type)
1995 _hc(' *****************************************************************************/')
1997 _hc('%s', cookie_type)
1999 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
2000 comma = ',' if len(param_fields) else ');'
2001 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
2002 comma = ',' if len(param_fields) else ')'
2003 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
2005 func_spacing = ' ' * (len(func_name) + 2)
2006 count = len(param_fields)
2007 for field in param_fields:
2009 c_field_const_type = field.c_field_const_type
2010 c_pointer = field.c_pointer
2011 if field.type.need_serialize and not aux:
2012 c_field_const_type = "const void"
2014 spacing = ' ' * (maxtypelen - len(c_field_const_type))
2015 comma = ',' if count else ');'
2016 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
2017 spacing, c_pointer, field.c_field_name, comma)
2018 comma = ',' if count else ')'
2019 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
2020 spacing, c_pointer, field.c_field_name, comma)
2023 if not self.var_followed_by_fixed_fields:
2024 for field in param_fields:
2025 if not field.type.fixed_size():
2027 if field.type.need_serialize:
2028 # _serialize() keeps track of padding automatically
2030 dimension = count + 2
2033 _c(' static const xcb_protocol_request_t xcb_req = {')
2034 _c(' /* count */ %d,', count)
2035 _c(' /* ext */ %s,', func_ext_global)
2036 _c(' /* opcode */ %s,', self.c_request_name.upper())
2037 _c(' /* isvoid */ %d', 1 if void else 0)
2041 _c(' struct iovec xcb_parts[%d];', dimension)
2042 _c(' %s xcb_ret;', func_cookie)
2043 _c(' %s xcb_out;', self.c_type)
2044 if self.var_followed_by_fixed_fields:
2045 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
2046 _c(' void *xcb_aux = 0;')
2049 for idx, f in enumerate(serial_fields):
2051 _c(' void *xcb_aux%d = 0;' % (idx))
2052 if list_with_var_size_elems:
2053 _c(' unsigned int i;')
2054 _c(' unsigned int xcb_tmp_len;')
2055 _c(' char *xcb_tmp;')
2057 # simple request call tracing
2058 # _c(' printf("in function %s\\n");' % func_name)
2061 for field in wire_fields:
2062 if field.type.fixed_size():
2063 if field.type.is_expr:
2064 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
2065 elif field.type.is_pad:
2066 if field.type.nmemb == 1:
2067 _c(' xcb_out.%s = 0;', field.c_field_name)
2069 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
2071 if field.type.nmemb == 1:
2072 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
2074 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
2076 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
2077 serialize_args = get_serialize_params(context, type_obj,
2080 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
2082 # calls in order to free dyn. all. memory
2086 if not self.var_followed_by_fixed_fields:
2087 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2088 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
2089 _c(' xcb_parts[3].iov_base = 0;')
2090 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2094 for field in param_fields:
2095 if not field.type.fixed_size():
2096 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
2097 # default: simple cast to char *
2098 if not field.type.need_serialize and not field.type.need_sizeof:
2099 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2100 if field.type.is_list:
2101 if field.type.member.fixed_size():
2102 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
2103 _c_accessor_get_expr(field.type.expr, None),
2104 field.type.member.c_wiretype)
2106 list_length = _c_accessor_get_expr(field.type.expr, None)
2109 _c(" xcb_parts[%d].iov_len = 0;" % count)
2110 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2111 _c(" for(i=0; i<%s; i++) {" % list_length)
2112 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2113 (field.type.c_sizeof_name))
2114 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2115 _c(" xcb_tmp += xcb_tmp_len;")
2118 # not supposed to happen
2119 raise Exception("unhandled variable size field %s" % field.c_field_name)
2122 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2123 idx = serial_fields.index(field)
2124 aux_var = '&xcb_aux%d' % idx
2125 context = 'serialize' if aux else 'sizeof'
2126 _c(' xcb_parts[%d].iov_len = ', count)
2128 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2129 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2130 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2131 free_calls.append(' free(xcb_aux%d);' % idx)
2133 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2134 func_name = field.type.c_sizeof_name
2135 _c(' %s (%s);', func_name, serialize_args)
2138 if not (field.type.need_serialize or field.type.need_sizeof):
2139 # the _serialize() function keeps track of padding automatically
2140 _c(' xcb_parts[%d].iov_base = 0;', count)
2141 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2144 # elif self.var_followed_by_fixed_fields:
2146 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2147 # request header: opcodes + length
2148 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2151 buffer_var = '&xcb_aux'
2152 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2153 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2154 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2155 free_calls.append(' free(xcb_aux);')
2156 # no padding necessary - _serialize() keeps track of padding automatically
2159 for field in param_fields:
2161 _c(' xcb_send_fd(c, %s);', field.c_field_name)
2163 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2165 # free dyn. all. data, if any
2166 for f in free_calls:
2168 _c(' return xcb_ret;')
2171 def _c_reply(self, name):
2173 Declares the function that returns the reply structure.
2175 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2176 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2177 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2179 # check if _unserialize() has to be called for any field
2180 def look_for_special_cases(complex_obj):
2181 unserialize_fields = []
2182 # no unserialize call in case of switch
2183 if not complex_obj.is_switch:
2184 for field in complex_obj.fields:
2185 # three cases: 1. field with special case
2186 # 2. container that contains special case field
2187 # 3. list with special case elements
2188 if field.type.var_followed_by_fixed_fields:
2189 unserialize_fields.append(field)
2190 elif field.type.is_container:
2191 unserialize_fields += look_for_special_cases(field.type)
2192 elif field.type.is_list:
2193 if field.type.member.var_followed_by_fixed_fields:
2194 unserialize_fields.append(field)
2195 if field.type.member.is_container:
2196 unserialize_fields += look_for_special_cases(field.type.member)
2197 return unserialize_fields
2199 unserialize_fields = look_for_special_cases(self.reply)
2203 _h(' * Return the reply')
2204 _h(' * @param c The connection')
2205 _h(' * @param cookie The cookie')
2206 _h(' * @param e The xcb_generic_error_t supplied')
2208 _h(' * Returns the reply of the request asked by')
2210 _h(' * The parameter @p e supplied to this function must be NULL if')
2211 _h(' * %s(). is used.', self.c_unchecked_name)
2212 _h(' * Otherwise, it stores the error if any.')
2214 _h(' * The returned value must be freed by the caller using free().')
2218 _hc('/*****************************************************************************')
2220 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
2222 _hc(' ** @param xcb_connection_t%s *c', spacing1)
2223 _hc(' ** @param %s cookie', self.c_cookie_type)
2224 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
2225 _hc(' ** @returns %s *', self.c_reply_type)
2227 _hc(' *****************************************************************************/')
2229 _hc('%s *', self.c_reply_type)
2230 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2231 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2232 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2233 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2236 if len(unserialize_fields)>0:
2237 # certain variable size fields need to be unserialized explicitly
2238 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2239 self.c_reply_type, self.c_reply_type)
2241 for field in unserialize_fields:
2242 if field.type.is_list:
2243 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2244 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2245 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2247 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2248 # call _unserialize(), using the reply as source and target buffer
2249 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2250 for field in unserialize_fields:
2251 if field.type.is_list:
2252 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2253 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2254 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2255 field.c_field_name, field.c_field_name)
2256 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2258 # return the transformed reply
2259 _c(' return reply;')
2262 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2266 def _c_reply_has_fds(self):
2267 for field in self.fields:
2272 def _c_reply_fds(self, name):
2274 Declares the function that returns fds related to the reply.
2276 spacing1 = ' ' * (len(self.c_reply_type) - len('xcb_connection_t'))
2277 spacing3 = ' ' * (len(self.c_reply_fds_name) + 2)
2280 _h(' * Return the reply fds')
2281 _h(' * @param c The connection')
2282 _h(' * @param reply The reply')
2284 _h(' * Returns the array of reply fds of the request asked by')
2286 _h(' * The returned value must be freed by the caller using free().')
2290 _hc('/*****************************************************************************')
2292 _hc(' ** int * %s', self.c_reply_fds_name)
2294 _hc(' ** @param xcb_connection_t%s *c', spacing1)
2295 _hc(' ** @param %s *reply', self.c_reply_type)
2296 _hc(' ** @returns int *')
2298 _hc(' *****************************************************************************/')
2301 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_fds_name, spacing1)
2302 _h('%s%s *reply /**< */);', spacing3, self.c_reply_type)
2303 _c('%s%s *reply /**< */)', spacing3, self.c_reply_type)
2306 _c(' return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
2311 def _c_opcode(name, opcode):
2313 Declares the opcode define for requests, events, and errors.
2317 _h('/** Opcode for %s. */', _n(name))
2318 _h('#define %s %s', _n(name).upper(), opcode)
2320 def _c_cookie(self, name):
2322 Declares the cookie type for a non-void request.
2327 _h(' * @brief %s', self.c_cookie_type)
2329 _h('typedef struct %s {', self.c_cookie_type)
2330 _h(' unsigned int sequence; /**< */')
2331 _h('} %s;', self.c_cookie_type)
2333 def _man_request(self, name, cookie_type, void, aux):
2334 param_fields = [f for f in self.fields if f.visible]
2336 func_name = self.c_request_name if not aux else self.c_aux_name
2338 def create_link(linkname):
2339 name = 'man/%s.3' % linkname
2341 sys.stdout.write(name)
2343 f.write('.so man3/%s.3' % func_name)
2347 sys.stdout.write('man/%s.3 ' % func_name)
2348 # Our CWD is src/, so this will end up in src/man/
2349 f = open('man/%s.3' % func_name, 'w')
2350 f.write('.TH %s 3 %s "XCB" "XCB Requests"\n' % (func_name, today))
2351 # Left-adjust instead of adjusting to both sides
2353 f.write('.SH NAME\n')
2354 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2355 f.write('%s \\- %s\n' % (func_name, brief))
2356 f.write('.SH SYNOPSIS\n')
2357 # Don't split words (hyphenate)
2359 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2361 # function prototypes
2363 count = len(param_fields)
2364 for field in param_fields:
2366 c_field_const_type = field.c_field_const_type
2367 c_pointer = field.c_pointer
2368 if c_pointer == ' ':
2370 if field.type.need_serialize and not aux:
2371 c_field_const_type = "const void"
2373 comma = ', ' if count else ');'
2374 prototype += '%s\\ %s\\fI%s\\fP%s' % (c_field_const_type, c_pointer, field.c_field_name, comma)
2376 f.write('.SS Request function\n')
2378 base_func_name = self.c_request_name if not aux else self.c_aux_name
2379 f.write('%s \\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\n' % (cookie_type, base_func_name, prototype))
2380 create_link('%s_%s' % (base_func_name, ('checked' if void else 'unchecked')))
2383 f.write('.SS Reply datastructure\n')
2386 f.write('typedef %s %s {\n' % (self.reply.c_container, self.reply.c_type))
2390 for field in self.reply.fields:
2391 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2394 struct_fields.append(field)
2396 for field in struct_fields:
2397 length = len(field.c_field_type)
2398 # account for '*' pointer_spec
2399 if not field.type.fixed_size():
2401 maxtypelen = max(maxtypelen, length)
2403 def _c_complex_field(self, field, space=''):
2404 if (field.type.fixed_size() or
2405 # in case of switch with switch children, don't make the field a pointer
2406 # necessary for unserialize to work
2407 (self.is_switch and field.type.is_switch)):
2408 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2409 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2411 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
2412 f.write('ELSE %s = %s\n' % (field.c_field_type, field.c_field_name))
2413 #_h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2415 if not self.is_switch:
2416 for field in struct_fields:
2417 _c_complex_field(self, field)
2419 for b in self.bitcases:
2423 for field in b.type.fields:
2424 _c_complex_field(self, field, space)
2426 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2429 f.write('} \\fB%s\\fP;\n' % self.reply.c_type)
2432 f.write('.SS Reply function\n')
2434 f.write(('%s *\\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\\ '
2435 '\\fIcookie\\fP, xcb_generic_error_t\\ **\\fIe\\fP);\n') %
2436 (self.c_reply_type, self.c_reply_name, self.c_cookie_type))
2437 create_link('%s' % self.c_reply_name)
2439 has_accessors = False
2440 for field in self.reply.fields:
2441 if field.type.is_list and not field.type.fixed_size():
2442 has_accessors = True
2443 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2444 has_accessors = True
2447 f.write('.SS Reply accessors\n')
2449 def _c_accessors_field(self, field):
2451 Declares the accessor functions for a non-list field that follows a variable-length field.
2453 c_type = self.c_type
2455 # special case: switch
2456 switch_obj = self if self.is_switch else None
2458 switch_obj = self.parents[-1]
2459 if switch_obj is not None:
2460 c_type = switch_obj.c_type
2462 if field.type.is_simple:
2463 f.write('%s %s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2464 create_link('%s' % field.c_accessor_name)
2466 f.write('%s *%s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2467 create_link('%s' % field.c_accessor_name)
2469 def _c_accessors_list(self, field):
2471 Declares the accessor functions for a list field.
2472 Declares a direct-accessor function only if the list members are fixed size.
2473 Declares length and get-iterator functions always.
2476 c_type = self.reply.c_type
2478 # special case: switch
2479 # in case of switch, 2 params have to be supplied to certain accessor functions:
2480 # 1. the anchestor object (request or reply)
2481 # 2. the (anchestor) switch object
2482 # the reason is that switch is either a child of a request/reply or nested in another switch,
2483 # so whenever we need to access a length field, we might need to refer to some anchestor type
2484 switch_obj = self if self.is_switch else None
2486 switch_obj = self.parents[-1]
2487 if switch_obj is not None:
2488 c_type = switch_obj.c_type
2492 parents = self.parents if hasattr(self, 'parents') else [self]
2493 # 'R': parents[0] is always the 'toplevel' container type
2494 params.append(('const %s *\\fIreply\\fP' % parents[0].c_type, parents[0]))
2495 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
2496 # auxiliary object for 'R' parameters
2499 if switch_obj is not None:
2500 # now look where the fields are defined that are needed to evaluate
2501 # the switch expr, and store the parent objects in accessor_params and
2502 # the fields in switch_fields
2504 # 'S': name for the 'toplevel' switch
2505 toplevel_switch = parents[1]
2506 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
2507 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
2509 # initialize prefix for everything "below" S
2510 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
2511 prefix = [(prefix_str, '->', toplevel_switch)]
2513 # look for fields in the remaining containers
2514 for p in parents[2:] + [self]:
2515 # the separator between parent and child is always '.' here,
2516 # because of nested switch statements
2517 if not p.is_bitcase or (p.is_bitcase and p.has_name):
2518 prefix.append((p.name[-1], '.', p))
2519 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
2521 # auxiliary object for 'S' parameter
2524 if list.member.fixed_size():
2525 idx = 1 if switch_obj is not None else 0
2527 f.write('%s *\\fB%s\\fP(%s);\n' %
2528 (field.c_field_type, field.c_accessor_name, params[idx][0]))
2529 create_link('%s' % field.c_accessor_name)
2532 f.write('int \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2533 (field.c_length_name, c_type))
2534 create_link('%s' % field.c_length_name)
2536 if field.type.member.is_simple:
2538 f.write('xcb_generic_iterator_t \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2539 (field.c_end_name, c_type))
2540 create_link('%s' % field.c_end_name)
2543 f.write('%s \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2544 (field.c_iterator_type, field.c_iterator_name,
2546 create_link('%s' % field.c_iterator_name)
2548 for field in self.reply.fields:
2549 if field.type.is_list and not field.type.fixed_size():
2550 _c_accessors_list(self, field)
2551 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2552 _c_accessors_field(self, field)
2556 # Re-enable hyphenation and adjusting to both sides
2559 # argument reference
2560 f.write('.SH REQUEST ARGUMENTS\n')
2561 f.write('.IP \\fI%s\\fP 1i\n' % 'conn')
2562 f.write('The XCB connection to X11.\n')
2563 for field in param_fields:
2564 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2565 printed_enum = False
2566 # XXX: hard-coded until we fix xproto.xml
2567 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
2569 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
2571 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
2573 if hasattr(field, "enum") and field.enum:
2574 # XXX: why the 'xcb' prefix?
2575 key = ('xcb', field.enum)
2577 f.write('One of the following values:\n')
2580 count = len(enum.values)
2581 for (enam, eval) in enum.values:
2583 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2584 if hasattr(enum, "doc") and enum.doc and enam in enum.doc.fields:
2585 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2586 f.write('%s\n' % desc)
2588 f.write('TODO: NOT YET DOCUMENTED.\n')
2593 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2594 desc = self.doc.fields[field.field_name]
2595 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2598 f.write('%s\n' % desc)
2600 f.write('TODO: NOT YET DOCUMENTED.\n')
2606 f.write('.SH REPLY FIELDS\n')
2607 # These fields are present in every reply:
2608 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2609 f.write(('The type of this reply, in this case \\fI%s\\fP. This field '
2610 'is also present in the \\fIxcb_generic_reply_t\\fP and can '
2611 'be used to tell replies apart from each other.\n') %
2612 _n(self.reply.name).upper())
2613 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2614 f.write('The sequence number of the last request processed by the X11 server.\n')
2615 f.write('.IP \\fI%s\\fP 1i\n' % 'length')
2616 f.write('The length of the reply, in words (a word is 4 bytes).\n')
2617 for field in self.reply.fields:
2618 if (field.c_field_name in frozenset(['response_type', 'sequence', 'length']) or
2619 field.c_field_name.startswith('pad')):
2622 if field.type.is_list and not field.type.fixed_size():
2624 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2626 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2627 printed_enum = False
2628 if hasattr(field, "enum") and field.enum:
2629 # XXX: why the 'xcb' prefix?
2630 key = ('xcb', field.enum)
2632 f.write('One of the following values:\n')
2635 count = len(enum.values)
2636 for (enam, eval) in enum.values:
2638 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2639 if enum.doc and enam in enum.doc.fields:
2640 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2641 f.write('%s\n' % desc)
2643 f.write('TODO: NOT YET DOCUMENTED.\n')
2648 if hasattr(self.reply, "doc") and self.reply.doc and field.field_name in self.reply.doc.fields:
2649 desc = self.reply.doc.fields[field.field_name]
2650 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2653 f.write('%s\n' % desc)
2655 f.write('TODO: NOT YET DOCUMENTED.\n')
2662 f.write('.SH DESCRIPTION\n')
2663 if hasattr(self, "doc") and self.doc and self.doc.description:
2664 desc = self.doc.description
2665 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2666 lines = desc.split('\n')
2667 f.write('\n'.join(lines) + '\n')
2669 f.write('.SH RETURN VALUE\n')
2671 f.write(('Returns an \\fIxcb_void_cookie_t\\fP. Errors (if any) '
2672 'have to be handled in the event loop.\n\nIf you want to '
2673 'handle errors directly with \\fIxcb_request_check\\fP '
2674 'instead, use \\fI%s_checked\\fP. See '
2675 '\\fBxcb-requests(3)\\fP for details.\n') % (base_func_name))
2677 f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
2678 'calling the reply function \\fI%s\\fP.\n\nIf you want to '
2679 'handle errors in the event loop instead, use '
2680 '\\fI%s_unchecked\\fP. See \\fBxcb-requests(3)\\fP for '
2682 (cookie_type, self.c_reply_name, base_func_name))
2683 f.write('.SH ERRORS\n')
2684 if hasattr(self, "doc") and self.doc:
2685 for errtype, errtext in self.doc.errors.items():
2686 f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
2687 errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
2688 f.write('%s\n' % (errtext))
2689 if not hasattr(self, "doc") or not self.doc or len(self.doc.errors) == 0:
2690 f.write('This request does never generate any errors.\n')
2691 if hasattr(self, "doc") and self.doc and self.doc.example:
2692 f.write('.SH EXAMPLE\n')
2695 lines = self.doc.example.split('\n')
2696 f.write('\n'.join(lines) + '\n')
2698 f.write('.SH SEE ALSO\n')
2699 if hasattr(self, "doc") and self.doc:
2700 see = ['.BR %s (3)' % 'xcb-requests']
2701 if self.doc.example:
2702 see.append('.BR %s (3)' % 'xcb-examples')
2703 for seename, seetype in self.doc.see.items():
2704 if seetype == 'program':
2705 see.append('.BR %s (1)' % seename)
2706 elif seetype == 'event':
2707 see.append('.BR %s (3)' % _t(('xcb', seename, 'event')))
2708 elif seetype == 'request':
2709 see.append('.BR %s (3)' % _n(('xcb', seename)))
2710 elif seetype == 'function':
2711 see.append('.BR %s (3)' % seename)
2713 see.append('TODO: %s (type %s)' % (seename, seetype))
2714 f.write(',\n'.join(see) + '\n')
2715 f.write('.SH AUTHOR\n')
2716 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2719 def _man_event(self, name):
2721 sys.stdout.write('man/%s.3 ' % self.c_type)
2722 # Our CWD is src/, so this will end up in src/man/
2723 f = open('man/%s.3' % self.c_type, 'w')
2724 f.write('.TH %s 3 %s "XCB" "XCB Events"\n' % (self.c_type, today))
2725 # Left-adjust instead of adjusting to both sides
2727 f.write('.SH NAME\n')
2728 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2729 f.write('%s \\- %s\n' % (self.c_type, brief))
2730 f.write('.SH SYNOPSIS\n')
2731 # Don't split words (hyphenate)
2733 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2736 f.write('.SS Event datastructure\n')
2739 f.write('typedef %s %s {\n' % (self.c_container, self.c_type))
2743 for field in self.fields:
2744 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2747 struct_fields.append(field)
2749 for field in struct_fields:
2750 length = len(field.c_field_type)
2751 # account for '*' pointer_spec
2752 if not field.type.fixed_size():
2754 maxtypelen = max(maxtypelen, length)
2756 def _c_complex_field(self, field, space=''):
2757 if (field.type.fixed_size() or
2758 # in case of switch with switch children, don't make the field a pointer
2759 # necessary for unserialize to work
2760 (self.is_switch and field.type.is_switch)):
2761 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2762 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2764 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2766 if not self.is_switch:
2767 for field in struct_fields:
2768 _c_complex_field(self, field)
2770 for b in self.bitcases:
2774 for field in b.type.fields:
2775 _c_complex_field(self, field, space)
2777 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2780 f.write('} \\fB%s\\fP;\n' % self.c_type)
2785 # Re-enable hyphenation and adjusting to both sides
2788 # argument reference
2789 f.write('.SH EVENT FIELDS\n')
2790 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2791 f.write(('The type of this event, in this case \\fI%s\\fP. This field is '
2792 'also present in the \\fIxcb_generic_event_t\\fP and can be used '
2793 'to tell events apart from each other.\n') % _n(name).upper())
2794 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2795 f.write('The sequence number of the last request processed by the X11 server.\n')
2797 if not self.is_switch:
2798 for field in struct_fields:
2799 # Skip the fields which every event has, we already documented
2801 if field.c_field_name in ('response_type', 'sequence'):
2803 if isinstance(field.type, PadType):
2805 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2806 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2807 desc = self.doc.fields[field.field_name]
2808 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2809 f.write('%s\n' % desc)
2811 f.write('NOT YET DOCUMENTED.\n')
2814 f.write('.SH DESCRIPTION\n')
2815 if hasattr(self, "doc") and self.doc and self.doc.description:
2816 desc = self.doc.description
2817 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2818 lines = desc.split('\n')
2819 f.write('\n'.join(lines) + '\n')
2821 if hasattr(self, "doc") and self.doc and self.doc.example:
2822 f.write('.SH EXAMPLE\n')
2825 lines = self.doc.example.split('\n')
2826 f.write('\n'.join(lines) + '\n')
2828 f.write('.SH SEE ALSO\n')
2829 if hasattr(self, "doc") and self.doc:
2830 see = ['.BR %s (3)' % 'xcb_generic_event_t']
2831 if self.doc.example:
2832 see.append('.BR %s (3)' % 'xcb-examples')
2833 for seename, seetype in self.doc.see.items():
2834 if seetype == 'program':
2835 see.append('.BR %s (1)' % seename)
2836 elif seetype == 'event':
2837 see.append('.BR %s (3)' % _t(('xcb', seename, 'event')))
2838 elif seetype == 'request':
2839 see.append('.BR %s (3)' % _n(('xcb', seename)))
2840 elif seetype == 'function':
2841 see.append('.BR %s (3)' % seename)
2843 see.append('TODO: %s (type %s)' % (seename, seetype))
2844 f.write(',\n'.join(see) + '\n')
2845 f.write('.SH AUTHOR\n')
2846 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2850 def c_request(self, name):
2852 Exported function that handles request declarations.
2854 _c_type_setup(self, name, ('request',))
2857 # Cookie type declaration
2858 _c_cookie(self, name)
2861 _c_opcode(name, self.opcode)
2863 # Request structure declaration
2867 _c_type_setup(self.reply, name, ('reply',))
2868 # Reply structure definition
2869 _c_complex(self.reply)
2870 # Request prototypes
2871 has_fds = _c_reply_has_fds(self.reply)
2872 _c_request_helper(self, name, self.c_cookie_type, False, True, False, has_fds)
2873 _c_request_helper(self, name, self.c_cookie_type, False, False, False, has_fds)
2875 _c_request_helper(self, name, self.c_cookie_type, False, True, True, has_fds)
2876 _c_request_helper(self, name, self.c_cookie_type, False, False, True, has_fds)
2878 _c_accessors(self.reply, name + ('reply',), name)
2879 _c_reply(self, name)
2881 _c_reply_fds(self, name)
2883 # Request prototypes
2884 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2885 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2887 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2888 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2890 # We generate the manpage afterwards because _c_type_setup has been called.
2891 # TODO: what about aux helpers?
2892 cookie_type = self.c_cookie_type if self.reply else 'xcb_void_cookie_t'
2893 _man_request(self, name, cookie_type, not self.reply, False)
2895 def c_event(self, name):
2897 Exported function that handles event declarations.
2900 # The generic event structure xcb_ge_event_t has the full_sequence field
2901 # at the 32byte boundary. That's why we've to inject this field into GE
2902 # events while generating the structure for them. Otherwise we would read
2903 # garbage (the internal full_sequence) when accessing normal event fields
2905 if hasattr(self, 'is_ge_event') and self.is_ge_event and self.name == name:
2907 for field in self.fields:
2908 if field.type.size != None and field.type.nmemb != None:
2909 event_size += field.type.size * field.type.nmemb
2910 if event_size == 32:
2911 full_sequence = Field(tcard32, tcard32.name, 'full_sequence', False, True, True)
2912 idx = self.fields.index(field)
2913 self.fields.insert(idx + 1, full_sequence)
2916 _c_type_setup(self, name, ('event',))
2919 _c_opcode(name, self.opcodes[name])
2921 if self.name == name:
2922 # Structure definition
2927 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2929 _man_event(self, name)
2931 def c_error(self, name):
2933 Exported function that handles error declarations.
2935 _c_type_setup(self, name, ('error',))
2938 _c_opcode(name, self.opcodes[name])
2940 if self.name == name:
2941 # Structure definition
2946 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2949 # Main routine starts here
2951 # Must create an "output" dictionary before any xcbgen imports.
2952 output = {'open' : c_open,
2954 'simple' : c_simple,
2956 'struct' : c_struct,
2958 'request' : c_request,
2963 # Boilerplate below this point
2965 # Check for the argument that specifies path to the xcbgen python package.
2967 opts, args = getopt.getopt(sys.argv[1:], 'p:m')
2968 except getopt.GetoptError as err:
2970 print('Usage: c_client.py [-p path] file.xml')
2973 for (opt, arg) in opts:
2975 sys.path.insert(1, arg)
2978 sys.stdout.write('man_MANS = ')
2980 # Import the module class
2982 from xcbgen.state import Module
2983 from xcbgen.xtypes import *
2986 Failed to load the xcbgen Python package!
2987 Make sure that xcb/proto installed it on your Python path.
2988 If not, you will need to create a .pth file or define $PYTHONPATH
2990 Refer to the README file in xcb/proto for more info.
2994 # Ensure the man subdirectory exists
2997 except OSError as e:
2998 if e.errno != errno.EEXIST:
3001 today = time.strftime('%Y-%m-%d', time.gmtime(os.path.getmtime(args[0])))
3003 # Parse the xml header
3004 module = Module(args[0], output)
3006 # Build type-registry and resolve type dependencies