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('#include <stdlib.h>')
180 _c('#include <string.h>')
181 _c('#include <assert.h>')
182 _c('#include <stddef.h> /* for offsetof() */')
183 _c('#include "xcbext.h"')
184 _c('#include "%s.h"', _ns.header)
187 _c('#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)')
190 for (n, h) in self.imports:
191 _hc('#include "%s.h"', h)
194 _h('#ifdef __cplusplus')
200 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
201 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
203 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
206 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
210 Exported function that handles module close.
211 Writes out all the stored content lines, then closes the files.
218 _h('#ifdef __cplusplus')
230 hfile = open('%s.h' % _ns.header, 'w')
238 cfile = open('%s.c' % _ns.header, 'w')
245 def build_collision_table():
249 for v in module.types.values():
251 namecount[name] = (namecount.get(name) or 0) + 1
253 def c_enum(self, name):
255 Exported function that handles enum declarations.
261 if namecount[tname] > 1:
262 tname = _t(name + ('enum',))
266 _h('typedef enum %s {', tname)
268 count = len(self.values)
270 for (enam, eval) in self.values:
272 equals = ' = ' if eval != '' else ''
273 comma = ',' if count > 0 else ''
275 if hasattr(self, "doc") and self.doc and enam in self.doc.fields:
276 doc = '\n/**< %s */\n' % self.doc.fields[enam]
277 _h(' %s%s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma, doc)
281 def _c_type_setup(self, name, postfix):
283 Sets up all the C-related state by adding additional data fields to
284 all Field and Type objects. Here is where we figure out most of our
285 variable and function names.
287 Recurses into child fields and list member types.
289 # Do all the various names in advance
290 self.c_type = _t(name + postfix)
291 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
293 self.c_iterator_type = _t(name + ('iterator',))
294 self.c_next_name = _n(name + ('next',))
295 self.c_end_name = _n(name + ('end',))
297 self.c_request_name = _n(name)
298 self.c_checked_name = _n(name + ('checked',))
299 self.c_unchecked_name = _n(name + ('unchecked',))
300 self.c_reply_name = _n(name + ('reply',))
301 self.c_reply_type = _t(name + ('reply',))
302 self.c_cookie_type = _t(name + ('cookie',))
304 self.need_aux = False
305 self.need_serialize = False
306 self.need_sizeof = False
308 self.c_aux_name = _n(name + ('aux',))
309 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
310 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
311 self.c_serialize_name = _n(name + ('serialize',))
312 self.c_unserialize_name = _n(name + ('unserialize',))
313 self.c_unpack_name = _n(name + ('unpack',))
314 self.c_sizeof_name = _n(name + ('sizeof',))
316 # special case: structs where variable size fields are followed by fixed size fields
317 self.var_followed_by_fixed_fields = False
320 self.need_serialize = True
321 self.c_container = 'struct'
322 for bitcase in self.bitcases:
323 bitcase.c_field_name = _cpp(bitcase.field_name)
324 bitcase_name = bitcase.field_type if bitcase.type.has_name else name
325 _c_type_setup(bitcase.type, bitcase_name, ())
327 elif self.is_container:
329 self.c_container = 'union' if self.is_union else 'struct'
330 prev_varsized_field = None
331 prev_varsized_offset = 0
332 first_field_after_varsized = None
334 for field in self.fields:
335 _c_type_setup(field.type, field.field_type, ())
336 if field.type.is_list:
337 _c_type_setup(field.type.member, field.field_type, ())
338 if (field.type.nmemb is None):
339 self.need_sizeof = True
341 field.c_field_type = _t(field.field_type)
342 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
343 field.c_field_name = _cpp(field.field_name)
344 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb and field.type.nmemb > 1) else ''
345 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
347 # correct the c_pointer field for variable size non-list types
348 if not field.type.fixed_size() and field.c_pointer == ' ':
349 field.c_pointer = '*'
350 if field.type.is_list and not field.type.member.fixed_size():
351 field.c_pointer = '*'
353 if field.type.is_switch:
354 field.c_pointer = '*'
355 field.c_field_const_type = 'const ' + field.c_field_type
357 elif not field.type.fixed_size() and not field.type.is_bitcase:
358 self.need_sizeof = True
360 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
361 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
362 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
363 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
364 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
366 field.prev_varsized_field = prev_varsized_field
367 field.prev_varsized_offset = prev_varsized_offset
369 if prev_varsized_offset == 0:
370 first_field_after_varsized = field
371 field.first_field_after_varsized = first_field_after_varsized
373 if field.type.fixed_size():
374 prev_varsized_offset += field.type.size
375 # special case: intermixed fixed and variable size fields
376 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
377 if not self.is_union:
378 self.need_serialize = True
379 self.var_followed_by_fixed_fields = True
381 self.last_varsized_field = field
382 prev_varsized_field = field
383 prev_varsized_offset = 0
385 if self.var_followed_by_fixed_fields:
386 if field.type.fixed_size():
387 field.prev_varsized_field = None
389 if self.need_serialize:
390 # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
391 self.need_sizeof = True
393 # as switch does never appear at toplevel,
394 # continue here with type construction
396 if self.c_type not in finished_switch:
397 finished_switch.append(self.c_type)
398 # special: switch C structs get pointer fields for variable-sized members
400 for bitcase in self.bitcases:
401 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
402 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
403 # no list with switch as element, so no call to
404 # _c_iterator(field.type, field_name) necessary
406 if not self.is_bitcase:
407 if self.need_serialize:
408 if self.c_serialize_name not in finished_serializers:
409 finished_serializers.append(self.c_serialize_name)
410 _c_serialize('serialize', self)
412 # _unpack() and _unserialize() are only needed for special cases:
414 # special cases -> unserialize
415 if self.is_switch or self.var_followed_by_fixed_fields:
416 _c_serialize('unserialize', self)
419 if self.c_sizeof_name not in finished_sizeof:
420 if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
421 finished_sizeof.append(self.c_sizeof_name)
422 _c_serialize('sizeof', self)
425 def _c_helper_absolute_name(prefix, field=None):
427 turn prefix, which is a list of tuples (name, separator, Type obj) into a string
428 representing a valid name in C (based on the context)
429 if field is not None, append the field name as well
432 for name, sep, obj in prefix:
436 if ((obj.is_bitcase and obj.has_name) or # named bitcase
437 (obj.is_switch and len(obj.parents)>1)):
440 if field is not None:
441 prefix_str += _cpp(field.field_name)
445 def _c_helper_field_mapping(complex_type, prefix, flat=False):
447 generate absolute names, based on prefix, for all fields starting from complex_type
448 if flat == True, nested complex types are not taken into account
451 if complex_type.is_switch:
452 for b in complex_type.bitcases:
454 switch_name, switch_sep, switch_type = prefix[-1]
455 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
457 bitcase_prefix = prefix
459 if (True==flat and not b.type.has_name) or False==flat:
460 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
462 for f in complex_type.fields:
463 fname = _c_helper_absolute_name(prefix, f)
464 if f.field_name in all_fields:
465 raise Exception("field name %s has been registered before" % f.field_name)
467 all_fields[f.field_name] = (fname, f)
468 if f.type.is_container and flat==False:
469 if f.type.is_bitcase and not f.type.has_name:
471 elif f.type.is_switch and len(f.type.parents)>1:
472 # nested switch gets another separator
473 new_prefix = prefix+[(f.c_field_name, '.', f.type)]
475 new_prefix = prefix+[(f.c_field_name, '->', f.type)]
476 all_fields.update(_c_helper_field_mapping(f.type, new_prefix, flat))
481 def _c_helper_resolve_field_names (prefix):
483 get field names for all objects in the prefix array
487 # look for fields in the remaining containers
488 for idx, p in enumerate(prefix):
491 # sep can be preset in prefix, if not, make a sensible guess
492 sep = '.' if (obj.is_switch or obj.is_bitcase) else '->'
493 # exception: 'toplevel' object (switch as well!) always have sep '->'
494 sep = '->' if idx<1 else sep
495 if not obj.is_bitcase or (obj.is_bitcase and obj.has_name):
496 tmp_prefix.append((name, sep, obj))
497 all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
500 # _c_helper_resolve_field_names
502 def get_expr_fields(self):
504 get the Fields referenced by switch or list expression
506 def get_expr_field_names(expr):
508 if expr.lenfield_name is not None:
509 return [expr.lenfield_name]
511 # constant value expr
515 return get_expr_field_names(expr.rhs)
516 elif expr.op == 'popcount':
517 return get_expr_field_names(expr.rhs)
518 elif expr.op == 'sumof':
519 # sumof expr references another list,
520 # we need that list's length field here
522 for f in expr.lenfield_parent.fields:
523 if f.field_name == expr.lenfield_name:
527 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
528 # referenced list + its length field
529 return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
530 elif expr.op == 'enumref':
533 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
534 # get_expr_field_names()
536 # resolve the field names with the parent structure(s)
537 unresolved_fields_names = get_expr_field_names(self.expr)
539 # construct prefix from self
540 prefix = [('', '', p) for p in self.parents]
541 if self.is_container:
542 prefix.append(('', '', self))
544 all_fields = _c_helper_resolve_field_names (prefix)
545 resolved_fields_names = list(filter(lambda x: x in all_fields.keys(), unresolved_fields_names))
546 if len(unresolved_fields_names) != len(resolved_fields_names):
547 raise Exception("could not resolve all fields for %s" % self.name)
549 resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
550 return resolved_fields
553 def resolve_expr_fields(complex_obj):
555 find expr fields appearing in complex_obj and descendents that cannot be resolved within complex_obj
556 these are normally fields that need to be given as function parameters
562 for field in complex_obj.fields:
563 all_fields.append(field)
564 if field.type.is_switch or field.type.is_list:
565 expr_fields += get_expr_fields(field.type)
566 if field.type.is_container:
567 expr_fields += resolve_expr_fields(field.type)
569 # try to resolve expr fields
570 for e in expr_fields:
571 if e not in all_fields and e not in unresolved:
574 # resolve_expr_fields()
576 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
578 functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
579 E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch
580 expression. This function tries to resolve all fields within a structure, and returns the
581 unresolved fields as the list of external parameters.
583 def add_param(params, param):
584 if param not in params:
587 # collect all fields into param_fields
591 for field in self.fields:
593 # the field should appear as a parameter in the function call
594 param_fields.append(field)
595 if field.wire and not field.auto:
596 if field.type.fixed_size() and not self.is_switch:
597 # field in the xcb_out structure
598 wire_fields.append(field)
599 # fields like 'pad0' are skipped!
601 # in case of switch, parameters always contain any fields referenced in the switch expr
602 # we do not need any variable size fields here, as the switch data type contains both
603 # fixed and variable size fields
605 param_fields = get_expr_fields(self)
607 # _serialize()/_unserialize()/_unpack() function parameters
608 # note: don't use set() for params, it is unsorted
611 # 1. the parameter for the void * buffer
612 if 'serialize' == context:
613 params.append(('void', '**', buffer_var))
614 elif context in ('unserialize', 'unpack', 'sizeof'):
615 params.append(('const void', '*', buffer_var))
617 # 2. any expr fields that cannot be resolved within self and descendants
618 unresolved_fields = resolve_expr_fields(self)
619 for f in unresolved_fields:
620 add_param(params, (f.c_field_type, '', f.c_field_name))
622 # 3. param_fields contain the fields necessary to evaluate the switch expr or any other fields
623 # that do not appear in the data type struct
624 for p in param_fields:
626 typespec = p.c_field_const_type
627 pointerspec = p.c_pointer
628 add_param(params, (typespec, pointerspec, p.c_field_name))
630 if p.visible and not p.wire and not p.auto:
631 typespec = p.c_field_type
633 add_param(params, (typespec, pointerspec, p.c_field_name))
636 if 'serialize' == context:
637 add_param(params, ('const %s' % self.c_type, '*', aux_var))
638 elif 'unserialize' == context:
639 add_param(params, ('%s' % self.c_type, '**', aux_var))
640 elif 'unpack' == context:
641 add_param(params, ('%s' % self.c_type, '*', aux_var))
643 # 5. switch contains all variable size fields as struct members
644 # for other data types though, these have to be supplied separately
645 # this is important for the special case of intermixed fixed and
646 # variable size fields
647 if not self.is_switch and 'serialize' == context:
648 for p in param_fields:
649 if not p.type.fixed_size():
650 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
652 return (param_fields, wire_fields, params)
653 # get_serialize_params()
655 def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
656 code_lines.append('%s /* insert padding */' % space)
657 code_lines.append('%s xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
658 # code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
659 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
662 code_lines.append('%s if (0 != xcb_pad) {' % space)
664 if 'serialize' == context:
665 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
666 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
667 code_lines.append('%s xcb_parts_idx++;' % space)
668 elif context in ('unserialize', 'unpack', 'sizeof'):
669 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
671 code_lines.append('%s xcb_pad = 0;' % space)
672 code_lines.append('%s }' % space)
674 code_lines.append('%s xcb_block_len = 0;' % space)
676 # keep tracking of xcb_parts entries for serialize
678 # _c_serialize_helper_insert_padding()
680 def _c_serialize_helper_switch(context, self, complex_name,
681 code_lines, temp_vars,
684 switch_expr = _c_accessor_get_expr(self.expr, None)
686 for b in self.bitcases:
687 bitcase_expr = _c_accessor_get_expr(b.type.expr, None)
688 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
689 # code_lines.append(' printf("switch %s: entering bitcase section %s (mask=%%%%d)...\\n", %s);' %
690 # (self.name[-1], b.type.name[-1], bitcase_expr))
693 b_prefix = prefix + [(b.c_field_name, '.', b.type)]
695 count += _c_serialize_helper_fields(context, b.type,
696 code_lines, temp_vars,
700 code_lines.append(' }')
702 # if 'serialize' == context:
703 # count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
704 # elif context in ('unserialize', 'unpack', 'sizeof'):
706 # code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
707 # code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
710 # _c_serialize_helper_switch
712 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
714 handle switch by calling _serialize() or _unpack(), depending on context
716 # switch is handled by this function as a special case
717 param_fields, wire_fields, params = get_serialize_params(context, self)
718 field_mapping = _c_helper_field_mapping(self, prefix)
719 prefix_str = _c_helper_absolute_name(prefix)
721 # find the parameters that need to be passed to _serialize()/_unpack():
722 # all switch expr fields must be given as parameters
723 args = get_expr_fields(field.type)
724 # length fields for variable size types in switch, normally only some of need
725 # need to be passed as parameters
726 switch_len_fields = resolve_expr_fields(field.type)
728 # a switch field at this point _must_ be a bitcase field
729 # we require that bitcases are "self-contiguous"
730 bitcase_unresolved = resolve_expr_fields(self)
731 if len(bitcase_unresolved) != 0:
732 raise Exception('unresolved fields within bitcase is not supported at this point')
734 # get the C names for the parameters
736 for a in switch_len_fields:
737 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
739 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
741 # call _serialize()/_unpack() to determine the actual size
742 if 'serialize' == context:
743 length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
744 c_field_names, prefix_str, field.c_field_name)
745 elif context in ('unserialize', 'unpack'):
746 length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
747 c_field_names, prefix_str, field.c_field_name)
750 # _c_serialize_helper_switch_field()
752 def _c_serialize_helper_list_field(context, self, field,
753 code_lines, temp_vars,
756 helper function to cope with lists of variable length
758 expr = field.type.expr
759 prefix_str = _c_helper_absolute_name(prefix)
760 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
761 param_names = [p[2] for p in params]
763 expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
764 resolved = list(filter(lambda x: x in param_names, expr_fields_names))
765 unresolved = list(filter(lambda x: x not in param_names, expr_fields_names))
769 field_mapping[r] = (r, None)
771 if len(unresolved)>0:
773 if len(tmp_prefix)==0:
774 raise Exception("found an empty prefix while resolving expr field names for list %s",
777 field_mapping.update(_c_helper_resolve_field_names(prefix))
778 resolved += list(filter(lambda x: x in field_mapping, unresolved))
779 unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
780 if len(unresolved)>0:
781 raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
783 list_length = _c_accessor_get_expr(expr, field_mapping)
785 # default: list with fixed size elements
786 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
788 # list with variable-sized elements
789 if not field.type.member.fixed_size():
791 if context in ('unserialize', 'sizeof', 'unpack'):
792 int_i = ' unsigned int i;'
793 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
794 if int_i not in temp_vars:
795 temp_vars.append(int_i)
796 if xcb_tmp_len not in temp_vars:
797 temp_vars.append(xcb_tmp_len)
798 # loop over all list elements and call sizeof repeatedly
799 # this should be a bit faster than using the iterators
800 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
801 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
802 (space, field.type.c_sizeof_name))
803 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
804 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
805 code_lines.append("%s }" % space)
807 elif 'serialize' == context:
808 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
809 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
810 code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length))
811 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
812 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
813 code_lines.append('%s }' % space)
814 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
817 # _c_serialize_helper_list_field()
819 def _c_serialize_helper_fields_fixed_size(context, self, field,
820 code_lines, temp_vars,
822 # keep the C code a bit more readable by giving the field name
823 if not self.is_bitcase:
824 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
826 scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
827 typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
828 code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
830 abs_field_name = _c_helper_absolute_name(prefix, field)
831 # default for simple cases: call sizeof()
832 length = "sizeof(%s)" % field.c_field_type
834 if context in ('unserialize', 'unpack', 'sizeof'):
835 # default: simple cast
836 value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
838 # padding - we could probably just ignore it
839 if field.type.is_pad and field.type.nmemb > 1:
841 for i in range(field.type.nmemb):
842 code_lines.append('%s %s[%d] = *(%s *)xcb_tmp;' %
843 (space, abs_field_name, i, field.c_field_type))
844 # total padding = sizeof(pad0) * nmemb
845 length += " * %d" % field.type.nmemb
847 if field.type.is_list:
848 # no such case in the protocol, cannot be tested and therefore ignored for now
849 raise Exception('list with fixed number of elemens unhandled in _unserialize()')
851 elif 'serialize' == context:
852 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
854 if field.type.is_expr:
855 # need to register a temporary variable for the expression in case we know its type
856 if field.type.c_type is None:
857 raise Exception("type for field '%s' (expression '%s') unkown" %
858 (field.field_name, _c_accessor_get_expr(field.type.expr)))
860 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
861 _c_accessor_get_expr(field.type.expr, prefix)))
862 value += "&xcb_expr_%s;" % _cpp(field.field_name)
864 elif field.type.is_pad:
865 if field.type.nmemb == 1:
868 # we could also set it to 0, see definition of xcb_send_request()
869 value = ' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
870 length += "*%d" % field.type.nmemb
873 # non-list type with fixed size
874 if field.type.nmemb == 1:
875 value += "&%s;" % (abs_field_name)
877 # list with nmemb (fixed size) elements
879 value += '%s;' % (abs_field_name)
880 length = '%d' % field.type.nmemb
882 return (value, length)
883 # _c_serialize_helper_fields_fixed_size()
885 def _c_serialize_helper_fields_variable_size(context, self, field,
886 code_lines, temp_vars,
888 prefix_str = _c_helper_absolute_name(prefix)
890 if context in ('unserialize', 'unpack', 'sizeof'):
892 var_field_name = 'xcb_tmp'
894 # special case: intermixed fixed and variable size fields
895 if self.var_followed_by_fixed_fields and 'unserialize' == context:
896 value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
897 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
898 # special case: switch
899 if 'unpack' == context:
900 value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
902 elif 'serialize' == context:
903 # variable size fields appear as parameters to _serialize() if the
904 # 'toplevel' container is not a switch
905 prefix_string = prefix_str if prefix[0][2].is_switch else ''
906 var_field_name = "%s%s" % (prefix_string, field.c_field_name)
907 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
911 code_lines.append('%s /* %s */' % (space, field.c_field_name))
913 if field.type.is_list:
915 # in any context, list is already a pointer, so the default assignment is ok
916 code_lines.append("%s%s" % (space, value))
918 length = _c_serialize_helper_list_field(context, self, field,
919 code_lines, temp_vars,
922 elif field.type.is_switch:
924 if context == 'serialize':
925 # the _serialize() function allocates the correct amount memory if given a NULL pointer
926 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
927 length = _c_serialize_helper_switch_field(context, self, field,
928 'xcb_parts[xcb_parts_idx].iov_base',
932 # in all remaining special cases - call _sizeof()
933 length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
935 return (value, length)
936 # _c_serialize_helper_fields_variable_size
938 def _c_serialize_helper_fields(context, self,
939 code_lines, temp_vars,
940 space, prefix, is_bitcase):
943 prev_field_was_variable = False
945 for field in self.fields:
946 if not field.visible:
947 if not ((field.wire and not field.auto) or 'unserialize' == context):
950 # switch/bitcase: fixed size fields must be considered explicitly
951 if field.type.fixed_size():
952 if self.is_bitcase or self.var_followed_by_fixed_fields:
953 if prev_field_was_variable and need_padding:
955 # count += _c_serialize_helper_insert_padding(context, code_lines, space,
956 # self.var_followed_by_fixed_fields)
957 prev_field_was_variable = False
959 # prefix for fixed size fields
960 fixed_prefix = prefix
962 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
963 code_lines, temp_vars,
968 # fields with variable size
970 # switch/bitcase: always calculate padding before and after variable sized fields
971 if need_padding or is_bitcase:
972 count += _c_serialize_helper_insert_padding(context, code_lines, space,
973 self.var_followed_by_fixed_fields)
975 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
976 code_lines, temp_vars,
978 prev_field_was_variable = True
980 # save (un)serialization C code
982 code_lines.append('%s%s' % (space, value))
984 if field.type.fixed_size():
985 if is_bitcase or self.var_followed_by_fixed_fields:
986 # keep track of (un)serialized object's size
987 code_lines.append('%s xcb_block_len += %s;' % (space, length))
988 if context in ('unserialize', 'unpack', 'sizeof'):
989 code_lines.append('%s xcb_tmp += %s;' % (space, length))
991 # variable size objects or bitcase:
992 # value & length might have been inserted earlier for special cases
994 # special case: intermixed fixed and variable size fields
995 if (not field.type.fixed_size() and
996 self.var_followed_by_fixed_fields and 'unserialize' == context):
997 temp_vars.append(' int %s_len;' % field.c_field_name)
998 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
999 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
1000 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
1002 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1003 # increase pointer into the byte stream accordingly
1004 if context in ('unserialize', 'sizeof', 'unpack'):
1005 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1007 if 'serialize' == context:
1009 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
1010 code_lines.append('%s xcb_parts_idx++;' % space)
1013 code_lines.append('%s xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type))
1016 if self.var_followed_by_fixed_fields:
1017 need_padding = False
1020 # _c_serialize_helper_fields()
1022 def _c_serialize_helper(context, complex_type,
1023 code_lines, temp_vars,
1024 space='', prefix=[]):
1025 # count tracks the number of fields to serialize
1028 if hasattr(complex_type, 'type'):
1029 self = complex_type.type
1030 complex_name = complex_type.name
1033 if self.var_followed_by_fixed_fields and 'unserialize' == context:
1034 complex_name = 'xcb_out'
1036 complex_name = '_aux'
1038 # special case: switch is serialized by evaluating each bitcase separately
1040 count += _c_serialize_helper_switch(context, self, complex_name,
1041 code_lines, temp_vars,
1044 # all other data types can be evaluated one field a time
1046 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1047 if context in ('unserialize', 'unpack', 'sizeof') and not self.var_followed_by_fixed_fields:
1048 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1049 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1050 # probably not needed
1051 #_c_serialize_helper_insert_padding(context, code_lines, space, False)
1053 count += _c_serialize_helper_fields(context, self,
1054 code_lines, temp_vars,
1055 space, prefix, False)
1057 count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
1060 # _c_serialize_helper()
1062 def _c_serialize(context, self):
1064 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1065 for the ComplexType variable self
1071 # _serialize() returns the buffer size
1074 if self.is_switch and 'unserialize' == context:
1077 cases = { 'serialize' : self.c_serialize_name,
1078 'unserialize' : self.c_unserialize_name,
1079 'unpack' : self.c_unpack_name,
1080 'sizeof' : self.c_sizeof_name }
1081 func_name = cases[context]
1083 param_fields, wire_fields, params = get_serialize_params(context, self)
1084 variable_size_fields = 0
1085 # maximum space required for type definition of function arguments
1088 # determine N(variable_fields)
1089 for field in param_fields:
1090 # if self.is_switch, treat all fields as if they are variable sized
1091 if not field.type.fixed_size() or self.is_switch:
1092 variable_size_fields += 1
1093 # determine maxtypelen
1095 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1098 indent = ' '*(len(func_name)+2)
1101 typespec, pointerspec, field_name = p
1102 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1103 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1104 # insert function name
1105 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1106 param_str = list(map(lambda x: "%s," % x, param_str))
1107 for s in param_str[:-1]:
1109 _h("%s);" % param_str[-1].rstrip(','))
1110 _c("%s)" % param_str[-1].rstrip(','))
1117 if 'serialize' == context:
1118 if not self.is_switch and not self.var_followed_by_fixed_fields:
1119 _c(' %s *xcb_out = *_buffer;', self.c_type)
1120 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1121 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1122 _c(' unsigned int xcb_align_to;')
1124 _c(' char *xcb_out = *_buffer;')
1125 _c(' unsigned int xcb_buffer_len = 0;')
1126 _c(' unsigned int xcb_align_to;')
1127 prefix = [('_aux', '->', self)]
1130 elif context in ('unserialize', 'unpack'):
1131 _c(' char *xcb_tmp = (char *)_buffer;')
1132 if not self.is_switch:
1133 if not self.var_followed_by_fixed_fields:
1134 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1135 prefix = [('_aux', '->', self)]
1137 _c(' %s xcb_out;', self.c_type)
1138 prefix = [('xcb_out', '.', self)]
1140 aux_var = '_aux' # default for unpack: single pointer
1141 # note: unserialize not generated for switch
1142 if 'unserialize' == context:
1143 aux_var = '(*_aux)' # unserialize: double pointer (!)
1144 prefix = [(aux_var, '->', self)]
1146 _c(' unsigned int xcb_buffer_len = 0;')
1147 _c(' unsigned int xcb_block_len = 0;')
1148 _c(' unsigned int xcb_pad = 0;')
1149 _c(' unsigned int xcb_align_to;')
1151 elif 'sizeof' == context:
1152 param_names = [p[2] for p in params]
1154 # switch: call _unpack()
1155 _c(' %s _aux;', self.c_type)
1156 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1159 elif self.var_followed_by_fixed_fields:
1160 # special case: call _unserialize()
1161 _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1165 _c(' char *xcb_tmp = (char *)_buffer;')
1166 prefix = [('_aux', '->', self)]
1168 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1169 # update variable size fields (only important for context=='serialize'
1170 variable_size_fields = count
1171 if 'serialize' == context:
1172 temp_vars.append(' unsigned int xcb_pad = 0;')
1173 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1174 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1175 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1176 temp_vars.append(' unsigned int xcb_block_len = 0;')
1177 temp_vars.append(' unsigned int i;')
1178 temp_vars.append(' char *xcb_tmp;')
1179 elif 'sizeof' == context:
1180 # neither switch nor intermixed fixed and variable size fields:
1181 # evaluate parameters directly
1182 if not (self.is_switch or self.var_followed_by_fixed_fields):
1184 # look if we have to declare an '_aux' variable at all
1185 if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
1186 if not self.var_followed_by_fixed_fields:
1187 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1189 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1191 _c(' unsigned int xcb_buffer_len = 0;')
1192 _c(' unsigned int xcb_block_len = 0;')
1193 _c(' unsigned int xcb_pad = 0;')
1194 _c(' unsigned int xcb_align_to;')
1200 for l in code_lines:
1203 # variable sized fields have been collected, now
1204 # allocate memory and copy everything into a continuous memory area
1205 # note: this is not necessary in case of unpack
1206 if context in ('serialize', 'unserialize'):
1207 # unserialize: check for sizeof-only invocation
1208 if 'unserialize' == context:
1210 _c(' if (NULL == _aux)')
1211 _c(' return xcb_buffer_len;')
1214 _c(' if (NULL == %s) {', aux_ptr)
1215 _c(' /* allocate memory */')
1216 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1217 if 'serialize' == context:
1218 _c(' *_buffer = xcb_out;')
1222 # serialize: handle variable size fields in a loop
1223 if 'serialize' == context:
1224 if not self.is_switch and not self.var_followed_by_fixed_fields:
1225 if len(wire_fields)>0:
1226 _c(' *xcb_out = *_aux;')
1227 # copy variable size fields into the buffer
1228 if variable_size_fields > 0:
1230 if not self.is_switch and not self.var_followed_by_fixed_fields:
1231 _c(' xcb_tmp = (char*)++xcb_out;')
1232 _c(' xcb_tmp += xcb_out_pad;')
1234 _c(' xcb_tmp = xcb_out;')
1236 # variable sized fields
1237 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1238 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1239 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1240 _c(' if (0 != xcb_parts[i].iov_len)')
1241 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1244 # unserialize: assign variable size fields individually
1245 if 'unserialize' == context:
1246 _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1247 param_fields.reverse()
1248 for field in param_fields:
1249 if not field.type.fixed_size():
1250 _c(' xcb_tmp -= %s_len;', field.c_field_name)
1251 _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1252 _c(' *%s = xcb_out;', aux_ptr)
1255 _c(' return xcb_buffer_len;')
1259 def _c_iterator_get_end(field, accum):
1261 Figures out what C code is needed to find the end of a variable-length structure field.
1262 For nested structures, recurses into its last variable-sized field.
1263 For lists, calls the end function
1265 if field.type.is_container:
1266 accum = field.c_accessor_name + '(' + accum + ')'
1267 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1268 if field.type.is_list:
1269 # XXX we can always use the first way
1270 if field.type.member.is_simple:
1271 return field.c_end_name + '(' + accum + ')'
1273 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1275 def _c_iterator(self, name):
1277 Declares the iterator structure and next/end functions for a given type.
1282 _h(' * @brief %s', self.c_iterator_type)
1284 _h('typedef struct %s {', self.c_iterator_type)
1285 _h(' %s *data; /**< */', self.c_type)
1286 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1287 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1288 _h('} %s;', self.c_iterator_type)
1294 _h(' * Get the next element of the iterator')
1295 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1297 _h(' * Get the next element in the iterator. The member rem is')
1298 _h(' * decreased by one. The member data points to the next')
1299 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1303 _hc('/*****************************************************************************')
1305 _hc(' ** void %s', self.c_next_name)
1307 _hc(' ** @param %s *i', self.c_iterator_type)
1308 _hc(' ** @returns void')
1310 _hc(' *****************************************************************************/')
1313 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1314 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1317 if not self.fixed_size():
1318 _c(' %s *R = i->data;', self.c_type)
1321 # FIXME - how to determine the size of a variable size union??
1322 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1324 if self.need_sizeof:
1325 _c(' xcb_generic_iterator_t child;')
1326 _c(' child.data = (%s *)(((char *)R) + %s(R));',
1327 self.c_type, self.c_sizeof_name)
1328 _c(' i->index = (char *) child.data - (char *) i->data;')
1330 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1331 _c(' i->index = child.index;')
1333 _c(' i->data = (%s *) child.data;', self.c_type)
1338 _c(' i->index += sizeof(%s);', self.c_type)
1344 _h(' * Return the iterator pointing to the last element')
1345 _h(' * @param i An %s', self.c_iterator_type)
1346 _h(' * @return The iterator pointing to the last element')
1348 _h(' * Set the current element in the iterator to the last element.')
1349 _h(' * The member rem is set to 0. The member data points to the')
1350 _h(' * last element.')
1354 _hc('/*****************************************************************************')
1356 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1358 _hc(' ** @param %s i', self.c_iterator_type)
1359 _hc(' ** @returns xcb_generic_iterator_t')
1361 _hc(' *****************************************************************************/')
1363 _hc('xcb_generic_iterator_t')
1364 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1365 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1367 _c(' xcb_generic_iterator_t ret;')
1369 if self.fixed_size():
1370 _c(' ret.data = i.data + i.rem;')
1371 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1374 _c(' while(i.rem > 0)')
1375 _c(' %s(&i);', self.c_next_name)
1376 _c(' ret.data = i.data;')
1377 _c(' ret.rem = i.rem;')
1378 _c(' ret.index = i.index;')
1383 def _c_accessor_get_length(expr, field_mapping=None):
1385 Figures out what C code is needed to get a length field.
1386 The field_mapping parameter can be used to change the absolute name of a length field.
1387 For fields that follow a variable-length field, use the accessor.
1388 Otherwise, just reference the structure field directly.
1391 lenfield_name = expr.lenfield_name
1392 if lenfield_name is not None:
1393 if field_mapping is not None:
1394 lenfield_name = field_mapping[lenfield_name][0]
1396 if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1397 # special case: variable and fixed size fields are intermixed
1398 # if the lenfield is among the fixed size fields, there is no need
1399 # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1400 return field_mapping(expr.lenfield_name)
1401 elif expr.lenfield_name is not None:
1402 return lenfield_name
1404 return str(expr.nmemb)
1406 def _c_accessor_get_expr(expr, field_mapping):
1408 Figures out what C code is needed to get the length of a list field.
1409 The field_mapping parameter can be used to change the absolute name of a length field.
1410 Recurses for math operations.
1411 Returns bitcount for value-mask fields.
1412 Otherwise, uses the value of the length field.
1414 lenexp = _c_accessor_get_length(expr, field_mapping)
1417 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1418 elif expr.op == 'popcount':
1419 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1420 elif expr.op == 'enumref':
1421 enum_name = expr.lenfield_type.name
1422 constant_name = expr.lenfield_name
1423 c_name = _n(enum_name + (constant_name,)).upper()
1425 elif expr.op == 'sumof':
1426 # locate the referenced list object
1427 list_obj = expr.lenfield_type
1429 for f in expr.lenfield_parent.fields:
1430 if f.field_name == expr.lenfield_name:
1435 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1436 list_name = field_mapping[field.c_field_name][0]
1437 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1438 # note: xcb_sumof() has only been defined for integers
1439 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1440 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1441 elif expr.op != None:
1442 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1443 ' ' + expr.op + ' ' +
1444 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1446 return 'xcb_popcount(' + lenexp + ')'
1450 def type_pad_type(type):
1455 def _c_accessors_field(self, field):
1457 Declares the accessor functions for a non-list field that follows a variable-length field.
1459 c_type = self.c_type
1461 # special case: switch
1462 switch_obj = self if self.is_switch else None
1464 switch_obj = self.parents[-1]
1465 if switch_obj is not None:
1466 c_type = switch_obj.c_type
1468 if field.type.is_simple:
1471 _hc('/*****************************************************************************')
1473 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1475 _hc(' ** @param const %s *R', c_type)
1476 _hc(' ** @returns %s', field.c_field_type)
1478 _hc(' *****************************************************************************/')
1480 _hc('%s', field.c_field_type)
1481 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1482 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1484 if field.prev_varsized_field is None:
1485 _c(' return (%s *) (R + 1);', field.c_field_type)
1487 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1488 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1489 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1494 _hc('/*****************************************************************************')
1496 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1498 _hc(' ** @param const %s *R', c_type)
1499 _hc(' ** @returns %s *', field.c_field_type)
1501 _hc(' *****************************************************************************/')
1503 if field.type.is_switch and switch_obj is None:
1504 return_type = 'void *'
1506 return_type = '%s *' % field.c_field_type
1509 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1510 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1512 if field.prev_varsized_field is None:
1513 _c(' return (%s) (R + 1);', return_type)
1514 # note: the special case 'variable fields followed by fixed size fields'
1515 # is not of any consequence here, since the ordering gets
1516 # 'corrected' in the reply function
1518 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1519 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1520 return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1524 def _c_accessors_list(self, field):
1526 Declares the accessor functions for a list field.
1527 Declares a direct-accessor function only if the list members are fixed size.
1528 Declares length and get-iterator functions always.
1531 c_type = self.c_type
1533 # special case: switch
1534 # in case of switch, 2 params have to be supplied to certain accessor functions:
1535 # 1. the anchestor object (request or reply)
1536 # 2. the (anchestor) switch object
1537 # the reason is that switch is either a child of a request/reply or nested in another switch,
1538 # so whenever we need to access a length field, we might need to refer to some anchestor type
1539 switch_obj = self if self.is_switch else None
1541 switch_obj = self.parents[-1]
1542 if switch_obj is not None:
1543 c_type = switch_obj.c_type
1547 parents = self.parents if hasattr(self, 'parents') else [self]
1548 # 'R': parents[0] is always the 'toplevel' container type
1549 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1550 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1551 # auxiliary object for 'R' parameters
1554 if switch_obj is not None:
1555 # now look where the fields are defined that are needed to evaluate
1556 # the switch expr, and store the parent objects in accessor_params and
1557 # the fields in switch_fields
1559 # 'S': name for the 'toplevel' switch
1560 toplevel_switch = parents[1]
1561 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1562 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1564 # initialize prefix for everything "below" S
1565 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1566 prefix = [(prefix_str, '->', toplevel_switch)]
1568 # look for fields in the remaining containers
1569 for p in parents[2:] + [self]:
1570 # the separator between parent and child is always '.' here,
1571 # because of nested switch statements
1572 if not p.is_bitcase or (p.is_bitcase and p.has_name):
1573 prefix.append((p.name[-1], '.', p))
1574 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1576 # auxiliary object for 'S' parameter
1581 if list.member.fixed_size():
1582 idx = 1 if switch_obj is not None else 0
1585 _hc('/*****************************************************************************')
1587 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1589 _hc(' ** @param %s', params[idx][0])
1590 _hc(' ** @returns %s *', field.c_field_type)
1592 _hc(' *****************************************************************************/')
1594 _hc('%s *', field.c_field_type)
1596 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1597 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1600 if switch_obj is not None:
1601 _c(' return %s;', fields[field.c_field_name][0])
1602 elif field.prev_varsized_field is None:
1603 _c(' return (%s *) (R + 1);', field.c_field_type)
1605 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1606 _c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1607 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1612 _hc('/*****************************************************************************')
1614 _hc(' ** int %s', field.c_length_name)
1616 _hc(' ** @param const %s *R', c_type)
1617 _hc(' ** @returns int')
1619 _hc(' *****************************************************************************/')
1622 if switch_obj is not None:
1623 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1624 spacing = ' '*(len(field.c_length_name)+2)
1625 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1626 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1627 length = _c_accessor_get_expr(field.type.expr, fields)
1629 _h('%s (const %s *R /**< */);', field.c_length_name, c_type)
1630 _c('%s (const %s *R /**< */)', field.c_length_name, c_type)
1631 length = _c_accessor_get_expr(field.type.expr, fields)
1633 _c(' return %s;', length)
1636 if field.type.member.is_simple:
1639 _hc('/*****************************************************************************')
1641 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1643 _hc(' ** @param const %s *R', c_type)
1644 _hc(' ** @returns xcb_generic_iterator_t')
1646 _hc(' *****************************************************************************/')
1648 _hc('xcb_generic_iterator_t')
1649 if switch_obj is not None:
1650 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1651 spacing = ' '*(len(field.c_end_name)+2)
1652 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1653 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1655 _h('%s (const %s *R /**< */);', field.c_end_name, c_type)
1656 _c('%s (const %s *R /**< */)', field.c_end_name, c_type)
1658 _c(' xcb_generic_iterator_t i;')
1660 param = 'R' if switch_obj is None else 'S'
1661 if switch_obj is not None:
1662 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1663 _c_accessor_get_expr(field.type.expr, fields))
1664 elif field.prev_varsized_field == None:
1665 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1666 _c_accessor_get_expr(field.type.expr, fields))
1668 _c(' xcb_generic_iterator_t child = %s;',
1669 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1670 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1671 _c_accessor_get_expr(field.type.expr, fields))
1674 _c(' i.index = (char *) i.data - (char *) %s;', param)
1681 _hc('/*****************************************************************************')
1683 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1685 _hc(' ** @param const %s *R', c_type)
1686 _hc(' ** @returns %s', field.c_iterator_type)
1688 _hc(' *****************************************************************************/')
1691 _hc('%s', field.c_iterator_type)
1692 if switch_obj is not None:
1693 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1694 spacing = ' '*(len(field.c_iterator_name)+2)
1695 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1696 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1698 _h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
1699 _c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
1701 _c(' %s i;', field.c_iterator_type)
1703 if switch_obj is not None:
1704 _c(' i.data = %s;', fields[field.c_field_name][0])
1705 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1706 elif field.prev_varsized_field == None:
1707 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1709 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1710 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));',
1711 field.c_field_type, type_pad_type(field.c_field_type))
1712 if switch_obj is None:
1713 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1714 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1718 def _c_accessors(self, name, base):
1720 Declares the accessor functions for the fields of a structure.
1722 # no accessors for switch itself -
1723 # switch always needs to be unpacked explicitly
1724 # if self.is_switch:
1728 for field in self.fields:
1729 if field.type.is_list and not field.type.fixed_size():
1730 _c_accessors_list(self, field)
1731 elif field.prev_varsized_field is not None or not field.type.fixed_size():
1732 _c_accessors_field(self, field)
1734 def c_simple(self, name):
1736 Exported function that handles cardinal type declarations.
1737 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1739 _c_type_setup(self, name, ())
1741 if (self.name != name):
1746 _h('typedef %s %s;', _t(self.name), my_name)
1749 _c_iterator(self, name)
1751 def _c_complex(self):
1753 Helper function for handling all structure types.
1754 Called for all structs, requests, replies, events, errors.
1759 _h(' * @brief %s', self.c_type)
1761 _h('typedef %s %s {', self.c_container, self.c_type)
1767 for field in self.fields:
1768 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1769 varfield = field.c_field_name
1772 struct_fields.append(field)
1774 for field in struct_fields:
1775 length = len(field.c_field_type)
1776 # account for '*' pointer_spec
1777 if not field.type.fixed_size():
1779 maxtypelen = max(maxtypelen, length)
1781 def _c_complex_field(self, field, space=''):
1782 if (field.type.fixed_size() or
1783 # in case of switch with switch children, don't make the field a pointer
1784 # necessary for unserialize to work
1785 (self.is_switch and field.type.is_switch)):
1786 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1787 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1789 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1790 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1792 if not self.is_switch:
1793 for field in struct_fields:
1794 _c_complex_field(self, field)
1796 for b in self.bitcases:
1799 _h(' struct _%s {', b.c_field_name)
1801 for field in b.type.fields:
1802 _c_complex_field(self, field, space)
1804 _h(' } %s;', b.c_field_name)
1806 _h('} %s;', self.c_type)
1808 def c_struct(self, name):
1810 Exported function that handles structure declarations.
1812 _c_type_setup(self, name, ())
1814 _c_accessors(self, name, name)
1815 _c_iterator(self, name)
1817 def c_union(self, name):
1819 Exported function that handles union declarations.
1821 _c_type_setup(self, name, ())
1823 _c_iterator(self, name)
1825 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1827 Declares a request function.
1830 # Four stunningly confusing possibilities here:
1833 # ------------------------------
1835 # 0 flag CHECKED flag Normal Mode
1836 # void_cookie req_cookie
1837 # ------------------------------
1838 # "req_checked" "req_unchecked"
1839 # CHECKED flag 0 flag Abnormal Mode
1840 # void_cookie req_cookie
1841 # ------------------------------
1844 # Whether we are _checked or _unchecked
1845 checked = void and not regular
1846 unchecked = not void and not regular
1848 # What kind of cookie we return
1849 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1851 # What flag is passed to xcb_request
1852 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1854 # Global extension id variable or NULL for xproto
1855 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1857 # What our function name is
1858 func_name = self.c_request_name if not aux else self.c_aux_name
1860 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1862 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1866 maxtypelen = len('xcb_connection_t')
1868 # special case: list with variable size elements
1869 list_with_var_size_elems = False
1871 for field in self.fields:
1873 # The field should appear as a call parameter
1874 param_fields.append(field)
1875 if field.wire and not field.auto:
1876 # We need to set the field up in the structure
1877 wire_fields.append(field)
1878 if field.type.need_serialize or field.type.need_sizeof:
1879 serial_fields.append(field)
1881 for field in param_fields:
1882 c_field_const_type = field.c_field_const_type
1883 if field.type.need_serialize and not aux:
1884 c_field_const_type = "const void"
1885 if len(c_field_const_type) > maxtypelen:
1886 maxtypelen = len(c_field_const_type)
1887 if field.type.is_list and not field.type.member.fixed_size():
1888 list_with_var_size_elems = True
1894 if hasattr(self, "doc") and self.doc:
1896 _h(' * @brief ' + self.doc.brief)
1898 _h(' * No brief doc yet')
1901 _h(' * @param c The connection')
1902 param_names = [f.c_field_name for f in param_fields]
1903 if hasattr(self, "doc") and self.doc:
1904 for field in param_fields:
1905 # XXX: hard-coded until we fix xproto.xml
1906 base_func_name = self.c_request_name if not aux else self.c_aux_name
1907 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
1909 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
1911 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
1914 # XXX: why the 'xcb' prefix?
1915 key = ('xcb', field.enum)
1918 if namecount[tname] > 1:
1919 tname = _t(key + ('enum',))
1920 _h(' * @param %s A bitmask of #%s values.' % (field.c_field_name, tname))
1922 if self.doc and field.field_name in self.doc.fields:
1923 desc = self.doc.fields[field.field_name]
1924 for name in param_names:
1925 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1926 desc = desc.split("\n")
1927 desc = [line if line != '' else '\\n' for line in desc]
1928 _h(' * @param %s %s' % (field.c_field_name, "\n * ".join(desc)))
1929 # If there is no documentation yet, we simply don't generate an
1930 # @param tag. Doxygen will then warn about missing documentation.
1932 _h(' * @return A cookie')
1935 if hasattr(self, "doc") and self.doc:
1936 if self.doc.description:
1937 desc = self.doc.description
1938 for name in param_names:
1939 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1940 desc = desc.split("\n")
1941 _h(' * ' + "\n * ".join(desc))
1943 _h(' * No description yet')
1945 _h(' * Delivers a request to the X server.')
1948 _h(' * This form can be used only if the request will not cause')
1949 _h(' * a reply to be generated. Any returned error will be')
1950 _h(' * saved for handling by xcb_request_check().')
1952 _h(' * This form can be used only if the request will cause')
1953 _h(' * a reply to be generated. Any returned error will be')
1954 _h(' * placed in the event queue.')
1958 _hc('/*****************************************************************************')
1960 _hc(' ** %s %s', cookie_type, func_name)
1963 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1964 _hc(' ** @param xcb_connection_t%s *c', spacing)
1966 for field in param_fields:
1967 c_field_const_type = field.c_field_const_type
1968 if field.type.need_serialize and not aux:
1969 c_field_const_type = "const void"
1970 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1971 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1973 _hc(' ** @returns %s', cookie_type)
1975 _hc(' *****************************************************************************/')
1977 _hc('%s', cookie_type)
1979 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1980 comma = ',' if len(param_fields) else ');'
1981 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1982 comma = ',' if len(param_fields) else ')'
1983 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1985 func_spacing = ' ' * (len(func_name) + 2)
1986 count = len(param_fields)
1987 for field in param_fields:
1989 c_field_const_type = field.c_field_const_type
1990 c_pointer = field.c_pointer
1991 if field.type.need_serialize and not aux:
1992 c_field_const_type = "const void"
1994 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1995 comma = ',' if count else ');'
1996 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1997 spacing, c_pointer, field.c_field_name, comma)
1998 comma = ',' if count else ')'
1999 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
2000 spacing, c_pointer, field.c_field_name, comma)
2003 if not self.var_followed_by_fixed_fields:
2004 for field in param_fields:
2005 if not field.type.fixed_size():
2007 if field.type.need_serialize:
2008 # _serialize() keeps track of padding automatically
2010 dimension = count + 2
2013 _c(' static const xcb_protocol_request_t xcb_req = {')
2014 _c(' /* count */ %d,', count)
2015 _c(' /* ext */ %s,', func_ext_global)
2016 _c(' /* opcode */ %s,', self.c_request_name.upper())
2017 _c(' /* isvoid */ %d', 1 if void else 0)
2021 _c(' struct iovec xcb_parts[%d];', dimension)
2022 _c(' %s xcb_ret;', func_cookie)
2023 _c(' %s xcb_out;', self.c_type)
2024 if self.var_followed_by_fixed_fields:
2025 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
2026 _c(' void *xcb_aux = 0;')
2029 for idx, f in enumerate(serial_fields):
2031 _c(' void *xcb_aux%d = 0;' % (idx))
2032 if list_with_var_size_elems:
2033 _c(' unsigned int i;')
2034 _c(' unsigned int xcb_tmp_len;')
2035 _c(' char *xcb_tmp;')
2037 # simple request call tracing
2038 # _c(' printf("in function %s\\n");' % func_name)
2041 for field in wire_fields:
2042 if field.type.fixed_size():
2043 if field.type.is_expr:
2044 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
2045 elif field.type.is_pad:
2046 if field.type.nmemb == 1:
2047 _c(' xcb_out.%s = 0;', field.c_field_name)
2049 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
2051 if field.type.nmemb == 1:
2052 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
2054 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
2056 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
2057 serialize_args = get_serialize_params(context, type_obj,
2060 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
2062 # calls in order to free dyn. all. memory
2066 if not self.var_followed_by_fixed_fields:
2067 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2068 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
2069 _c(' xcb_parts[3].iov_base = 0;')
2070 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2074 for field in param_fields:
2075 if not field.type.fixed_size():
2076 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
2077 # default: simple cast to char *
2078 if not field.type.need_serialize and not field.type.need_sizeof:
2079 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2080 if field.type.is_list:
2081 if field.type.member.fixed_size():
2082 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
2083 _c_accessor_get_expr(field.type.expr, None),
2084 field.type.member.c_wiretype)
2086 list_length = _c_accessor_get_expr(field.type.expr, None)
2089 _c(" xcb_parts[%d].iov_len = 0;" % count)
2090 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2091 _c(" for(i=0; i<%s; i++) {" % list_length)
2092 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2093 (field.type.c_sizeof_name))
2094 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2095 _c(" xcb_tmp += xcb_tmp_len;")
2098 # not supposed to happen
2099 raise Exception("unhandled variable size field %s" % field.c_field_name)
2102 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2103 idx = serial_fields.index(field)
2104 aux_var = '&xcb_aux%d' % idx
2105 context = 'serialize' if aux else 'sizeof'
2106 _c(' xcb_parts[%d].iov_len = ', count)
2108 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2109 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2110 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2111 free_calls.append(' free(xcb_aux%d);' % idx)
2113 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2114 func_name = field.type.c_sizeof_name
2115 _c(' %s (%s);', func_name, serialize_args)
2118 if not (field.type.need_serialize or field.type.need_sizeof):
2119 # the _serialize() function keeps track of padding automatically
2120 _c(' xcb_parts[%d].iov_base = 0;', count)
2121 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2124 # elif self.var_followed_by_fixed_fields:
2126 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2127 # request header: opcodes + length
2128 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2131 buffer_var = '&xcb_aux'
2132 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2133 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2134 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2135 free_calls.append(' free(xcb_aux);')
2136 # no padding necessary - _serialize() keeps track of padding automatically
2139 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2141 # free dyn. all. data, if any
2142 for f in free_calls:
2144 _c(' return xcb_ret;')
2147 def _c_reply(self, name):
2149 Declares the function that returns the reply structure.
2151 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2152 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2153 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2155 # check if _unserialize() has to be called for any field
2156 def look_for_special_cases(complex_obj):
2157 unserialize_fields = []
2158 # no unserialize call in case of switch
2159 if not complex_obj.is_switch:
2160 for field in complex_obj.fields:
2161 # three cases: 1. field with special case
2162 # 2. container that contains special case field
2163 # 3. list with special case elements
2164 if field.type.var_followed_by_fixed_fields:
2165 unserialize_fields.append(field)
2166 elif field.type.is_container:
2167 unserialize_fields += look_for_special_cases(field.type)
2168 elif field.type.is_list:
2169 if field.type.member.var_followed_by_fixed_fields:
2170 unserialize_fields.append(field)
2171 if field.type.member.is_container:
2172 unserialize_fields += look_for_special_cases(field.type.member)
2173 return unserialize_fields
2175 unserialize_fields = look_for_special_cases(self.reply)
2179 _h(' * Return the reply')
2180 _h(' * @param c The connection')
2181 _h(' * @param cookie The cookie')
2182 _h(' * @param e The xcb_generic_error_t supplied')
2184 _h(' * Returns the reply of the request asked by')
2186 _h(' * The parameter @p e supplied to this function must be NULL if')
2187 _h(' * %s(). is used.', self.c_unchecked_name)
2188 _h(' * Otherwise, it stores the error if any.')
2190 _h(' * The returned value must be freed by the caller using free().')
2194 _hc('/*****************************************************************************')
2196 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
2198 _hc(' ** @param xcb_connection_t%s *c', spacing1)
2199 _hc(' ** @param %s cookie', self.c_cookie_type)
2200 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
2201 _hc(' ** @returns %s *', self.c_reply_type)
2203 _hc(' *****************************************************************************/')
2205 _hc('%s *', self.c_reply_type)
2206 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2207 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2208 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2209 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2212 if len(unserialize_fields)>0:
2213 # certain variable size fields need to be unserialized explicitly
2214 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2215 self.c_reply_type, self.c_reply_type)
2217 for field in unserialize_fields:
2218 if field.type.is_list:
2219 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2220 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2221 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2223 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2224 # call _unserialize(), using the reply as source and target buffer
2225 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2226 for field in unserialize_fields:
2227 if field.type.is_list:
2228 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2229 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2230 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2231 field.c_field_name, field.c_field_name)
2232 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2234 # return the transformed reply
2235 _c(' return reply;')
2238 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2242 def _c_opcode(name, opcode):
2244 Declares the opcode define for requests, events, and errors.
2248 _h('/** Opcode for %s. */', _n(name))
2249 _h('#define %s %s', _n(name).upper(), opcode)
2251 def _c_cookie(self, name):
2253 Declares the cookie type for a non-void request.
2258 _h(' * @brief %s', self.c_cookie_type)
2260 _h('typedef struct %s {', self.c_cookie_type)
2261 _h(' unsigned int sequence; /**< */')
2262 _h('} %s;', self.c_cookie_type)
2264 def _man_request(self, name, cookie_type, void, aux):
2265 param_fields = [f for f in self.fields if f.visible]
2267 func_name = self.c_request_name if not aux else self.c_aux_name
2269 def create_link(linkname):
2270 name = 'man/%s.3' % linkname
2272 sys.stdout.write(name)
2274 f.write('.so man3/%s.3' % func_name)
2278 sys.stdout.write('man/%s.3 ' % func_name)
2279 # Our CWD is src/, so this will end up in src/man/
2280 f = open('man/%s.3' % func_name, 'w')
2281 f.write('.TH %s 3 %s "XCB" "XCB Requests"\n' % (func_name, today))
2282 # Left-adjust instead of adjusting to both sides
2284 f.write('.SH NAME\n')
2285 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2286 f.write('%s \\- %s\n' % (func_name, brief))
2287 f.write('.SH SYNOPSIS\n')
2288 # Don't split words (hyphenate)
2290 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2292 # function prototypes
2294 count = len(param_fields)
2295 for field in param_fields:
2297 c_field_const_type = field.c_field_const_type
2298 c_pointer = field.c_pointer
2299 if c_pointer == ' ':
2301 if field.type.need_serialize and not aux:
2302 c_field_const_type = "const void"
2304 comma = ', ' if count else ');'
2305 prototype += '%s\\ %s\\fI%s\\fP%s' % (c_field_const_type, c_pointer, field.c_field_name, comma)
2307 f.write('.SS Request function\n')
2309 base_func_name = self.c_request_name if not aux else self.c_aux_name
2310 f.write('%s \\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\n' % (cookie_type, base_func_name, prototype))
2311 create_link('%s_%s' % (base_func_name, ('checked' if void else 'unchecked')))
2314 f.write('.SS Reply datastructure\n')
2317 f.write('typedef %s %s {\n' % (self.reply.c_container, self.reply.c_type))
2321 for field in self.reply.fields:
2322 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2325 struct_fields.append(field)
2327 for field in struct_fields:
2328 length = len(field.c_field_type)
2329 # account for '*' pointer_spec
2330 if not field.type.fixed_size():
2332 maxtypelen = max(maxtypelen, length)
2334 def _c_complex_field(self, field, space=''):
2335 if (field.type.fixed_size() or
2336 # in case of switch with switch children, don't make the field a pointer
2337 # necessary for unserialize to work
2338 (self.is_switch and field.type.is_switch)):
2339 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2340 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2342 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
2343 f.write('ELSE %s = %s\n' % (field.c_field_type, field.c_field_name))
2344 #_h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2346 if not self.is_switch:
2347 for field in struct_fields:
2348 _c_complex_field(self, field)
2350 for b in self.bitcases:
2354 for field in b.type.fields:
2355 _c_complex_field(self, field, space)
2357 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2360 f.write('} \\fB%s\\fP;\n' % self.reply.c_type)
2363 f.write('.SS Reply function\n')
2365 f.write(('%s *\\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\\ '
2366 '\\fIcookie\\fP, xcb_generic_error_t\\ **\\fIe\\fP);\n') %
2367 (self.c_reply_type, self.c_reply_name, self.c_cookie_type))
2368 create_link('%s' % self.c_reply_name)
2370 has_accessors = False
2371 for field in self.reply.fields:
2372 if field.type.is_list and not field.type.fixed_size():
2373 has_accessors = True
2374 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2375 has_accessors = True
2378 f.write('.SS Reply accessors\n')
2380 def _c_accessors_field(self, field):
2382 Declares the accessor functions for a non-list field that follows a variable-length field.
2384 c_type = self.c_type
2386 # special case: switch
2387 switch_obj = self if self.is_switch else None
2389 switch_obj = self.parents[-1]
2390 if switch_obj is not None:
2391 c_type = switch_obj.c_type
2393 if field.type.is_simple:
2394 f.write('%s %s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2395 create_link('%s' % field.c_accessor_name)
2397 f.write('%s *%s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2398 create_link('%s' % field.c_accessor_name)
2400 def _c_accessors_list(self, field):
2402 Declares the accessor functions for a list field.
2403 Declares a direct-accessor function only if the list members are fixed size.
2404 Declares length and get-iterator functions always.
2407 c_type = self.reply.c_type
2409 # special case: switch
2410 # in case of switch, 2 params have to be supplied to certain accessor functions:
2411 # 1. the anchestor object (request or reply)
2412 # 2. the (anchestor) switch object
2413 # the reason is that switch is either a child of a request/reply or nested in another switch,
2414 # so whenever we need to access a length field, we might need to refer to some anchestor type
2415 switch_obj = self if self.is_switch else None
2417 switch_obj = self.parents[-1]
2418 if switch_obj is not None:
2419 c_type = switch_obj.c_type
2423 parents = self.parents if hasattr(self, 'parents') else [self]
2424 # 'R': parents[0] is always the 'toplevel' container type
2425 params.append(('const %s *\\fIreply\\fP' % parents[0].c_type, parents[0]))
2426 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
2427 # auxiliary object for 'R' parameters
2430 if switch_obj is not None:
2431 # now look where the fields are defined that are needed to evaluate
2432 # the switch expr, and store the parent objects in accessor_params and
2433 # the fields in switch_fields
2435 # 'S': name for the 'toplevel' switch
2436 toplevel_switch = parents[1]
2437 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
2438 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
2440 # initialize prefix for everything "below" S
2441 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
2442 prefix = [(prefix_str, '->', toplevel_switch)]
2444 # look for fields in the remaining containers
2445 for p in parents[2:] + [self]:
2446 # the separator between parent and child is always '.' here,
2447 # because of nested switch statements
2448 if not p.is_bitcase or (p.is_bitcase and p.has_name):
2449 prefix.append((p.name[-1], '.', p))
2450 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
2452 # auxiliary object for 'S' parameter
2455 if list.member.fixed_size():
2456 idx = 1 if switch_obj is not None else 0
2458 f.write('%s *\\fB%s\\fP(%s);\n' %
2459 (field.c_field_type, field.c_accessor_name, params[idx][0]))
2460 create_link('%s' % field.c_accessor_name)
2463 f.write('int \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2464 (field.c_length_name, c_type))
2465 create_link('%s' % field.c_length_name)
2467 if field.type.member.is_simple:
2469 f.write('xcb_generic_iterator_t \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2470 (field.c_end_name, c_type))
2471 create_link('%s' % field.c_end_name)
2474 f.write('%s \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2475 (field.c_iterator_type, field.c_iterator_name,
2477 create_link('%s' % field.c_iterator_name)
2479 for field in self.reply.fields:
2480 if field.type.is_list and not field.type.fixed_size():
2481 _c_accessors_list(self, field)
2482 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2483 _c_accessors_field(self, field)
2487 # Re-enable hyphenation and adjusting to both sides
2490 # argument reference
2491 f.write('.SH REQUEST ARGUMENTS\n')
2492 f.write('.IP \\fI%s\\fP 1i\n' % 'conn')
2493 f.write('The XCB connection to X11.\n')
2494 for field in param_fields:
2495 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2496 printed_enum = False
2497 # XXX: hard-coded until we fix xproto.xml
2498 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
2500 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
2502 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
2504 if hasattr(field, "enum") and field.enum:
2505 # XXX: why the 'xcb' prefix?
2506 key = ('xcb', field.enum)
2508 f.write('One of the following values:\n')
2511 count = len(enum.values)
2512 for (enam, eval) in enum.values:
2514 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2515 if hasattr(enum, "doc") and enum.doc and enam in enum.doc.fields:
2516 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2517 f.write('%s\n' % desc)
2519 f.write('TODO: NOT YET DOCUMENTED.\n')
2524 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2525 desc = self.doc.fields[field.field_name]
2526 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2529 f.write('%s\n' % desc)
2531 f.write('TODO: NOT YET DOCUMENTED.\n')
2537 f.write('.SH REPLY FIELDS\n')
2538 # These fields are present in every reply:
2539 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2540 f.write(('The type of this reply, in this case \\fI%s\\fP. This field '
2541 'is also present in the \\fIxcb_generic_reply_t\\fP and can '
2542 'be used to tell replies apart from each other.\n') %
2543 _n(self.reply.name).upper())
2544 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2545 f.write('The sequence number of the last request processed by the X11 server.\n')
2546 f.write('.IP \\fI%s\\fP 1i\n' % 'length')
2547 f.write('The length of the reply, in words (a word is 4 bytes).\n')
2548 for field in self.reply.fields:
2549 if (field.c_field_name in frozenset(['response_type', 'sequence', 'length']) or
2550 field.c_field_name.startswith('pad')):
2553 if field.type.is_list and not field.type.fixed_size():
2555 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2557 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2558 printed_enum = False
2559 if hasattr(field, "enum") and field.enum:
2560 # XXX: why the 'xcb' prefix?
2561 key = ('xcb', field.enum)
2563 f.write('One of the following values:\n')
2566 count = len(enum.values)
2567 for (enam, eval) in enum.values:
2569 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2570 if enum.doc and enam in enum.doc.fields:
2571 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2572 f.write('%s\n' % desc)
2574 f.write('TODO: NOT YET DOCUMENTED.\n')
2579 if hasattr(self.reply, "doc") and self.reply.doc and field.field_name in self.reply.doc.fields:
2580 desc = self.reply.doc.fields[field.field_name]
2581 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2584 f.write('%s\n' % desc)
2586 f.write('TODO: NOT YET DOCUMENTED.\n')
2593 f.write('.SH DESCRIPTION\n')
2594 if hasattr(self, "doc") and self.doc and self.doc.description:
2595 desc = self.doc.description
2596 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2597 lines = desc.split('\n')
2598 f.write('\n'.join(lines) + '\n')
2600 f.write('.SH RETURN VALUE\n')
2602 f.write(('Returns an \\fIxcb_void_cookie_t\\fP. Errors (if any) '
2603 'have to be handled in the event loop.\n\nIf you want to '
2604 'handle errors directly with \\fIxcb_request_check\\fP '
2605 'instead, use \\fI%s_checked\\fP. See '
2606 '\\fBxcb-requests(3)\\fP for details.\n') % (base_func_name))
2608 f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
2609 'calling the reply function \\fI%s\\fP.\n\nIf you want to '
2610 'handle errors in the event loop instead, use '
2611 '\\fI%s_unchecked\\fP. See \\fBxcb-requests(3)\\fP for '
2613 (cookie_type, self.c_reply_name, base_func_name))
2614 f.write('.SH ERRORS\n')
2615 if hasattr(self, "doc") and self.doc:
2616 for errtype, errtext in self.doc.errors.iteritems():
2617 f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
2618 errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
2619 f.write('%s\n' % (errtext))
2620 if not hasattr(self, "doc") or not self.doc or len(self.doc.errors) == 0:
2621 f.write('This request does never generate any errors.\n')
2622 if hasattr(self, "doc") and self.doc and self.doc.example:
2623 f.write('.SH EXAMPLE\n')
2626 lines = self.doc.example.split('\n')
2627 f.write('\n'.join(lines) + '\n')
2629 f.write('.SH SEE ALSO\n')
2630 if hasattr(self, "doc") and self.doc:
2631 see = ['.BR %s (3)' % 'xcb-requests']
2632 if self.doc.example:
2633 see.append('.BR %s (3)' % 'xcb-examples')
2634 for seename, seetype in self.doc.see.iteritems():
2635 if seetype == 'program':
2636 see.append('.BR %s (1)' % seename)
2637 elif seetype == 'event':
2638 see.append('.BR %s (3)' % _t(('xcb', seename, 'event')))
2639 elif seetype == 'request':
2640 see.append('.BR %s (3)' % _n(('xcb', seename)))
2641 elif seetype == 'function':
2642 see.append('.BR %s (3)' % seename)
2644 see.append('TODO: %s (type %s)' % (seename, seetype))
2645 f.write(',\n'.join(see) + '\n')
2646 f.write('.SH AUTHOR\n')
2647 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2650 def _man_event(self, name):
2652 sys.stdout.write('man/%s.3 ' % self.c_type)
2653 # Our CWD is src/, so this will end up in src/man/
2654 f = open('man/%s.3' % self.c_type, 'w')
2655 f.write('.TH %s 3 %s "XCB" "XCB Events"\n' % (self.c_type, today))
2656 # Left-adjust instead of adjusting to both sides
2658 f.write('.SH NAME\n')
2659 brief = self.doc.brief if hasattr(self, "doc") and self.doc else ''
2660 f.write('%s \\- %s\n' % (self.c_type, brief))
2661 f.write('.SH SYNOPSIS\n')
2662 # Don't split words (hyphenate)
2664 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2667 f.write('.SS Event datastructure\n')
2670 f.write('typedef %s %s {\n' % (self.c_container, self.c_type))
2674 for field in self.fields:
2675 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2678 struct_fields.append(field)
2680 for field in struct_fields:
2681 length = len(field.c_field_type)
2682 # account for '*' pointer_spec
2683 if not field.type.fixed_size():
2685 maxtypelen = max(maxtypelen, length)
2687 def _c_complex_field(self, field, space=''):
2688 if (field.type.fixed_size() or
2689 # in case of switch with switch children, don't make the field a pointer
2690 # necessary for unserialize to work
2691 (self.is_switch and field.type.is_switch)):
2692 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2693 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2695 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2697 if not self.is_switch:
2698 for field in struct_fields:
2699 _c_complex_field(self, field)
2701 for b in self.bitcases:
2705 for field in b.type.fields:
2706 _c_complex_field(self, field, space)
2708 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2711 f.write('} \\fB%s\\fP;\n' % self.c_type)
2716 # Re-enable hyphenation and adjusting to both sides
2719 # argument reference
2720 f.write('.SH EVENT FIELDS\n')
2721 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2722 f.write(('The type of this event, in this case \\fI%s\\fP. This field is '
2723 'also present in the \\fIxcb_generic_event_t\\fP and can be used '
2724 'to tell events apart from each other.\n') % _n(name).upper())
2725 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2726 f.write('The sequence number of the last request processed by the X11 server.\n')
2728 if not self.is_switch:
2729 for field in struct_fields:
2730 # Skip the fields which every event has, we already documented
2732 if field.c_field_name in ('response_type', 'sequence'):
2734 if isinstance(field.type, PadType):
2736 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2737 if hasattr(self, "doc") and self.doc and field.field_name in self.doc.fields:
2738 desc = self.doc.fields[field.field_name]
2739 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2740 f.write('%s\n' % desc)
2742 f.write('NOT YET DOCUMENTED.\n')
2745 f.write('.SH DESCRIPTION\n')
2746 if hasattr(self, "doc") and self.doc and self.doc.description:
2747 desc = self.doc.description
2748 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2749 lines = desc.split('\n')
2750 f.write('\n'.join(lines) + '\n')
2752 if hasattr(self, "doc") and self.doc and self.doc.example:
2753 f.write('.SH EXAMPLE\n')
2756 lines = self.doc.example.split('\n')
2757 f.write('\n'.join(lines) + '\n')
2759 f.write('.SH SEE ALSO\n')
2760 if hasattr(self, "doc") and self.doc:
2761 see = ['.BR %s (3)' % 'xcb_generic_event_t']
2762 if self.doc.example:
2763 see.append('.BR %s (3)' % 'xcb-examples')
2764 for seename, seetype in self.doc.see.iteritems():
2765 if seetype == 'program':
2766 see.append('.BR %s (1)' % seename)
2767 elif seetype == 'event':
2768 see.append('.BR %s (3)' % _t(('xcb', seename, 'event')))
2769 elif seetype == 'request':
2770 see.append('.BR %s (3)' % _n(('xcb', seename)))
2771 elif seetype == 'function':
2772 see.append('.BR %s (3)' % seename)
2774 see.append('TODO: %s (type %s)' % (seename, seetype))
2775 f.write(',\n'.join(see) + '\n')
2776 f.write('.SH AUTHOR\n')
2777 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2781 def c_request(self, name):
2783 Exported function that handles request declarations.
2785 _c_type_setup(self, name, ('request',))
2788 # Cookie type declaration
2789 _c_cookie(self, name)
2792 _c_opcode(name, self.opcode)
2794 # Request structure declaration
2798 _c_type_setup(self.reply, name, ('reply',))
2799 # Reply structure definition
2800 _c_complex(self.reply)
2801 # Request prototypes
2802 _c_request_helper(self, name, self.c_cookie_type, False, True)
2803 _c_request_helper(self, name, self.c_cookie_type, False, False)
2805 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
2806 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
2808 _c_accessors(self.reply, name + ('reply',), name)
2809 _c_reply(self, name)
2811 # Request prototypes
2812 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2813 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2815 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2816 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2818 # We generate the manpage afterwards because _c_type_setup has been called.
2819 # TODO: what about aux helpers?
2820 cookie_type = self.c_cookie_type if self.reply else 'xcb_void_cookie_t'
2821 _man_request(self, name, cookie_type, not self.reply, False)
2823 def c_event(self, name):
2825 Exported function that handles event declarations.
2827 _c_type_setup(self, name, ('event',))
2830 _c_opcode(name, self.opcodes[name])
2832 if self.name == name:
2833 # Structure definition
2838 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2840 _man_event(self, name)
2842 def c_error(self, name):
2844 Exported function that handles error declarations.
2846 _c_type_setup(self, name, ('error',))
2849 _c_opcode(name, self.opcodes[name])
2851 if self.name == name:
2852 # Structure definition
2857 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2860 # Main routine starts here
2862 # Must create an "output" dictionary before any xcbgen imports.
2863 output = {'open' : c_open,
2865 'simple' : c_simple,
2867 'struct' : c_struct,
2869 'request' : c_request,
2874 # Boilerplate below this point
2876 # Check for the argument that specifies path to the xcbgen python package.
2878 opts, args = getopt.getopt(sys.argv[1:], 'p:m')
2879 except getopt.GetoptError as err:
2881 print('Usage: c_client.py [-p path] file.xml')
2884 for (opt, arg) in opts:
2886 sys.path.insert(1, arg)
2889 sys.stdout.write('man_MANS = ')
2891 # Import the module class
2893 from xcbgen.state import Module
2894 from xcbgen.xtypes import *
2897 Failed to load the xcbgen Python package!
2898 Make sure that xcb/proto installed it on your Python path.
2899 If not, you will need to create a .pth file or define $PYTHONPATH
2901 Refer to the README file in xcb/proto for more info.
2905 # Ensure the man subdirectory exists
2909 if e.errno != errno.EEXIST:
2912 today = time.strftime('%Y-%m-%d', time.gmtime(os.path.getmtime(args[0])))
2914 # Parse the xml header
2915 module = Module(args[0], output)
2917 # Build type-registry and resolve type dependencies