2 from xml.etree.cElementTree import *
3 from os.path import basename
4 from functools import reduce
11 # Jump to the bottom of this file for the main routine
13 # Some hacks to make the API more readable, and to keep backwards compability
14 _cname_re = re.compile('([A-Z0-9][a-z]+|[A-Z0-9]+(?![a-z])|[a-z]+)')
15 _cname_special_cases = {'DECnet':'decnet'}
17 _extension_special_cases = ['XPrint', 'XCMisc', 'BigRequests']
19 _cplusplus_annoyances = {'class' : '_class',
22 _c_keywords = {'default' : '_default'}
30 # global variable to keep track of serializers and
31 # switch data types due to weird dependencies
32 finished_serializers = []
36 # keeps enum objects so that we can refer to them when generating manpages.
43 Writes the given line to the header file.
45 _hlines[_hlevel].append(fmt % args)
49 Writes the given line to the source file.
51 _clines[_clevel].append(fmt % args)
55 Writes the given line to both the header and source files.
60 # XXX See if this level thing is really necessary.
63 Changes the array that header lines are written to.
64 Supports writing different sections of the header file.
67 while len(_hlines) <= idx:
73 Changes the array that source lines are written to.
74 Supports writing to different sections of the source file.
77 while len(_clines) <= idx:
83 Does C-name conversion on a single string fragment.
84 Uses a regexp with some hard-coded special cases.
86 if str in _cname_special_cases:
87 return _cname_special_cases[str]
89 split = _cname_re.finditer(str)
90 name_parts = [match.group(0) for match in split]
91 return '_'.join(name_parts)
95 Checks for certain C++ reserved words and fixes them.
97 if str in _cplusplus_annoyances:
98 return _cplusplus_annoyances[str]
99 elif str in _c_keywords:
100 return _c_keywords[str]
106 Does C-name conversion on an extension name.
107 Has some additional special cases on top of _n_item.
109 if str in _extension_special_cases:
110 return _n_item(str).lower()
116 Does C-name conversion on a tuple of strings.
117 Different behavior depending on length of tuple, extension/not extension, etc.
118 Basically C-name converts the individual pieces, then joins with underscores.
123 parts = [list[0], _n_item(list[1])]
125 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
127 parts = [list[0]] + [_n_item(i) for i in list[1:]]
128 return '_'.join(parts).lower()
132 Does C-name conversion on a tuple of strings representing a type.
133 Same as _n but adds a "_t" on the end.
138 parts = [list[0], _n_item(list[1]), 't']
140 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
142 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
143 return '_'.join(parts).lower()
148 Exported function that handles module open.
149 Opens the files and writes out the auto-generated comment, header file includes, etc.
153 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
155 # Build the type-name collision avoidance table used by c_enum
156 build_collision_table()
162 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
163 _hc(' * Edit at your peril.')
168 _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
169 _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
173 _h('#ifndef __%s_H', _ns.header.upper())
174 _h('#define __%s_H', _ns.header.upper())
176 _h('#include "xcb.h"')
178 _c('#include <stdlib.h>')
179 _c('#include <string.h>')
180 _c('#include <assert.h>')
181 _c('#include <stddef.h> /* for offsetof() */')
182 _c('#include "xcbext.h"')
183 _c('#include "%s.h"', _ns.header)
186 _c('#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)')
189 for (n, h) in self.imports:
190 _hc('#include "%s.h"', h)
193 _h('#ifdef __cplusplus')
199 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
200 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
202 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
205 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
209 Exported function that handles module close.
210 Writes out all the stored content lines, then closes the files.
217 _h('#ifdef __cplusplus')
229 hfile = open('%s.h' % _ns.header, 'w')
237 cfile = open('%s.c' % _ns.header, 'w')
244 def build_collision_table():
248 for v in module.types.values():
250 namecount[name] = (namecount.get(name) or 0) + 1
252 def c_enum(self, name):
254 Exported function that handles enum declarations.
260 if namecount[tname] > 1:
261 tname = _t(name + ('enum',))
265 _h('typedef enum %s {', tname)
267 count = len(self.values)
269 for (enam, eval) in self.values:
271 equals = ' = ' if eval != '' else ''
272 comma = ',' if count > 0 else ''
274 if self.doc and enam in self.doc.fields:
275 doc = '\n/**< %s */\n' % self.doc.fields[enam]
276 _h(' %s%s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma, doc)
280 def _c_type_setup(self, name, postfix):
282 Sets up all the C-related state by adding additional data fields to
283 all Field and Type objects. Here is where we figure out most of our
284 variable and function names.
286 Recurses into child fields and list member types.
288 # Do all the various names in advance
289 self.c_type = _t(name + postfix)
290 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
292 self.c_iterator_type = _t(name + ('iterator',))
293 self.c_next_name = _n(name + ('next',))
294 self.c_end_name = _n(name + ('end',))
296 self.c_request_name = _n(name)
297 self.c_checked_name = _n(name + ('checked',))
298 self.c_unchecked_name = _n(name + ('unchecked',))
299 self.c_reply_name = _n(name + ('reply',))
300 self.c_reply_type = _t(name + ('reply',))
301 self.c_cookie_type = _t(name + ('cookie',))
303 self.need_aux = False
304 self.need_serialize = False
305 self.need_sizeof = False
307 self.c_aux_name = _n(name + ('aux',))
308 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
309 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
310 self.c_serialize_name = _n(name + ('serialize',))
311 self.c_unserialize_name = _n(name + ('unserialize',))
312 self.c_unpack_name = _n(name + ('unpack',))
313 self.c_sizeof_name = _n(name + ('sizeof',))
315 # special case: structs where variable size fields are followed by fixed size fields
316 self.var_followed_by_fixed_fields = False
319 self.need_serialize = True
320 self.c_container = 'struct'
321 for bitcase in self.bitcases:
322 bitcase.c_field_name = _cpp(bitcase.field_name)
323 bitcase_name = bitcase.field_type if bitcase.type.has_name else name
324 _c_type_setup(bitcase.type, bitcase_name, ())
326 elif self.is_container:
328 self.c_container = 'union' if self.is_union else 'struct'
329 prev_varsized_field = None
330 prev_varsized_offset = 0
331 first_field_after_varsized = None
333 for field in self.fields:
334 _c_type_setup(field.type, field.field_type, ())
335 if field.type.is_list:
336 _c_type_setup(field.type.member, field.field_type, ())
337 if (field.type.nmemb is None):
338 self.need_sizeof = True
340 field.c_field_type = _t(field.field_type)
341 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
342 field.c_field_name = _cpp(field.field_name)
343 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb and field.type.nmemb > 1) else ''
344 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
346 # correct the c_pointer field for variable size non-list types
347 if not field.type.fixed_size() and field.c_pointer == ' ':
348 field.c_pointer = '*'
349 if field.type.is_list and not field.type.member.fixed_size():
350 field.c_pointer = '*'
352 if field.type.is_switch:
353 field.c_pointer = '*'
354 field.c_field_const_type = 'const ' + field.c_field_type
356 elif not field.type.fixed_size() and not field.type.is_bitcase:
357 self.need_sizeof = True
359 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
360 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
361 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
362 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
363 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
365 field.prev_varsized_field = prev_varsized_field
366 field.prev_varsized_offset = prev_varsized_offset
368 if prev_varsized_offset == 0:
369 first_field_after_varsized = field
370 field.first_field_after_varsized = first_field_after_varsized
372 if field.type.fixed_size():
373 prev_varsized_offset += field.type.size
374 # special case: intermixed fixed and variable size fields
375 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
376 if not self.is_union:
377 self.need_serialize = True
378 self.var_followed_by_fixed_fields = True
380 self.last_varsized_field = field
381 prev_varsized_field = field
382 prev_varsized_offset = 0
384 if self.var_followed_by_fixed_fields:
385 if field.type.fixed_size():
386 field.prev_varsized_field = None
388 if self.need_serialize:
389 # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
390 self.need_sizeof = True
392 # as switch does never appear at toplevel,
393 # continue here with type construction
395 if self.c_type not in finished_switch:
396 finished_switch.append(self.c_type)
397 # special: switch C structs get pointer fields for variable-sized members
399 for bitcase in self.bitcases:
400 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
401 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
402 # no list with switch as element, so no call to
403 # _c_iterator(field.type, field_name) necessary
405 if not self.is_bitcase:
406 if self.need_serialize:
407 if self.c_serialize_name not in finished_serializers:
408 finished_serializers.append(self.c_serialize_name)
409 _c_serialize('serialize', self)
411 # _unpack() and _unserialize() are only needed for special cases:
413 # special cases -> unserialize
414 if self.is_switch or self.var_followed_by_fixed_fields:
415 _c_serialize('unserialize', self)
418 if self.c_sizeof_name not in finished_sizeof:
419 if not module.namespace.is_ext or self.name[:2] == module.namespace.prefix:
420 finished_sizeof.append(self.c_sizeof_name)
421 _c_serialize('sizeof', self)
424 def _c_helper_absolute_name(prefix, field=None):
426 turn prefix, which is a list of tuples (name, separator, Type obj) into a string
427 representing a valid name in C (based on the context)
428 if field is not None, append the field name as well
431 for name, sep, obj in prefix:
435 if ((obj.is_bitcase and obj.has_name) or # named bitcase
436 (obj.is_switch and len(obj.parents)>1)):
439 if field is not None:
440 prefix_str += _cpp(field.field_name)
444 def _c_helper_field_mapping(complex_type, prefix, flat=False):
446 generate absolute names, based on prefix, for all fields starting from complex_type
447 if flat == True, nested complex types are not taken into account
450 if complex_type.is_switch:
451 for b in complex_type.bitcases:
453 switch_name, switch_sep, switch_type = prefix[-1]
454 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
456 bitcase_prefix = prefix
458 if (True==flat and not b.type.has_name) or False==flat:
459 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
461 for f in complex_type.fields:
462 fname = _c_helper_absolute_name(prefix, f)
463 if f.field_name in all_fields:
464 raise Exception("field name %s has been registered before" % f.field_name)
466 all_fields[f.field_name] = (fname, f)
467 if f.type.is_container and flat==False:
468 if f.type.is_bitcase and not f.type.has_name:
470 elif f.type.is_switch and len(f.type.parents)>1:
471 # nested switch gets another separator
472 new_prefix = prefix+[(f.c_field_name, '.', f.type)]
474 new_prefix = prefix+[(f.c_field_name, '->', f.type)]
475 all_fields.update(_c_helper_field_mapping(f.type, new_prefix, flat))
480 def _c_helper_resolve_field_names (prefix):
482 get field names for all objects in the prefix array
486 # look for fields in the remaining containers
487 for idx, p in enumerate(prefix):
490 # sep can be preset in prefix, if not, make a sensible guess
491 sep = '.' if (obj.is_switch or obj.is_bitcase) else '->'
492 # exception: 'toplevel' object (switch as well!) always have sep '->'
493 sep = '->' if idx<1 else sep
494 if not obj.is_bitcase or (obj.is_bitcase and obj.has_name):
495 tmp_prefix.append((name, sep, obj))
496 all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
499 # _c_helper_resolve_field_names
501 def get_expr_fields(self):
503 get the Fields referenced by switch or list expression
505 def get_expr_field_names(expr):
507 if expr.lenfield_name is not None:
508 return [expr.lenfield_name]
510 # constant value expr
514 return get_expr_field_names(expr.rhs)
515 elif expr.op == 'popcount':
516 return get_expr_field_names(expr.rhs)
517 elif expr.op == 'sumof':
518 # sumof expr references another list,
519 # we need that list's length field here
521 for f in expr.lenfield_parent.fields:
522 if f.field_name == expr.lenfield_name:
526 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
527 # referenced list + its length field
528 return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
529 elif expr.op == 'enumref':
532 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
533 # get_expr_field_names()
535 # resolve the field names with the parent structure(s)
536 unresolved_fields_names = get_expr_field_names(self.expr)
538 # construct prefix from self
539 prefix = [('', '', p) for p in self.parents]
540 if self.is_container:
541 prefix.append(('', '', self))
543 all_fields = _c_helper_resolve_field_names (prefix)
544 resolved_fields_names = list(filter(lambda x: x in all_fields.keys(), unresolved_fields_names))
545 if len(unresolved_fields_names) != len(resolved_fields_names):
546 raise Exception("could not resolve all fields for %s" % self.name)
548 resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
549 return resolved_fields
552 def resolve_expr_fields(complex_obj):
554 find expr fields appearing in complex_obj and descendents that cannot be resolved within complex_obj
555 these are normally fields that need to be given as function parameters
561 for field in complex_obj.fields:
562 all_fields.append(field)
563 if field.type.is_switch or field.type.is_list:
564 expr_fields += get_expr_fields(field.type)
565 if field.type.is_container:
566 expr_fields += resolve_expr_fields(field.type)
568 # try to resolve expr fields
569 for e in expr_fields:
570 if e not in all_fields and e not in unresolved:
573 # resolve_expr_fields()
575 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
577 functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
578 E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch
579 expression. This function tries to resolve all fields within a structure, and returns the
580 unresolved fields as the list of external parameters.
582 def add_param(params, param):
583 if param not in params:
586 # collect all fields into param_fields
590 for field in self.fields:
592 # the field should appear as a parameter in the function call
593 param_fields.append(field)
594 if field.wire and not field.auto:
595 if field.type.fixed_size() and not self.is_switch:
596 # field in the xcb_out structure
597 wire_fields.append(field)
598 # fields like 'pad0' are skipped!
600 # in case of switch, parameters always contain any fields referenced in the switch expr
601 # we do not need any variable size fields here, as the switch data type contains both
602 # fixed and variable size fields
604 param_fields = get_expr_fields(self)
606 # _serialize()/_unserialize()/_unpack() function parameters
607 # note: don't use set() for params, it is unsorted
610 # 1. the parameter for the void * buffer
611 if 'serialize' == context:
612 params.append(('void', '**', buffer_var))
613 elif context in ('unserialize', 'unpack', 'sizeof'):
614 params.append(('const void', '*', buffer_var))
616 # 2. any expr fields that cannot be resolved within self and descendants
617 unresolved_fields = resolve_expr_fields(self)
618 for f in unresolved_fields:
619 add_param(params, (f.c_field_type, '', f.c_field_name))
621 # 3. param_fields contain the fields necessary to evaluate the switch expr or any other fields
622 # that do not appear in the data type struct
623 for p in param_fields:
625 typespec = p.c_field_const_type
626 pointerspec = p.c_pointer
627 add_param(params, (typespec, pointerspec, p.c_field_name))
629 if p.visible and not p.wire and not p.auto:
630 typespec = p.c_field_type
632 add_param(params, (typespec, pointerspec, p.c_field_name))
635 if 'serialize' == context:
636 add_param(params, ('const %s' % self.c_type, '*', aux_var))
637 elif 'unserialize' == context:
638 add_param(params, ('%s' % self.c_type, '**', aux_var))
639 elif 'unpack' == context:
640 add_param(params, ('%s' % self.c_type, '*', aux_var))
642 # 5. switch contains all variable size fields as struct members
643 # for other data types though, these have to be supplied separately
644 # this is important for the special case of intermixed fixed and
645 # variable size fields
646 if not self.is_switch and 'serialize' == context:
647 for p in param_fields:
648 if not p.type.fixed_size():
649 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
651 return (param_fields, wire_fields, params)
652 # get_serialize_params()
654 def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
655 code_lines.append('%s /* insert padding */' % space)
656 code_lines.append('%s xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space)
657 # code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
658 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
661 code_lines.append('%s if (0 != xcb_pad) {' % space)
663 if 'serialize' == context:
664 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
665 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
666 code_lines.append('%s xcb_parts_idx++;' % space)
667 elif context in ('unserialize', 'unpack', 'sizeof'):
668 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
670 code_lines.append('%s xcb_pad = 0;' % space)
671 code_lines.append('%s }' % space)
673 code_lines.append('%s xcb_block_len = 0;' % space)
675 # keep tracking of xcb_parts entries for serialize
677 # _c_serialize_helper_insert_padding()
679 def _c_serialize_helper_switch(context, self, complex_name,
680 code_lines, temp_vars,
683 switch_expr = _c_accessor_get_expr(self.expr, None)
685 for b in self.bitcases:
686 bitcase_expr = _c_accessor_get_expr(b.type.expr, None)
687 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
688 # code_lines.append(' printf("switch %s: entering bitcase section %s (mask=%%%%d)...\\n", %s);' %
689 # (self.name[-1], b.type.name[-1], bitcase_expr))
692 b_prefix = prefix + [(b.c_field_name, '.', b.type)]
694 count += _c_serialize_helper_fields(context, b.type,
695 code_lines, temp_vars,
699 code_lines.append(' }')
701 # if 'serialize' == context:
702 # count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
703 # elif context in ('unserialize', 'unpack', 'sizeof'):
705 # code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
706 # code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
709 # _c_serialize_helper_switch
711 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
713 handle switch by calling _serialize() or _unpack(), depending on context
715 # switch is handled by this function as a special case
716 param_fields, wire_fields, params = get_serialize_params(context, self)
717 field_mapping = _c_helper_field_mapping(self, prefix)
718 prefix_str = _c_helper_absolute_name(prefix)
720 # find the parameters that need to be passed to _serialize()/_unpack():
721 # all switch expr fields must be given as parameters
722 args = get_expr_fields(field.type)
723 # length fields for variable size types in switch, normally only some of need
724 # need to be passed as parameters
725 switch_len_fields = resolve_expr_fields(field.type)
727 # a switch field at this point _must_ be a bitcase field
728 # we require that bitcases are "self-contiguous"
729 bitcase_unresolved = resolve_expr_fields(self)
730 if len(bitcase_unresolved) != 0:
731 raise Exception('unresolved fields within bitcase is not supported at this point')
733 # get the C names for the parameters
735 for a in switch_len_fields:
736 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
738 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
740 # call _serialize()/_unpack() to determine the actual size
741 if 'serialize' == context:
742 length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
743 c_field_names, prefix_str, field.c_field_name)
744 elif context in ('unserialize', 'unpack'):
745 length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
746 c_field_names, prefix_str, field.c_field_name)
749 # _c_serialize_helper_switch_field()
751 def _c_serialize_helper_list_field(context, self, field,
752 code_lines, temp_vars,
755 helper function to cope with lists of variable length
757 expr = field.type.expr
758 prefix_str = _c_helper_absolute_name(prefix)
759 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
760 param_names = [p[2] for p in params]
762 expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
763 resolved = list(filter(lambda x: x in param_names, expr_fields_names))
764 unresolved = list(filter(lambda x: x not in param_names, expr_fields_names))
768 field_mapping[r] = (r, None)
770 if len(unresolved)>0:
772 if len(tmp_prefix)==0:
773 raise Exception("found an empty prefix while resolving expr field names for list %s",
776 field_mapping.update(_c_helper_resolve_field_names(prefix))
777 resolved += list(filter(lambda x: x in field_mapping, unresolved))
778 unresolved = list(filter(lambda x: x not in field_mapping, unresolved))
779 if len(unresolved)>0:
780 raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
782 list_length = _c_accessor_get_expr(expr, field_mapping)
784 # default: list with fixed size elements
785 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
787 # list with variable-sized elements
788 if not field.type.member.fixed_size():
790 if context in ('unserialize', 'sizeof', 'unpack'):
791 int_i = ' unsigned int i;'
792 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
793 if int_i not in temp_vars:
794 temp_vars.append(int_i)
795 if xcb_tmp_len not in temp_vars:
796 temp_vars.append(xcb_tmp_len)
797 # loop over all list elements and call sizeof repeatedly
798 # this should be a bit faster than using the iterators
799 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
800 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
801 (space, field.type.c_sizeof_name))
802 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
803 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
804 code_lines.append("%s }" % space)
806 elif 'serialize' == context:
807 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
808 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
809 code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length))
810 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
811 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
812 code_lines.append('%s }' % space)
813 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
816 # _c_serialize_helper_list_field()
818 def _c_serialize_helper_fields_fixed_size(context, self, field,
819 code_lines, temp_vars,
821 # keep the C code a bit more readable by giving the field name
822 if not self.is_bitcase:
823 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
825 scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
826 typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
827 code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
829 abs_field_name = _c_helper_absolute_name(prefix, field)
830 # default for simple cases: call sizeof()
831 length = "sizeof(%s)" % field.c_field_type
833 if context in ('unserialize', 'unpack', 'sizeof'):
834 # default: simple cast
835 value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
837 # padding - we could probably just ignore it
838 if field.type.is_pad and field.type.nmemb > 1:
840 for i in range(field.type.nmemb):
841 code_lines.append('%s %s[%d] = *(%s *)xcb_tmp;' %
842 (space, abs_field_name, i, field.c_field_type))
843 # total padding = sizeof(pad0) * nmemb
844 length += " * %d" % field.type.nmemb
846 if field.type.is_list:
847 # no such case in the protocol, cannot be tested and therefore ignored for now
848 raise Exception('list with fixed number of elemens unhandled in _unserialize()')
850 elif 'serialize' == context:
851 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
853 if field.type.is_expr:
854 # need to register a temporary variable for the expression in case we know its type
855 if field.type.c_type is None:
856 raise Exception("type for field '%s' (expression '%s') unkown" %
857 (field.field_name, _c_accessor_get_expr(field.type.expr)))
859 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
860 _c_accessor_get_expr(field.type.expr, prefix)))
861 value += "&xcb_expr_%s;" % _cpp(field.field_name)
863 elif field.type.is_pad:
864 if field.type.nmemb == 1:
867 # we could also set it to 0, see definition of xcb_send_request()
868 value = ' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
869 length += "*%d" % field.type.nmemb
872 # non-list type with fixed size
873 if field.type.nmemb == 1:
874 value += "&%s;" % (abs_field_name)
876 # list with nmemb (fixed size) elements
878 value += '%s;' % (abs_field_name)
879 length = '%d' % field.type.nmemb
881 return (value, length)
882 # _c_serialize_helper_fields_fixed_size()
884 def _c_serialize_helper_fields_variable_size(context, self, field,
885 code_lines, temp_vars,
887 prefix_str = _c_helper_absolute_name(prefix)
889 if context in ('unserialize', 'unpack', 'sizeof'):
891 var_field_name = 'xcb_tmp'
893 # special case: intermixed fixed and variable size fields
894 if self.var_followed_by_fixed_fields and 'unserialize' == context:
895 value = ' %s = (%s *)xcb_tmp;' % (field.c_field_name, field.c_field_type)
896 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
897 # special case: switch
898 if 'unpack' == context:
899 value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
901 elif 'serialize' == context:
902 # variable size fields appear as parameters to _serialize() if the
903 # 'toplevel' container is not a switch
904 prefix_string = prefix_str if prefix[0][2].is_switch else ''
905 var_field_name = "%s%s" % (prefix_string, field.c_field_name)
906 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
910 code_lines.append('%s /* %s */' % (space, field.c_field_name))
912 if field.type.is_list:
914 # in any context, list is already a pointer, so the default assignment is ok
915 code_lines.append("%s%s" % (space, value))
917 length = _c_serialize_helper_list_field(context, self, field,
918 code_lines, temp_vars,
921 elif field.type.is_switch:
923 if context == 'serialize':
924 # the _serialize() function allocates the correct amount memory if given a NULL pointer
925 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
926 length = _c_serialize_helper_switch_field(context, self, field,
927 'xcb_parts[xcb_parts_idx].iov_base',
931 # in all remaining special cases - call _sizeof()
932 length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
934 return (value, length)
935 # _c_serialize_helper_fields_variable_size
937 def _c_serialize_helper_fields(context, self,
938 code_lines, temp_vars,
939 space, prefix, is_bitcase):
942 prev_field_was_variable = False
944 for field in self.fields:
945 if not field.visible:
946 if not ((field.wire and not field.auto) or 'unserialize' == context):
949 # switch/bitcase: fixed size fields must be considered explicitly
950 if field.type.fixed_size():
951 if self.is_bitcase or self.var_followed_by_fixed_fields:
952 if prev_field_was_variable and need_padding:
954 # count += _c_serialize_helper_insert_padding(context, code_lines, space,
955 # self.var_followed_by_fixed_fields)
956 prev_field_was_variable = False
958 # prefix for fixed size fields
959 fixed_prefix = prefix
961 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
962 code_lines, temp_vars,
967 # fields with variable size
969 # switch/bitcase: always calculate padding before and after variable sized fields
970 if need_padding or is_bitcase:
971 count += _c_serialize_helper_insert_padding(context, code_lines, space,
972 self.var_followed_by_fixed_fields)
974 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
975 code_lines, temp_vars,
977 prev_field_was_variable = True
979 # save (un)serialization C code
981 code_lines.append('%s%s' % (space, value))
983 if field.type.fixed_size():
984 if is_bitcase or self.var_followed_by_fixed_fields:
985 # keep track of (un)serialized object's size
986 code_lines.append('%s xcb_block_len += %s;' % (space, length))
987 if context in ('unserialize', 'unpack', 'sizeof'):
988 code_lines.append('%s xcb_tmp += %s;' % (space, length))
990 # variable size objects or bitcase:
991 # value & length might have been inserted earlier for special cases
993 # special case: intermixed fixed and variable size fields
994 if (not field.type.fixed_size() and
995 self.var_followed_by_fixed_fields and 'unserialize' == context):
996 temp_vars.append(' int %s_len;' % field.c_field_name)
997 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
998 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
999 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
1001 code_lines.append('%s xcb_block_len += %s;' % (space, length))
1002 # increase pointer into the byte stream accordingly
1003 if context in ('unserialize', 'sizeof', 'unpack'):
1004 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1006 if 'serialize' == context:
1008 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
1009 code_lines.append('%s xcb_parts_idx++;' % space)
1012 code_lines.append('%s xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type))
1015 if self.var_followed_by_fixed_fields:
1016 need_padding = False
1019 # _c_serialize_helper_fields()
1021 def _c_serialize_helper(context, complex_type,
1022 code_lines, temp_vars,
1023 space='', prefix=[]):
1024 # count tracks the number of fields to serialize
1027 if hasattr(complex_type, 'type'):
1028 self = complex_type.type
1029 complex_name = complex_type.name
1032 if self.var_followed_by_fixed_fields and 'unserialize' == context:
1033 complex_name = 'xcb_out'
1035 complex_name = '_aux'
1037 # special case: switch is serialized by evaluating each bitcase separately
1039 count += _c_serialize_helper_switch(context, self, complex_name,
1040 code_lines, temp_vars,
1043 # all other data types can be evaluated one field a time
1045 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1046 if context in ('unserialize', 'unpack', 'sizeof') and not self.var_followed_by_fixed_fields:
1047 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1048 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1049 # probably not needed
1050 #_c_serialize_helper_insert_padding(context, code_lines, space, False)
1052 count += _c_serialize_helper_fields(context, self,
1053 code_lines, temp_vars,
1054 space, prefix, False)
1056 count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
1059 # _c_serialize_helper()
1061 def _c_serialize(context, self):
1063 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1064 for the ComplexType variable self
1070 # _serialize() returns the buffer size
1073 if self.is_switch and 'unserialize' == context:
1076 cases = { 'serialize' : self.c_serialize_name,
1077 'unserialize' : self.c_unserialize_name,
1078 'unpack' : self.c_unpack_name,
1079 'sizeof' : self.c_sizeof_name }
1080 func_name = cases[context]
1082 param_fields, wire_fields, params = get_serialize_params(context, self)
1083 variable_size_fields = 0
1084 # maximum space required for type definition of function arguments
1087 # determine N(variable_fields)
1088 for field in param_fields:
1089 # if self.is_switch, treat all fields as if they are variable sized
1090 if not field.type.fixed_size() or self.is_switch:
1091 variable_size_fields += 1
1092 # determine maxtypelen
1094 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1097 indent = ' '*(len(func_name)+2)
1100 typespec, pointerspec, field_name = p
1101 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1102 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1103 # insert function name
1104 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1105 param_str = list(map(lambda x: "%s," % x, param_str))
1106 for s in param_str[:-1]:
1108 _h("%s);" % param_str[-1].rstrip(','))
1109 _c("%s)" % param_str[-1].rstrip(','))
1116 if 'serialize' == context:
1117 if not self.is_switch and not self.var_followed_by_fixed_fields:
1118 _c(' %s *xcb_out = *_buffer;', self.c_type)
1119 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1120 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1121 _c(' unsigned int xcb_align_to;')
1123 _c(' char *xcb_out = *_buffer;')
1124 _c(' unsigned int xcb_buffer_len = 0;')
1125 _c(' unsigned int xcb_align_to;')
1126 prefix = [('_aux', '->', self)]
1129 elif context in ('unserialize', 'unpack'):
1130 _c(' char *xcb_tmp = (char *)_buffer;')
1131 if not self.is_switch:
1132 if not self.var_followed_by_fixed_fields:
1133 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1134 prefix = [('_aux', '->', self)]
1136 _c(' %s xcb_out;', self.c_type)
1137 prefix = [('xcb_out', '.', self)]
1139 aux_var = '_aux' # default for unpack: single pointer
1140 # note: unserialize not generated for switch
1141 if 'unserialize' == context:
1142 aux_var = '(*_aux)' # unserialize: double pointer (!)
1143 prefix = [(aux_var, '->', self)]
1145 _c(' unsigned int xcb_buffer_len = 0;')
1146 _c(' unsigned int xcb_block_len = 0;')
1147 _c(' unsigned int xcb_pad = 0;')
1148 _c(' unsigned int xcb_align_to;')
1150 elif 'sizeof' == context:
1151 param_names = [p[2] for p in params]
1153 # switch: call _unpack()
1154 _c(' %s _aux;', self.c_type)
1155 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1158 elif self.var_followed_by_fixed_fields:
1159 # special case: call _unserialize()
1160 _c(' return %s(%s, NULL);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1164 _c(' char *xcb_tmp = (char *)_buffer;')
1165 prefix = [('_aux', '->', self)]
1167 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1168 # update variable size fields (only important for context=='serialize'
1169 variable_size_fields = count
1170 if 'serialize' == context:
1171 temp_vars.append(' unsigned int xcb_pad = 0;')
1172 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1173 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1174 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1175 temp_vars.append(' unsigned int xcb_block_len = 0;')
1176 temp_vars.append(' unsigned int i;')
1177 temp_vars.append(' char *xcb_tmp;')
1178 elif 'sizeof' == context:
1179 # neither switch nor intermixed fixed and variable size fields:
1180 # evaluate parameters directly
1181 if not (self.is_switch or self.var_followed_by_fixed_fields):
1183 # look if we have to declare an '_aux' variable at all
1184 if len(list(filter(lambda x: x.find('_aux')!=-1, code_lines)))>0:
1185 if not self.var_followed_by_fixed_fields:
1186 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1188 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1190 _c(' unsigned int xcb_buffer_len = 0;')
1191 _c(' unsigned int xcb_block_len = 0;')
1192 _c(' unsigned int xcb_pad = 0;')
1193 _c(' unsigned int xcb_align_to;')
1199 for l in code_lines:
1202 # variable sized fields have been collected, now
1203 # allocate memory and copy everything into a continuous memory area
1204 # note: this is not necessary in case of unpack
1205 if context in ('serialize', 'unserialize'):
1206 # unserialize: check for sizeof-only invocation
1207 if 'unserialize' == context:
1209 _c(' if (NULL == _aux)')
1210 _c(' return xcb_buffer_len;')
1213 _c(' if (NULL == %s) {', aux_ptr)
1214 _c(' /* allocate memory */')
1215 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1216 if 'serialize' == context:
1217 _c(' *_buffer = xcb_out;')
1221 # serialize: handle variable size fields in a loop
1222 if 'serialize' == context:
1223 if not self.is_switch and not self.var_followed_by_fixed_fields:
1224 if len(wire_fields)>0:
1225 _c(' *xcb_out = *_aux;')
1226 # copy variable size fields into the buffer
1227 if variable_size_fields > 0:
1229 if not self.is_switch and not self.var_followed_by_fixed_fields:
1230 _c(' xcb_tmp = (char*)++xcb_out;')
1231 _c(' xcb_tmp += xcb_out_pad;')
1233 _c(' xcb_tmp = xcb_out;')
1235 # variable sized fields
1236 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1237 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1238 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1239 _c(' if (0 != xcb_parts[i].iov_len)')
1240 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1243 # unserialize: assign variable size fields individually
1244 if 'unserialize' == context:
1245 _c(' xcb_tmp = ((char *)*_aux)+xcb_buffer_len;')
1246 param_fields.reverse()
1247 for field in param_fields:
1248 if not field.type.fixed_size():
1249 _c(' xcb_tmp -= %s_len;', field.c_field_name)
1250 _c(' memmove(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1251 _c(' *%s = xcb_out;', aux_ptr)
1254 _c(' return xcb_buffer_len;')
1258 def _c_iterator_get_end(field, accum):
1260 Figures out what C code is needed to find the end of a variable-length structure field.
1261 For nested structures, recurses into its last variable-sized field.
1262 For lists, calls the end function
1264 if field.type.is_container:
1265 accum = field.c_accessor_name + '(' + accum + ')'
1266 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1267 if field.type.is_list:
1268 # XXX we can always use the first way
1269 if field.type.member.is_simple:
1270 return field.c_end_name + '(' + accum + ')'
1272 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1274 def _c_iterator(self, name):
1276 Declares the iterator structure and next/end functions for a given type.
1281 _h(' * @brief %s', self.c_iterator_type)
1283 _h('typedef struct %s {', self.c_iterator_type)
1284 _h(' %s *data; /**< */', self.c_type)
1285 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1286 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1287 _h('} %s;', self.c_iterator_type)
1293 _h(' * Get the next element of the iterator')
1294 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1296 _h(' * Get the next element in the iterator. The member rem is')
1297 _h(' * decreased by one. The member data points to the next')
1298 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1302 _hc('/*****************************************************************************')
1304 _hc(' ** void %s', self.c_next_name)
1306 _hc(' ** @param %s *i', self.c_iterator_type)
1307 _hc(' ** @returns void')
1309 _hc(' *****************************************************************************/')
1312 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1313 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1316 if not self.fixed_size():
1317 _c(' %s *R = i->data;', self.c_type)
1320 # FIXME - how to determine the size of a variable size union??
1321 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1323 if self.need_sizeof:
1324 _c(' xcb_generic_iterator_t child;')
1325 _c(' child.data = (%s *)(((char *)R) + %s(R));',
1326 self.c_type, self.c_sizeof_name)
1327 _c(' i->index = (char *) child.data - (char *) i->data;')
1329 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1330 _c(' i->index = child.index;')
1332 _c(' i->data = (%s *) child.data;', self.c_type)
1337 _c(' i->index += sizeof(%s);', self.c_type)
1343 _h(' * Return the iterator pointing to the last element')
1344 _h(' * @param i An %s', self.c_iterator_type)
1345 _h(' * @return The iterator pointing to the last element')
1347 _h(' * Set the current element in the iterator to the last element.')
1348 _h(' * The member rem is set to 0. The member data points to the')
1349 _h(' * last element.')
1353 _hc('/*****************************************************************************')
1355 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1357 _hc(' ** @param %s i', self.c_iterator_type)
1358 _hc(' ** @returns xcb_generic_iterator_t')
1360 _hc(' *****************************************************************************/')
1362 _hc('xcb_generic_iterator_t')
1363 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1364 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1366 _c(' xcb_generic_iterator_t ret;')
1368 if self.fixed_size():
1369 _c(' ret.data = i.data + i.rem;')
1370 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1373 _c(' while(i.rem > 0)')
1374 _c(' %s(&i);', self.c_next_name)
1375 _c(' ret.data = i.data;')
1376 _c(' ret.rem = i.rem;')
1377 _c(' ret.index = i.index;')
1382 def _c_accessor_get_length(expr, field_mapping=None):
1384 Figures out what C code is needed to get a length field.
1385 The field_mapping parameter can be used to change the absolute name of a length field.
1386 For fields that follow a variable-length field, use the accessor.
1387 Otherwise, just reference the structure field directly.
1390 lenfield_name = expr.lenfield_name
1391 if lenfield_name is not None:
1392 if field_mapping is not None:
1393 lenfield_name = field_mapping[lenfield_name][0]
1395 if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1396 # special case: variable and fixed size fields are intermixed
1397 # if the lenfield is among the fixed size fields, there is no need
1398 # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1399 return field_mapping(expr.lenfield_name)
1400 elif expr.lenfield_name is not None:
1401 return lenfield_name
1403 return str(expr.nmemb)
1405 def _c_accessor_get_expr(expr, field_mapping):
1407 Figures out what C code is needed to get the length of a list field.
1408 The field_mapping parameter can be used to change the absolute name of a length field.
1409 Recurses for math operations.
1410 Returns bitcount for value-mask fields.
1411 Otherwise, uses the value of the length field.
1413 lenexp = _c_accessor_get_length(expr, field_mapping)
1416 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1417 elif expr.op == 'popcount':
1418 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1419 elif expr.op == 'enumref':
1420 enum_name = expr.lenfield_type.name
1421 constant_name = expr.lenfield_name
1422 c_name = _n(enum_name + (constant_name,)).upper()
1424 elif expr.op == 'sumof':
1425 # locate the referenced list object
1426 list_obj = expr.lenfield_type
1428 for f in expr.lenfield_parent.fields:
1429 if f.field_name == expr.lenfield_name:
1434 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1435 list_name = field_mapping[field.c_field_name][0]
1436 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1437 # note: xcb_sumof() has only been defined for integers
1438 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1439 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1440 elif expr.op != None:
1441 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1442 ' ' + expr.op + ' ' +
1443 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1445 return 'xcb_popcount(' + lenexp + ')'
1449 def type_pad_type(type):
1454 def _c_accessors_field(self, field):
1456 Declares the accessor functions for a non-list field that follows a variable-length field.
1458 c_type = self.c_type
1460 # special case: switch
1461 switch_obj = self if self.is_switch else None
1463 switch_obj = self.parents[-1]
1464 if switch_obj is not None:
1465 c_type = switch_obj.c_type
1467 if field.type.is_simple:
1470 _hc('/*****************************************************************************')
1472 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1474 _hc(' ** @param const %s *R', c_type)
1475 _hc(' ** @returns %s', field.c_field_type)
1477 _hc(' *****************************************************************************/')
1479 _hc('%s', field.c_field_type)
1480 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1481 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1483 if field.prev_varsized_field is None:
1484 _c(' return (%s *) (R + 1);', field.c_field_type)
1486 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1487 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1488 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1493 _hc('/*****************************************************************************')
1495 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1497 _hc(' ** @param const %s *R', c_type)
1498 _hc(' ** @returns %s *', field.c_field_type)
1500 _hc(' *****************************************************************************/')
1502 if field.type.is_switch and switch_obj is None:
1503 return_type = 'void *'
1505 return_type = '%s *' % field.c_field_type
1508 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1509 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1511 if field.prev_varsized_field is None:
1512 _c(' return (%s) (R + 1);', return_type)
1513 # note: the special case 'variable fields followed by fixed size fields'
1514 # is not of any consequence here, since the ordering gets
1515 # 'corrected' in the reply function
1517 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1518 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1519 return_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1523 def _c_accessors_list(self, field):
1525 Declares the accessor functions for a list field.
1526 Declares a direct-accessor function only if the list members are fixed size.
1527 Declares length and get-iterator functions always.
1530 c_type = self.c_type
1532 # special case: switch
1533 # in case of switch, 2 params have to be supplied to certain accessor functions:
1534 # 1. the anchestor object (request or reply)
1535 # 2. the (anchestor) switch object
1536 # the reason is that switch is either a child of a request/reply or nested in another switch,
1537 # so whenever we need to access a length field, we might need to refer to some anchestor type
1538 switch_obj = self if self.is_switch else None
1540 switch_obj = self.parents[-1]
1541 if switch_obj is not None:
1542 c_type = switch_obj.c_type
1546 parents = self.parents if hasattr(self, 'parents') else [self]
1547 # 'R': parents[0] is always the 'toplevel' container type
1548 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1549 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1550 # auxiliary object for 'R' parameters
1553 if switch_obj is not None:
1554 # now look where the fields are defined that are needed to evaluate
1555 # the switch expr, and store the parent objects in accessor_params and
1556 # the fields in switch_fields
1558 # 'S': name for the 'toplevel' switch
1559 toplevel_switch = parents[1]
1560 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1561 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1563 # initialize prefix for everything "below" S
1564 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1565 prefix = [(prefix_str, '->', toplevel_switch)]
1567 # look for fields in the remaining containers
1568 for p in parents[2:] + [self]:
1569 # the separator between parent and child is always '.' here,
1570 # because of nested switch statements
1571 if not p.is_bitcase or (p.is_bitcase and p.has_name):
1572 prefix.append((p.name[-1], '.', p))
1573 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1575 # auxiliary object for 'S' parameter
1580 if list.member.fixed_size():
1581 idx = 1 if switch_obj is not None else 0
1584 _hc('/*****************************************************************************')
1586 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1588 _hc(' ** @param %s', params[idx][0])
1589 _hc(' ** @returns %s *', field.c_field_type)
1591 _hc(' *****************************************************************************/')
1593 _hc('%s *', field.c_field_type)
1595 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1596 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1599 if switch_obj is not None:
1600 _c(' return %s;', fields[field.c_field_name][0])
1601 elif field.prev_varsized_field is None:
1602 _c(' return (%s *) (R + 1);', field.c_field_type)
1604 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1605 _c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1606 field.c_field_type, type_pad_type(field.first_field_after_varsized.type.c_type), field.prev_varsized_offset)
1611 _hc('/*****************************************************************************')
1613 _hc(' ** int %s', field.c_length_name)
1615 _hc(' ** @param const %s *R', c_type)
1616 _hc(' ** @returns int')
1618 _hc(' *****************************************************************************/')
1621 if switch_obj is not None:
1622 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1623 spacing = ' '*(len(field.c_length_name)+2)
1624 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1625 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1626 length = _c_accessor_get_expr(field.type.expr, fields)
1628 _h('%s (const %s *R /**< */);', field.c_length_name, c_type)
1629 _c('%s (const %s *R /**< */)', field.c_length_name, c_type)
1630 length = _c_accessor_get_expr(field.type.expr, fields)
1632 _c(' return %s;', length)
1635 if field.type.member.is_simple:
1638 _hc('/*****************************************************************************')
1640 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1642 _hc(' ** @param const %s *R', c_type)
1643 _hc(' ** @returns xcb_generic_iterator_t')
1645 _hc(' *****************************************************************************/')
1647 _hc('xcb_generic_iterator_t')
1648 if switch_obj is not None:
1649 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1650 spacing = ' '*(len(field.c_end_name)+2)
1651 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1652 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1654 _h('%s (const %s *R /**< */);', field.c_end_name, c_type)
1655 _c('%s (const %s *R /**< */)', field.c_end_name, c_type)
1657 _c(' xcb_generic_iterator_t i;')
1659 param = 'R' if switch_obj is None else 'S'
1660 if switch_obj is not None:
1661 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1662 _c_accessor_get_expr(field.type.expr, fields))
1663 elif field.prev_varsized_field == None:
1664 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1665 _c_accessor_get_expr(field.type.expr, fields))
1667 _c(' xcb_generic_iterator_t child = %s;',
1668 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1669 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1670 _c_accessor_get_expr(field.type.expr, fields))
1673 _c(' i.index = (char *) i.data - (char *) %s;', param)
1680 _hc('/*****************************************************************************')
1682 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1684 _hc(' ** @param const %s *R', c_type)
1685 _hc(' ** @returns %s', field.c_iterator_type)
1687 _hc(' *****************************************************************************/')
1690 _hc('%s', field.c_iterator_type)
1691 if switch_obj is not None:
1692 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1693 spacing = ' '*(len(field.c_iterator_name)+2)
1694 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1695 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1697 _h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
1698 _c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
1700 _c(' %s i;', field.c_iterator_type)
1702 if switch_obj is not None:
1703 _c(' i.data = %s;', fields[field.c_field_name][0])
1704 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1705 elif field.prev_varsized_field == None:
1706 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1708 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1709 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));',
1710 field.c_field_type, type_pad_type(field.c_field_type))
1711 if switch_obj is None:
1712 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1713 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1717 def _c_accessors(self, name, base):
1719 Declares the accessor functions for the fields of a structure.
1721 # no accessors for switch itself -
1722 # switch always needs to be unpacked explicitly
1723 # if self.is_switch:
1727 for field in self.fields:
1728 if field.type.is_list and not field.type.fixed_size():
1729 _c_accessors_list(self, field)
1730 elif field.prev_varsized_field is not None or not field.type.fixed_size():
1731 _c_accessors_field(self, field)
1733 def c_simple(self, name):
1735 Exported function that handles cardinal type declarations.
1736 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1738 _c_type_setup(self, name, ())
1740 if (self.name != name):
1745 _h('typedef %s %s;', _t(self.name), my_name)
1748 _c_iterator(self, name)
1750 def _c_complex(self):
1752 Helper function for handling all structure types.
1753 Called for all structs, requests, replies, events, errors.
1758 _h(' * @brief %s', self.c_type)
1760 _h('typedef %s %s {', self.c_container, self.c_type)
1766 for field in self.fields:
1767 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1768 varfield = field.c_field_name
1771 struct_fields.append(field)
1773 for field in struct_fields:
1774 length = len(field.c_field_type)
1775 # account for '*' pointer_spec
1776 if not field.type.fixed_size():
1778 maxtypelen = max(maxtypelen, length)
1780 def _c_complex_field(self, field, space=''):
1781 if (field.type.fixed_size() or
1782 # in case of switch with switch children, don't make the field a pointer
1783 # necessary for unserialize to work
1784 (self.is_switch and field.type.is_switch)):
1785 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1786 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1788 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1789 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1791 if not self.is_switch:
1792 for field in struct_fields:
1793 _c_complex_field(self, field)
1795 for b in self.bitcases:
1798 _h(' struct _%s {', b.c_field_name)
1800 for field in b.type.fields:
1801 _c_complex_field(self, field, space)
1803 _h(' } %s;', b.c_field_name)
1805 _h('} %s;', self.c_type)
1807 def c_struct(self, name):
1809 Exported function that handles structure declarations.
1811 _c_type_setup(self, name, ())
1813 _c_accessors(self, name, name)
1814 _c_iterator(self, name)
1816 def c_union(self, name):
1818 Exported function that handles union declarations.
1820 _c_type_setup(self, name, ())
1822 _c_iterator(self, name)
1824 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1826 Declares a request function.
1829 # Four stunningly confusing possibilities here:
1832 # ------------------------------
1834 # 0 flag CHECKED flag Normal Mode
1835 # void_cookie req_cookie
1836 # ------------------------------
1837 # "req_checked" "req_unchecked"
1838 # CHECKED flag 0 flag Abnormal Mode
1839 # void_cookie req_cookie
1840 # ------------------------------
1843 # Whether we are _checked or _unchecked
1844 checked = void and not regular
1845 unchecked = not void and not regular
1847 # What kind of cookie we return
1848 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1850 # What flag is passed to xcb_request
1851 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1853 # Global extension id variable or NULL for xproto
1854 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1856 # What our function name is
1857 func_name = self.c_request_name if not aux else self.c_aux_name
1859 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1861 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1865 maxtypelen = len('xcb_connection_t')
1867 # special case: list with variable size elements
1868 list_with_var_size_elems = False
1870 for field in self.fields:
1872 # The field should appear as a call parameter
1873 param_fields.append(field)
1874 if field.wire and not field.auto:
1875 # We need to set the field up in the structure
1876 wire_fields.append(field)
1877 if field.type.need_serialize or field.type.need_sizeof:
1878 serial_fields.append(field)
1880 for field in param_fields:
1881 c_field_const_type = field.c_field_const_type
1882 if field.type.need_serialize and not aux:
1883 c_field_const_type = "const void"
1884 if len(c_field_const_type) > maxtypelen:
1885 maxtypelen = len(c_field_const_type)
1886 if field.type.is_list and not field.type.member.fixed_size():
1887 list_with_var_size_elems = True
1895 _h(' * @brief ' + self.doc.brief)
1897 _h(' * No brief doc yet')
1900 _h(' * @param c The connection')
1901 param_names = [f.c_field_name for f in param_fields]
1903 for field in param_fields:
1904 # XXX: hard-coded until we fix xproto.xml
1905 base_func_name = self.c_request_name if not aux else self.c_aux_name
1906 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
1908 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
1910 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
1913 # XXX: why the 'xcb' prefix?
1914 key = ('xcb', field.enum)
1917 if namecount[tname] > 1:
1918 tname = _t(key + ('enum',))
1919 _h(' * @param %s A bitmask of #%s values.' % (field.c_field_name, tname))
1921 if self.doc and field.field_name in self.doc.fields:
1922 desc = self.doc.fields[field.field_name]
1923 for name in param_names:
1924 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1925 desc = desc.split("\n")
1926 desc = [line if line != '' else '\\n' for line in desc]
1927 _h(' * @param %s %s' % (field.c_field_name, "\n * ".join(desc)))
1928 # If there is no documentation yet, we simply don't generate an
1929 # @param tag. Doxygen will then warn about missing documentation.
1931 _h(' * @return A cookie')
1935 if self.doc.description:
1936 desc = self.doc.description
1937 for name in param_names:
1938 desc = desc.replace('`%s`' % name, '\\a %s' % (name))
1939 desc = desc.split("\n")
1940 _h(' * ' + "\n * ".join(desc))
1942 _h(' * No description yet')
1944 _h(' * Delivers a request to the X server.')
1947 _h(' * This form can be used only if the request will not cause')
1948 _h(' * a reply to be generated. Any returned error will be')
1949 _h(' * saved for handling by xcb_request_check().')
1951 _h(' * This form can be used only if the request will cause')
1952 _h(' * a reply to be generated. Any returned error will be')
1953 _h(' * placed in the event queue.')
1957 _hc('/*****************************************************************************')
1959 _hc(' ** %s %s', cookie_type, func_name)
1962 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1963 _hc(' ** @param xcb_connection_t%s *c', spacing)
1965 for field in param_fields:
1966 c_field_const_type = field.c_field_const_type
1967 if field.type.need_serialize and not aux:
1968 c_field_const_type = "const void"
1969 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1970 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1972 _hc(' ** @returns %s', cookie_type)
1974 _hc(' *****************************************************************************/')
1976 _hc('%s', cookie_type)
1978 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1979 comma = ',' if len(param_fields) else ');'
1980 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1981 comma = ',' if len(param_fields) else ')'
1982 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1984 func_spacing = ' ' * (len(func_name) + 2)
1985 count = len(param_fields)
1986 for field in param_fields:
1988 c_field_const_type = field.c_field_const_type
1989 c_pointer = field.c_pointer
1990 if field.type.need_serialize and not aux:
1991 c_field_const_type = "const void"
1993 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1994 comma = ',' if count else ');'
1995 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1996 spacing, c_pointer, field.c_field_name, comma)
1997 comma = ',' if count else ')'
1998 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1999 spacing, c_pointer, field.c_field_name, comma)
2002 if not self.var_followed_by_fixed_fields:
2003 for field in param_fields:
2004 if not field.type.fixed_size():
2006 if field.type.need_serialize:
2007 # _serialize() keeps track of padding automatically
2009 dimension = count + 2
2012 _c(' static const xcb_protocol_request_t xcb_req = {')
2013 _c(' /* count */ %d,', count)
2014 _c(' /* ext */ %s,', func_ext_global)
2015 _c(' /* opcode */ %s,', self.c_request_name.upper())
2016 _c(' /* isvoid */ %d', 1 if void else 0)
2020 _c(' struct iovec xcb_parts[%d];', dimension)
2021 _c(' %s xcb_ret;', func_cookie)
2022 _c(' %s xcb_out;', self.c_type)
2023 if self.var_followed_by_fixed_fields:
2024 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
2025 _c(' void *xcb_aux = 0;')
2028 for idx, f in enumerate(serial_fields):
2030 _c(' void *xcb_aux%d = 0;' % (idx))
2031 if list_with_var_size_elems:
2032 _c(' unsigned int i;')
2033 _c(' unsigned int xcb_tmp_len;')
2034 _c(' char *xcb_tmp;')
2036 # simple request call tracing
2037 # _c(' printf("in function %s\\n");' % func_name)
2040 for field in wire_fields:
2041 if field.type.fixed_size():
2042 if field.type.is_expr:
2043 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
2044 elif field.type.is_pad:
2045 if field.type.nmemb == 1:
2046 _c(' xcb_out.%s = 0;', field.c_field_name)
2048 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
2050 if field.type.nmemb == 1:
2051 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
2053 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
2055 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
2056 serialize_args = get_serialize_params(context, type_obj,
2059 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
2061 # calls in order to free dyn. all. memory
2065 if not self.var_followed_by_fixed_fields:
2066 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2067 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
2068 _c(' xcb_parts[3].iov_base = 0;')
2069 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
2073 for field in param_fields:
2074 if not field.type.fixed_size():
2075 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
2076 # default: simple cast to char *
2077 if not field.type.need_serialize and not field.type.need_sizeof:
2078 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2079 if field.type.is_list:
2080 if field.type.member.fixed_size():
2081 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
2082 _c_accessor_get_expr(field.type.expr, None),
2083 field.type.member.c_wiretype)
2085 list_length = _c_accessor_get_expr(field.type.expr, None)
2088 _c(" xcb_parts[%d].iov_len = 0;" % count)
2089 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2090 _c(" for(i=0; i<%s; i++) {" % list_length)
2091 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2092 (field.type.c_sizeof_name))
2093 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2094 _c(" xcb_tmp += xcb_tmp_len;")
2097 # not supposed to happen
2098 raise Exception("unhandled variable size field %s" % field.c_field_name)
2101 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2102 idx = serial_fields.index(field)
2103 aux_var = '&xcb_aux%d' % idx
2104 context = 'serialize' if aux else 'sizeof'
2105 _c(' xcb_parts[%d].iov_len = ', count)
2107 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2108 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2109 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2110 free_calls.append(' free(xcb_aux%d);' % idx)
2112 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2113 func_name = field.type.c_sizeof_name
2114 _c(' %s (%s);', func_name, serialize_args)
2117 if not (field.type.need_serialize or field.type.need_sizeof):
2118 # the _serialize() function keeps track of padding automatically
2119 _c(' xcb_parts[%d].iov_base = 0;', count)
2120 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2123 # elif self.var_followed_by_fixed_fields:
2125 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2126 # request header: opcodes + length
2127 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2130 buffer_var = '&xcb_aux'
2131 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2132 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2133 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2134 free_calls.append(' free(xcb_aux);')
2135 # no padding necessary - _serialize() keeps track of padding automatically
2138 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2140 # free dyn. all. data, if any
2141 for f in free_calls:
2143 _c(' return xcb_ret;')
2146 def _c_reply(self, name):
2148 Declares the function that returns the reply structure.
2150 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2151 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2152 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2154 # check if _unserialize() has to be called for any field
2155 def look_for_special_cases(complex_obj):
2156 unserialize_fields = []
2157 # no unserialize call in case of switch
2158 if not complex_obj.is_switch:
2159 for field in complex_obj.fields:
2160 # three cases: 1. field with special case
2161 # 2. container that contains special case field
2162 # 3. list with special case elements
2163 if field.type.var_followed_by_fixed_fields:
2164 unserialize_fields.append(field)
2165 elif field.type.is_container:
2166 unserialize_fields += look_for_special_cases(field.type)
2167 elif field.type.is_list:
2168 if field.type.member.var_followed_by_fixed_fields:
2169 unserialize_fields.append(field)
2170 if field.type.member.is_container:
2171 unserialize_fields += look_for_special_cases(field.type.member)
2172 return unserialize_fields
2174 unserialize_fields = look_for_special_cases(self.reply)
2178 _h(' * Return the reply')
2179 _h(' * @param c The connection')
2180 _h(' * @param cookie The cookie')
2181 _h(' * @param e The xcb_generic_error_t supplied')
2183 _h(' * Returns the reply of the request asked by')
2185 _h(' * The parameter @p e supplied to this function must be NULL if')
2186 _h(' * %s(). is used.', self.c_unchecked_name)
2187 _h(' * Otherwise, it stores the error if any.')
2189 _h(' * The returned value must be freed by the caller using free().')
2193 _hc('/*****************************************************************************')
2195 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
2197 _hc(' ** @param xcb_connection_t%s *c', spacing1)
2198 _hc(' ** @param %s cookie', self.c_cookie_type)
2199 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
2200 _hc(' ** @returns %s *', self.c_reply_type)
2202 _hc(' *****************************************************************************/')
2204 _hc('%s *', self.c_reply_type)
2205 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2206 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2207 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2208 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2211 if len(unserialize_fields)>0:
2212 # certain variable size fields need to be unserialized explicitly
2213 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2214 self.c_reply_type, self.c_reply_type)
2216 for field in unserialize_fields:
2217 if field.type.is_list:
2218 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2219 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2220 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2222 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2223 # call _unserialize(), using the reply as source and target buffer
2224 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2225 for field in unserialize_fields:
2226 if field.type.is_list:
2227 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2228 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2229 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2230 field.c_field_name, field.c_field_name)
2231 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2233 # return the transformed reply
2234 _c(' return reply;')
2237 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2241 def _c_opcode(name, opcode):
2243 Declares the opcode define for requests, events, and errors.
2247 _h('/** Opcode for %s. */', _n(name))
2248 _h('#define %s %s', _n(name).upper(), opcode)
2250 def _c_cookie(self, name):
2252 Declares the cookie type for a non-void request.
2257 _h(' * @brief %s', self.c_cookie_type)
2259 _h('typedef struct %s {', self.c_cookie_type)
2260 _h(' unsigned int sequence; /**< */')
2261 _h('} %s;', self.c_cookie_type)
2263 def _man_request(self, name, cookie_type, void, aux):
2264 param_fields = [f for f in self.fields if f.visible]
2266 func_name = self.c_request_name if not aux else self.c_aux_name
2268 def create_link(linkname):
2269 name = 'man/%s.3' % linkname
2271 sys.stdout.write(name)
2273 f.write('.so man3/%s.3' % func_name)
2277 sys.stdout.write('man/%s.3 ' % func_name)
2278 # Our CWD is src/, so this will end up in src/man/
2279 f = open('man/%s.3' % func_name, 'w')
2280 f.write('.TH %s 3 %s "XCB" "XCB Requests"\n' % (func_name, today))
2281 # Left-adjust instead of adjusting to both sides
2283 f.write('.SH NAME\n')
2284 brief = self.doc.brief if self.doc else ''
2285 f.write('%s \\- %s\n' % (func_name, brief))
2286 f.write('.SH SYNOPSIS\n')
2287 # Don't split words (hyphenate)
2289 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2291 # function prototypes
2293 count = len(param_fields)
2294 for field in param_fields:
2296 c_field_const_type = field.c_field_const_type
2297 c_pointer = field.c_pointer
2298 if c_pointer == ' ':
2300 if field.type.need_serialize and not aux:
2301 c_field_const_type = "const void"
2303 comma = ', ' if count else ');'
2304 prototype += '%s\\ %s\\fI%s\\fP%s' % (c_field_const_type, c_pointer, field.c_field_name, comma)
2306 f.write('.SS Request function\n')
2308 base_func_name = self.c_request_name if not aux else self.c_aux_name
2309 f.write('%s \\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\n' % (cookie_type, base_func_name, prototype))
2310 create_link('%s_%s' % (base_func_name, ('checked' if void else 'unchecked')))
2313 f.write('.SS Reply datastructure\n')
2316 f.write('typedef %s %s {\n' % (self.reply.c_container, self.reply.c_type))
2320 for field in self.reply.fields:
2321 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2324 struct_fields.append(field)
2326 for field in struct_fields:
2327 length = len(field.c_field_type)
2328 # account for '*' pointer_spec
2329 if not field.type.fixed_size():
2331 maxtypelen = max(maxtypelen, length)
2333 def _c_complex_field(self, field, space=''):
2334 if (field.type.fixed_size() or
2335 # in case of switch with switch children, don't make the field a pointer
2336 # necessary for unserialize to work
2337 (self.is_switch and field.type.is_switch)):
2338 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2339 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2341 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
2342 f.write('ELSE %s = %s\n' % (field.c_field_type, field.c_field_name))
2343 #_h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
2345 if not self.is_switch:
2346 for field in struct_fields:
2347 _c_complex_field(self, field)
2349 for b in self.bitcases:
2353 for field in b.type.fields:
2354 _c_complex_field(self, field, space)
2356 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2359 f.write('} \\fB%s\\fP;\n' % self.reply.c_type)
2362 f.write('.SS Reply function\n')
2364 f.write(('%s *\\fB%s\\fP(xcb_connection_t\\ *\\fIconn\\fP, %s\\ '
2365 '\\fIcookie\\fP, xcb_generic_error_t\\ **\\fIe\\fP);\n') %
2366 (self.c_reply_type, self.c_reply_name, self.c_cookie_type))
2367 create_link('%s' % self.c_reply_name)
2369 has_accessors = False
2370 for field in self.reply.fields:
2371 if field.type.is_list and not field.type.fixed_size():
2372 has_accessors = True
2373 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2374 has_accessors = True
2377 f.write('.SS Reply accessors\n')
2379 def _c_accessors_field(self, field):
2381 Declares the accessor functions for a non-list field that follows a variable-length field.
2383 c_type = self.c_type
2385 # special case: switch
2386 switch_obj = self if self.is_switch else None
2388 switch_obj = self.parents[-1]
2389 if switch_obj is not None:
2390 c_type = switch_obj.c_type
2392 if field.type.is_simple:
2393 f.write('%s %s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2394 create_link('%s' % field.c_accessor_name)
2396 f.write('%s *%s (const %s *reply)\n' % (field.c_field_type, field.c_accessor_name, c_type))
2397 create_link('%s' % field.c_accessor_name)
2399 def _c_accessors_list(self, field):
2401 Declares the accessor functions for a list field.
2402 Declares a direct-accessor function only if the list members are fixed size.
2403 Declares length and get-iterator functions always.
2406 c_type = self.reply.c_type
2408 # special case: switch
2409 # in case of switch, 2 params have to be supplied to certain accessor functions:
2410 # 1. the anchestor object (request or reply)
2411 # 2. the (anchestor) switch object
2412 # the reason is that switch is either a child of a request/reply or nested in another switch,
2413 # so whenever we need to access a length field, we might need to refer to some anchestor type
2414 switch_obj = self if self.is_switch else None
2416 switch_obj = self.parents[-1]
2417 if switch_obj is not None:
2418 c_type = switch_obj.c_type
2422 parents = self.parents if hasattr(self, 'parents') else [self]
2423 # 'R': parents[0] is always the 'toplevel' container type
2424 params.append(('const %s *\\fIreply\\fP' % parents[0].c_type, parents[0]))
2425 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
2426 # auxiliary object for 'R' parameters
2429 if switch_obj is not None:
2430 # now look where the fields are defined that are needed to evaluate
2431 # the switch expr, and store the parent objects in accessor_params and
2432 # the fields in switch_fields
2434 # 'S': name for the 'toplevel' switch
2435 toplevel_switch = parents[1]
2436 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
2437 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
2439 # initialize prefix for everything "below" S
2440 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
2441 prefix = [(prefix_str, '->', toplevel_switch)]
2443 # look for fields in the remaining containers
2444 for p in parents[2:] + [self]:
2445 # the separator between parent and child is always '.' here,
2446 # because of nested switch statements
2447 if not p.is_bitcase or (p.is_bitcase and p.has_name):
2448 prefix.append((p.name[-1], '.', p))
2449 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
2451 # auxiliary object for 'S' parameter
2454 if list.member.fixed_size():
2455 idx = 1 if switch_obj is not None else 0
2457 f.write('%s *\\fB%s\\fP(%s);\n' %
2458 (field.c_field_type, field.c_accessor_name, params[idx][0]))
2459 create_link('%s' % field.c_accessor_name)
2462 f.write('int \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2463 (field.c_length_name, c_type))
2464 create_link('%s' % field.c_length_name)
2466 if field.type.member.is_simple:
2468 f.write('xcb_generic_iterator_t \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2469 (field.c_end_name, c_type))
2470 create_link('%s' % field.c_end_name)
2473 f.write('%s \\fB%s\\fP(const %s *\\fIreply\\fP);\n' %
2474 (field.c_iterator_type, field.c_iterator_name,
2476 create_link('%s' % field.c_iterator_name)
2478 for field in self.reply.fields:
2479 if field.type.is_list and not field.type.fixed_size():
2480 _c_accessors_list(self, field)
2481 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2482 _c_accessors_field(self, field)
2486 # Re-enable hyphenation and adjusting to both sides
2489 # argument reference
2490 f.write('.SH REQUEST ARGUMENTS\n')
2491 f.write('.IP \\fI%s\\fP 1i\n' % 'conn')
2492 f.write('The XCB connection to X11.\n')
2493 for field in param_fields:
2494 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2495 printed_enum = False
2496 # XXX: hard-coded until we fix xproto.xml
2497 if base_func_name == 'xcb_change_gc' and field.c_field_name == 'value_mask':
2499 elif base_func_name == 'xcb_change_window_attributes' and field.c_field_name == 'value_mask':
2501 elif base_func_name == 'xcb_create_window' and field.c_field_name == 'value_mask':
2504 # XXX: why the 'xcb' prefix?
2505 key = ('xcb', field.enum)
2507 f.write('One of the following values:\n')
2510 count = len(enum.values)
2511 for (enam, eval) in enum.values:
2513 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2514 if enum.doc and enam in enum.doc.fields:
2515 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2516 f.write('%s\n' % desc)
2518 f.write('TODO: NOT YET DOCUMENTED.\n')
2523 if self.doc and field.field_name in self.doc.fields:
2524 desc = self.doc.fields[field.field_name]
2525 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2528 f.write('%s\n' % desc)
2530 f.write('TODO: NOT YET DOCUMENTED.\n')
2536 f.write('.SH REPLY FIELDS\n')
2537 # These fields are present in every reply:
2538 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2539 f.write(('The type of this reply, in this case \\fI%s\\fP. This field '
2540 'is also present in the \\fIxcb_generic_reply_t\\fP and can '
2541 'be used to tell replies apart from each other.\n') %
2542 _n(self.reply.name).upper())
2543 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2544 f.write('The sequence number of the last request processed by the X11 server.\n')
2545 f.write('.IP \\fI%s\\fP 1i\n' % 'length')
2546 f.write('The length of the reply, in words (a word is 4 bytes).\n')
2547 for field in self.reply.fields:
2548 if (field.c_field_name in frozenset(['response_type', 'sequence', 'length']) or
2549 field.c_field_name.startswith('pad')):
2552 if field.type.is_list and not field.type.fixed_size():
2554 elif field.prev_varsized_field is not None or not field.type.fixed_size():
2556 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2557 printed_enum = False
2559 # XXX: why the 'xcb' prefix?
2560 key = ('xcb', field.enum)
2562 f.write('One of the following values:\n')
2565 count = len(enum.values)
2566 for (enam, eval) in enum.values:
2568 f.write('.IP \\fI%s\\fP 1i\n' % (_n(key + (enam,)).upper()))
2569 if enum.doc and enam in enum.doc.fields:
2570 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', enum.doc.fields[enam])
2571 f.write('%s\n' % desc)
2573 f.write('TODO: NOT YET DOCUMENTED.\n')
2578 if self.reply.doc and field.field_name in self.reply.doc.fields:
2579 desc = self.reply.doc.fields[field.field_name]
2580 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2583 f.write('%s\n' % desc)
2585 f.write('TODO: NOT YET DOCUMENTED.\n')
2592 f.write('.SH DESCRIPTION\n')
2593 if self.doc and self.doc.description:
2594 desc = self.doc.description
2595 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2596 lines = desc.split('\n')
2597 f.write('\n'.join(lines) + '\n')
2599 f.write('.SH RETURN VALUE\n')
2601 f.write(('Returns an \\fIxcb_void_cookie_t\\fP. Errors (if any) '
2602 'have to be handled in the event loop.\n\nIf you want to '
2603 'handle errors directly with \\fIxcb_request_check\\fP '
2604 'instead, use \\fI%s_checked\\fP. See '
2605 '\\fBxcb-requests(3)\\fP for details.\n') % (base_func_name))
2607 f.write(('Returns an \\fI%s\\fP. Errors have to be handled when '
2608 'calling the reply function \\fI%s\\fP.\n\nIf you want to '
2609 'handle errors in the event loop instead, use '
2610 '\\fI%s_unchecked\\fP. See \\fBxcb-requests(3)\\fP for '
2612 (cookie_type, self.c_reply_name, base_func_name))
2613 f.write('.SH ERRORS\n')
2615 for errtype, errtext in self.doc.errors.iteritems():
2616 f.write('.IP \\fI%s\\fP 1i\n' % (_t(('xcb', errtype, 'error'))))
2617 errtext = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', errtext)
2618 f.write('%s\n' % (errtext))
2619 if not self.doc or len(self.doc.errors) == 0:
2620 f.write('This request does never generate any errors.\n')
2621 if self.doc and self.doc.example:
2622 f.write('.SH EXAMPLE\n')
2625 lines = self.doc.example.split('\n')
2626 f.write('\n'.join(lines) + '\n')
2628 f.write('.SH SEE ALSO\n')
2630 see = ['.BR %s (3)' % 'xcb-requests']
2631 if self.doc.example:
2632 see.append('.BR %s (3)' % 'xcb-examples')
2633 for seename, seetype in self.doc.see.iteritems():
2634 if seetype == 'program':
2635 see.append('.BR %s (1)' % seename)
2636 elif seetype == 'event':
2637 see.append('.BR %s (3)' % _t(('xcb', seename, 'event')))
2638 elif seetype == 'request':
2639 see.append('.BR %s (3)' % _n(('xcb', seename)))
2640 elif seetype == 'function':
2641 see.append('.BR %s (3)' % seename)
2643 see.append('TODO: %s (type %s)' % (seename, seetype))
2644 f.write(',\n'.join(see) + '\n')
2645 f.write('.SH AUTHOR\n')
2646 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2649 def _man_event(self, name):
2651 sys.stdout.write('man/%s.3 ' % self.c_type)
2652 # Our CWD is src/, so this will end up in src/man/
2653 f = open('man/%s.3' % self.c_type, 'w')
2654 f.write('.TH %s 3 %s "XCB" "XCB Events"\n' % (self.c_type, today))
2655 # Left-adjust instead of adjusting to both sides
2657 f.write('.SH NAME\n')
2658 brief = self.doc.brief if self.doc else ''
2659 f.write('%s \\- %s\n' % (self.c_type, brief))
2660 f.write('.SH SYNOPSIS\n')
2661 # Don't split words (hyphenate)
2663 f.write('.B #include <xcb/%s.h>\n' % _ns.header)
2666 f.write('.SS Event datastructure\n')
2669 f.write('typedef %s %s {\n' % (self.c_container, self.c_type))
2673 for field in self.fields:
2674 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
2677 struct_fields.append(field)
2679 for field in struct_fields:
2680 length = len(field.c_field_type)
2681 # account for '*' pointer_spec
2682 if not field.type.fixed_size():
2684 maxtypelen = max(maxtypelen, length)
2686 def _c_complex_field(self, field, space=''):
2687 if (field.type.fixed_size() or
2688 # in case of switch with switch children, don't make the field a pointer
2689 # necessary for unserialize to work
2690 (self.is_switch and field.type.is_switch)):
2691 spacing = ' ' * (maxtypelen - len(field.c_field_type))
2692 f.write('%s %s%s \\fI%s\\fP%s;\n' % (space, field.c_field_type, spacing, field.c_field_name, field.c_subscript))
2694 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2696 if not self.is_switch:
2697 for field in struct_fields:
2698 _c_complex_field(self, field)
2700 for b in self.bitcases:
2704 for field in b.type.fields:
2705 _c_complex_field(self, field, space)
2707 print >> sys.stderr, 'ERROR: New unhandled documentation case'
2710 f.write('} \\fB%s\\fP;\n' % self.c_type)
2715 # Re-enable hyphenation and adjusting to both sides
2718 # argument reference
2719 f.write('.SH EVENT FIELDS\n')
2720 f.write('.IP \\fI%s\\fP 1i\n' % 'response_type')
2721 f.write(('The type of this event, in this case \\fI%s\\fP. This field is '
2722 'also present in the \\fIxcb_generic_event_t\\fP and can be used '
2723 'to tell events apart from each other.\n') % _n(name).upper())
2724 f.write('.IP \\fI%s\\fP 1i\n' % 'sequence')
2725 f.write('The sequence number of the last request processed by the X11 server.\n')
2727 if not self.is_switch:
2728 for field in struct_fields:
2729 # Skip the fields which every event has, we already documented
2731 if field.c_field_name in ('response_type', 'sequence'):
2733 if isinstance(field.type, PadType):
2735 f.write('.IP \\fI%s\\fP 1i\n' % (field.c_field_name))
2736 if self.doc and field.field_name in self.doc.fields:
2737 desc = self.doc.fields[field.field_name]
2738 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2739 f.write('%s\n' % desc)
2741 f.write('NOT YET DOCUMENTED.\n')
2744 f.write('.SH DESCRIPTION\n')
2745 if self.doc and self.doc.description:
2746 desc = self.doc.description
2747 desc = re.sub(r'`([^`]+)`', r'\\fI\1\\fP', desc)
2748 lines = desc.split('\n')
2749 f.write('\n'.join(lines) + '\n')
2751 if self.doc and self.doc.example:
2752 f.write('.SH EXAMPLE\n')
2755 lines = self.doc.example.split('\n')
2756 f.write('\n'.join(lines) + '\n')
2758 f.write('.SH SEE ALSO\n')
2760 see = ['.BR %s (3)' % 'xcb_generic_event_t']
2761 if self.doc.example:
2762 see.append('.BR %s (3)' % 'xcb-examples')
2763 for seename, seetype in self.doc.see.iteritems():
2764 if seetype == 'program':
2765 see.append('.BR %s (1)' % seename)
2766 elif seetype == 'event':
2767 see.append('.BR %s (3)' % _t(('xcb', seename, 'event')))
2768 elif seetype == 'request':
2769 see.append('.BR %s (3)' % _n(('xcb', seename)))
2770 elif seetype == 'function':
2771 see.append('.BR %s (3)' % seename)
2773 see.append('TODO: %s (type %s)' % (seename, seetype))
2774 f.write(',\n'.join(see) + '\n')
2775 f.write('.SH AUTHOR\n')
2776 f.write('Generated from %s.xml. Contact xcb@lists.freedesktop.org for corrections and improvements.\n' % _ns.header)
2780 def c_request(self, name):
2782 Exported function that handles request declarations.
2784 _c_type_setup(self, name, ('request',))
2787 # Cookie type declaration
2788 _c_cookie(self, name)
2791 _c_opcode(name, self.opcode)
2793 # Request structure declaration
2797 _c_type_setup(self.reply, name, ('reply',))
2798 # Reply structure definition
2799 _c_complex(self.reply)
2800 # Request prototypes
2801 _c_request_helper(self, name, self.c_cookie_type, False, True)
2802 _c_request_helper(self, name, self.c_cookie_type, False, False)
2804 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
2805 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
2807 _c_accessors(self.reply, name + ('reply',), name)
2808 _c_reply(self, name)
2810 # Request prototypes
2811 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2812 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2814 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2815 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2817 # We generate the manpage afterwards because _c_type_setup has been called.
2818 # TODO: what about aux helpers?
2819 cookie_type = self.c_cookie_type if self.reply else 'xcb_void_cookie_t'
2820 _man_request(self, name, cookie_type, not self.reply, False)
2822 def c_event(self, name):
2824 Exported function that handles event declarations.
2826 _c_type_setup(self, name, ('event',))
2829 _c_opcode(name, self.opcodes[name])
2831 if self.name == name:
2832 # Structure definition
2837 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2839 _man_event(self, name)
2841 def c_error(self, name):
2843 Exported function that handles error declarations.
2845 _c_type_setup(self, name, ('error',))
2848 _c_opcode(name, self.opcodes[name])
2850 if self.name == name:
2851 # Structure definition
2856 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2859 # Main routine starts here
2861 # Must create an "output" dictionary before any xcbgen imports.
2862 output = {'open' : c_open,
2864 'simple' : c_simple,
2866 'struct' : c_struct,
2868 'request' : c_request,
2873 # Boilerplate below this point
2875 # Check for the argument that specifies path to the xcbgen python package.
2877 opts, args = getopt.getopt(sys.argv[1:], 'p:m')
2878 except getopt.GetoptError as err:
2880 print('Usage: c_client.py [-p path] file.xml')
2883 for (opt, arg) in opts:
2885 sys.path.insert(1, arg)
2888 sys.stdout.write('man_MANS = ')
2890 # Import the module class
2892 from xcbgen.state import Module
2893 from xcbgen.xtypes import *
2896 Failed to load the xcbgen Python package!
2897 Make sure that xcb/proto installed it on your Python path.
2898 If not, you will need to create a .pth file or define $PYTHONPATH
2900 Refer to the README file in xcb/proto for more info.
2904 # Ensure the man subdirectory exists
2905 if not os.path.exists('man'):
2908 today = time.strftime('%Y-%m-%d', time.gmtime(os.path.getmtime(args[0])))
2910 # Parse the xml header
2911 module = Module(args[0], output)
2913 # Build type-registry and resolve type dependencies