2 from xml.etree.cElementTree import *
3 from os.path import basename
8 # Jump to the bottom of this file for the main routine
10 # Some hacks to make the API more readable, and to keep backwards compability
11 _cname_re = re.compile('([A-Z0-9][a-z]+|[A-Z0-9]+(?![a-z])|[a-z]+)')
12 _cname_special_cases = {'DECnet':'decnet'}
14 _extension_special_cases = ['XPrint', 'XCMisc', 'BigRequests']
16 _cplusplus_annoyances = {'class' : '_class',
19 _c_keywords = {'default' : '_default'}
27 # global variable to keep track of serializers and
28 # switch data types due to weird dependencies
29 finished_serializers = []
35 Writes the given line to the header file.
37 _hlines[_hlevel].append(fmt % args)
41 Writes the given line to the source file.
43 _clines[_clevel].append(fmt % args)
47 Writes the given line to both the header and source files.
52 # XXX See if this level thing is really necessary.
55 Changes the array that header lines are written to.
56 Supports writing different sections of the header file.
59 while len(_hlines) <= idx:
65 Changes the array that source lines are written to.
66 Supports writing to different sections of the source file.
69 while len(_clines) <= idx:
75 Does C-name conversion on a single string fragment.
76 Uses a regexp with some hard-coded special cases.
78 if str in _cname_special_cases:
79 return _cname_special_cases[str]
81 split = _cname_re.finditer(str)
82 name_parts = [match.group(0) for match in split]
83 return '_'.join(name_parts)
87 Checks for certain C++ reserved words and fixes them.
89 if str in _cplusplus_annoyances:
90 return _cplusplus_annoyances[str]
91 elif str in _c_keywords:
92 return _c_keywords[str]
98 Does C-name conversion on an extension name.
99 Has some additional special cases on top of _n_item.
101 if str in _extension_special_cases:
102 return _n_item(str).lower()
108 Does C-name conversion on a tuple of strings.
109 Different behavior depending on length of tuple, extension/not extension, etc.
110 Basically C-name converts the individual pieces, then joins with underscores.
115 parts = [list[0], _n_item(list[1])]
117 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
119 parts = [list[0]] + [_n_item(i) for i in list[1:]]
120 return '_'.join(parts).lower()
124 Does C-name conversion on a tuple of strings representing a type.
125 Same as _n but adds a "_t" on the end.
130 parts = [list[0], _n_item(list[1]), 't']
132 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
134 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
135 return '_'.join(parts).lower()
140 Exported function that handles module open.
141 Opens the files and writes out the auto-generated comment, header file includes, etc.
145 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
147 # Build the type-name collision avoidance table used by c_enum
148 build_collision_table()
154 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
155 _hc(' * Edit at your peril.')
160 _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
161 _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
165 _h('#ifndef __%s_H', _ns.header.upper())
166 _h('#define __%s_H', _ns.header.upper())
168 _h('#include "xcb.h"')
170 _c('#include <stdlib.h>')
171 _c('#include <string.h>')
172 _c('#include <assert.h>')
173 _c('#include "xcbext.h"')
174 _c('#include "%s.h"', _ns.header)
177 for (n, h) in self.imports:
178 _hc('#include "%s.h"', h)
181 _h('#ifdef __cplusplus')
187 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
188 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
190 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
193 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
197 Exported function that handles module close.
198 Writes out all the stored content lines, then closes the files.
205 _h('#ifdef __cplusplus')
217 hfile = open('%s.h' % _ns.header, 'w')
225 cfile = open('%s.c' % _ns.header, 'w')
232 def build_collision_table():
236 for v in module.types.values():
238 namecount[name] = (namecount.get(name) or 0) + 1
240 def c_enum(self, name):
242 Exported function that handles enum declarations.
246 if namecount[tname] > 1:
247 tname = _t(name + ('enum',))
251 _h('typedef enum %s {', tname)
253 count = len(self.values)
255 for (enam, eval) in self.values:
257 equals = ' = ' if eval != '' else ''
258 comma = ',' if count > 0 else ''
259 _h(' %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
263 def _c_type_setup(self, name, postfix):
265 Sets up all the C-related state by adding additional data fields to
266 all Field and Type objects. Here is where we figure out most of our
267 variable and function names.
269 Recurses into child fields and list member types.
271 # Do all the various names in advance
272 self.c_type = _t(name + postfix)
273 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
275 self.c_iterator_type = _t(name + ('iterator',))
276 self.c_next_name = _n(name + ('next',))
277 self.c_end_name = _n(name + ('end',))
279 self.c_request_name = _n(name)
280 self.c_checked_name = _n(name + ('checked',))
281 self.c_unchecked_name = _n(name + ('unchecked',))
282 self.c_reply_name = _n(name + ('reply',))
283 self.c_reply_type = _t(name + ('reply',))
284 self.c_cookie_type = _t(name + ('cookie',))
286 self.need_aux = False
287 self.need_serialize = False
288 self.need_sizeof = False
290 self.c_aux_name = _n(name + ('aux',))
291 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
292 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
293 self.c_serialize_name = _n(name + ('serialize',))
294 self.c_unserialize_name = _n(name + ('unserialize',))
295 self.c_unpack_name = _n(name + ('unpack',))
296 self.c_sizeof_name = _n(name + ('sizeof',))
298 # special case: structs where variable size fields are followed by fixed size fields
299 self.var_followed_by_fixed_fields = False
302 self.need_serialize = True
303 self.c_container = 'struct'
304 for bitcase in self.bitcases:
305 bitcase.c_field_name = _cpp(bitcase.field_name)
306 bitcase_name = bitcase.field_type if bitcase.type.has_name else name
307 _c_type_setup(bitcase.type, bitcase_name, ())
309 elif self.is_container:
311 self.c_container = 'union' if self.is_union else 'struct'
312 prev_varsized_field = None
313 prev_varsized_offset = 0
314 first_field_after_varsized = None
316 for field in self.fields:
317 _c_type_setup(field.type, field.field_type, ())
318 if field.type.is_list:
319 _c_type_setup(field.type.member, field.field_type, ())
320 if (field.type.nmemb is None):
321 self.need_sizeof = True
323 field.c_field_type = _t(field.field_type)
324 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
325 field.c_field_name = _cpp(field.field_name)
326 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
327 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
329 # correct the c_pointer field for variable size non-list types
330 if not field.type.fixed_size() and field.c_pointer == ' ':
331 field.c_pointer = '*'
332 if field.type.is_list and not field.type.member.fixed_size():
333 field.c_pointer = '*'
335 if field.type.is_switch:
336 field.c_pointer = '*'
337 field.c_field_const_type = 'const ' + field.c_field_type
339 elif not field.type.fixed_size() and not field.type.is_bitcase:
340 self.need_sizeof = True
342 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
343 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
344 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
345 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
346 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
348 field.prev_varsized_field = prev_varsized_field
349 field.prev_varsized_offset = prev_varsized_offset
351 if prev_varsized_offset == 0:
352 first_field_after_varsized = field
353 field.first_field_after_varsized = first_field_after_varsized
355 if field.type.fixed_size():
356 prev_varsized_offset += field.type.size
357 # special case: intermixed fixed and variable size fields
358 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
359 if not self.is_union:
360 self.need_serialize = True
361 self.var_followed_by_fixed_fields = True
363 self.last_varsized_field = field
364 prev_varsized_field = field
365 prev_varsized_offset = 0
367 if self.var_followed_by_fixed_fields:
368 if field.type.fixed_size():
369 field.prev_varsized_field = None
371 if self.need_serialize:
372 # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
373 self.need_sizeof = True
375 # as switch does never appear at toplevel,
376 # continue here with type construction
378 if self.c_type not in finished_switch:
379 finished_switch.append(self.c_type)
380 # special: switch C structs get pointer fields for variable-sized members
382 for bitcase in self.bitcases:
383 bitcase_name = bitcase.type.name if bitcase.type.has_name else name
384 _c_accessors(bitcase.type, bitcase_name, bitcase_name)
385 # no list with switch as element, so no call to
386 # _c_iterator(field.type, field_name) necessary
388 if not self.is_bitcase:
389 if self.need_serialize:
390 if self.c_serialize_name not in finished_serializers:
391 finished_serializers.append(self.c_serialize_name)
392 _c_serialize('serialize', self)
394 # _unpack() and _unserialize() are only needed for special cases:
396 # special cases -> unserialize
397 if self.is_switch or self.var_followed_by_fixed_fields:
398 _c_serialize('unserialize', self)
401 if self.c_sizeof_name not in finished_sizeof:
402 finished_sizeof.append(self.c_sizeof_name)
403 _c_serialize('sizeof', self)
406 def _c_helper_absolute_name(prefix, field=None):
408 turn prefix, which is a list of tuples (name, separator, Type obj) into a string
409 representing a valid name in C (based on the context)
410 if field is not None, append the field name as well
413 for name, sep, obj in prefix:
417 if ((obj.is_bitcase and obj.has_name) or # named bitcase
418 (obj.is_switch and len(obj.parents)>1)):
421 if field is not None:
422 prefix_str += _cpp(field.field_name)
426 def _c_helper_field_mapping(complex_type, prefix, flat=False):
428 generate absolute names, based on prefix, for all fields starting from complex_type
429 if flat == True, nested complex types are not taken into account
432 if complex_type.is_switch:
433 for b in complex_type.bitcases:
435 switch_name, switch_sep, switch_type = prefix[-1]
436 bitcase_prefix = prefix + [(b.type.name[-1], '.', b.type)]
438 bitcase_prefix = prefix
440 if (True==flat and not b.type.has_name) or False==flat:
441 all_fields.update(_c_helper_field_mapping(b.type, bitcase_prefix, flat))
443 for f in complex_type.fields:
444 fname = _c_helper_absolute_name(prefix, f)
445 if all_fields.has_key(f.field_name):
446 raise Exception("field name %s has been registered before" % f.field_name)
448 all_fields[f.field_name] = (fname, f)
449 if f.type.is_container and flat==False:
450 if f.type.is_bitcase and not f.type.has_name:
452 elif f.type.is_switch and len(f.type.parents)>1:
453 # nested switch gets another separator
454 new_prefix = prefix+[(f.c_field_name, '.', f.type)]
456 new_prefix = prefix+[(f.c_field_name, '->', f.type)]
457 all_fields.update(_c_helper_field_mapping(f.type, new_prefix, flat))
462 def _c_helper_resolve_field_names (prefix):
464 get field names for all objects in the prefix array
468 # look for fields in the remaining containers
469 for idx, p in enumerate(prefix):
472 # sep can be preset in prefix, if not, make a sensible guess
473 sep = '.' if (obj.is_switch or obj.is_bitcase) else '->'
474 # exception: 'toplevel' object (switch as well!) always have sep '->'
475 sep = '->' if idx<1 else sep
476 if not obj.is_bitcase or (obj.is_bitcase and obj.has_name):
477 tmp_prefix.append((name, sep, obj))
478 all_fields.update(_c_helper_field_mapping(obj, tmp_prefix, flat=True))
481 # _c_helper_resolve_field_names
483 def get_expr_fields(self):
485 get the Fields referenced by switch or list expression
487 def get_expr_field_names(expr):
489 if expr.lenfield_name is not None:
490 return [expr.lenfield_name]
492 # constant value expr
496 return get_expr_field_names(expr.rhs)
497 elif expr.op == 'popcount':
498 return get_expr_field_names(expr.rhs)
499 elif expr.op == 'sumof':
500 # sumof expr references another list,
501 # we need that list's length field here
503 for f in expr.lenfield_parent.fields:
504 if f.field_name == expr.lenfield_name:
508 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
509 # referenced list + its length field
510 return [expr.lenfield_name] + get_expr_field_names(field.type.expr)
511 elif expr.op == 'enumref':
514 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
515 # get_expr_field_names()
517 # resolve the field names with the parent structure(s)
518 unresolved_fields_names = get_expr_field_names(self.expr)
520 # construct prefix from self
521 prefix = [('', '', p) for p in self.parents]
522 if self.is_container:
523 prefix.append(('', '', self))
525 all_fields = _c_helper_resolve_field_names (prefix)
526 resolved_fields_names = filter(lambda x: x in all_fields.keys(), unresolved_fields_names)
527 if len(unresolved_fields_names) != len(resolved_fields_names):
528 raise Exception("could not resolve all fields for %s" % self.name)
530 resolved_fields = [all_fields[n][1] for n in resolved_fields_names]
531 return resolved_fields
534 def resolve_expr_fields(complex_obj):
536 find expr fields appearing in complex_obj and descendents that cannot be resolved within complex_obj
537 these are normally fields that need to be given as function parameters
543 for field in complex_obj.fields:
544 all_fields.append(field)
545 if field.type.is_switch or field.type.is_list:
546 expr_fields += get_expr_fields(field.type)
547 if field.type.is_container:
548 expr_fields += resolve_expr_fields(field.type)
550 # try to resolve expr fields
551 for e in expr_fields:
552 if e not in all_fields and e not in unresolved:
555 # resolve_expr_fields()
557 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
559 functions like _serialize(), _unserialize(), and _unpack() sometimes need additional parameters:
560 E.g. in order to unpack switch, extra parameters might be needed to evaluate the switch
561 expression. This function tries to resolve all fields within a structure, and returns the
562 unresolved fields as the list of external parameters.
564 def add_param(params, param):
565 if param not in params:
568 # collect all fields into param_fields
572 for field in self.fields:
574 # the field should appear as a parameter in the function call
575 param_fields.append(field)
576 if field.wire and not field.auto:
577 if field.type.fixed_size() and not self.is_switch:
578 # field in the xcb_out structure
579 wire_fields.append(field)
580 # fields like 'pad0' are skipped!
582 # in case of switch, parameters always contain any fields referenced in the switch expr
583 # we do not need any variable size fields here, as the switch data type contains both
584 # fixed and variable size fields
586 param_fields = get_expr_fields(self)
588 # _serialize()/_unserialize()/_unpack() function parameters
589 # note: don't use set() for params, it is unsorted
592 # 1. the parameter for the void * buffer
593 if 'serialize' == context:
594 params.append(('void', '**', buffer_var))
595 elif context in ('unserialize', 'unpack', 'sizeof'):
596 params.append(('const void', '*', buffer_var))
598 # 2. any expr fields that cannot be resolved within self and descendants
599 unresolved_fields = resolve_expr_fields(self)
600 for f in unresolved_fields:
601 add_param(params, (f.c_field_type, '', f.c_field_name))
603 # 3. param_fields contain the fields necessary to evaluate the switch expr or any other fields
604 # that do not appear in the data type struct
605 for p in param_fields:
607 typespec = p.c_field_const_type
608 pointerspec = p.c_pointer
609 add_param(params, (typespec, pointerspec, p.c_field_name))
611 if p.visible and not p.wire and not p.auto:
612 typespec = p.c_field_type
614 add_param(params, (typespec, pointerspec, p.c_field_name))
617 if 'serialize' == context:
618 add_param(params, ('const %s' % self.c_type, '*', aux_var))
619 elif 'unserialize' == context:
620 add_param(params, ('%s' % self.c_type, '**', aux_var))
621 elif 'unpack' == context:
622 add_param(params, ('%s' % self.c_type, '*', aux_var))
624 # 5. switch contains all variable size fields as struct members
625 # for other data types though, these have to be supplied separately
626 # this is important for the special case of intermixed fixed and
627 # variable size fields
628 if not self.is_switch and 'serialize' == context:
629 for p in param_fields:
630 if not p.type.fixed_size():
631 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
633 return (param_fields, wire_fields, params)
634 # get_serialize_params()
636 def _c_serialize_helper_insert_padding(context, code_lines, space, postpone):
637 code_lines.append('%s /* insert padding */' % space)
638 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
639 # code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space)
640 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
643 code_lines.append('%s if (0 != xcb_pad) {' % space)
645 if 'serialize' == context:
646 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
647 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
648 code_lines.append('%s xcb_parts_idx++;' % space)
649 elif context in ('unserialize', 'unpack', 'sizeof'):
650 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
652 code_lines.append('%s xcb_pad = 0;' % space)
653 code_lines.append('%s }' % space)
655 code_lines.append('%s xcb_block_len = 0;' % space)
657 # keep tracking of xcb_parts entries for serialize
659 # _c_serialize_helper_insert_padding()
661 def _c_serialize_helper_switch(context, self, complex_name,
662 code_lines, temp_vars,
665 switch_expr = _c_accessor_get_expr(self.expr, None)
667 for b in self.bitcases:
668 bitcase_expr = _c_accessor_get_expr(b.type.expr, None)
669 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
670 # code_lines.append(' printf("switch %s: entering bitcase section %s (mask=%%%%d)...\\n", %s);' %
671 # (self.name[-1], b.type.name[-1], bitcase_expr))
674 b_prefix = prefix + [(b.c_field_name, '.', b.type)]
676 count += _c_serialize_helper_fields(context, b.type,
677 code_lines, temp_vars,
681 code_lines.append(' }')
683 # if 'serialize' == context:
684 # count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
685 # elif context in ('unserialize', 'unpack', 'sizeof'):
687 # code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
688 # code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
691 # _c_serialize_helper_switch
693 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
695 handle switch by calling _serialize() or _unpack(), depending on context
697 # switch is handled by this function as a special case
698 param_fields, wire_fields, params = get_serialize_params(context, self)
699 field_mapping = _c_helper_field_mapping(self, prefix)
700 prefix_str = _c_helper_absolute_name(prefix)
702 # find the parameters that need to be passed to _serialize()/_unpack():
703 # all switch expr fields must be given as parameters
704 args = get_expr_fields(field.type)
705 # length fields for variable size types in switch, normally only some of need
706 # need to be passed as parameters
707 switch_len_fields = resolve_expr_fields(field.type)
709 # a switch field at this point _must_ be a bitcase field
710 # we require that bitcases are "self-contiguous"
711 bitcase_unresolved = resolve_expr_fields(self)
712 if len(bitcase_unresolved) != 0:
713 raise Exception('unresolved fields within bitcase is not supported at this point')
715 # get the C names for the parameters
717 for a in switch_len_fields:
718 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
720 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
722 # call _serialize()/_unpack() to determine the actual size
723 if 'serialize' == context:
724 length = "%s(&%s, %s&%s%s)" % (field.type.c_serialize_name, c_switch_variable,
725 c_field_names, prefix_str, field.c_field_name)
726 elif context in ('unserialize', 'unpack'):
727 length = "%s(xcb_tmp, %s&%s%s)" % (field.type.c_unpack_name,
728 c_field_names, prefix_str, field.c_field_name)
731 # _c_serialize_helper_switch_field()
733 def _c_serialize_helper_list_field(context, self, field,
734 code_lines, temp_vars,
737 helper function to cope with lists of variable length
739 expr = field.type.expr
740 prefix_str = _c_helper_absolute_name(prefix)
741 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
742 param_names = [p[2] for p in params]
744 expr_fields_names = [f.field_name for f in get_expr_fields(field.type)]
745 resolved = filter(lambda x: x in param_names, expr_fields_names)
746 unresolved = filter(lambda x: x not in param_names, expr_fields_names)
750 field_mapping[r] = (r, None)
752 if len(unresolved)>0:
754 if len(tmp_prefix)==0:
755 raise Exception("found an empty prefix while resolving expr field names for list %s",
758 field_mapping.update(_c_helper_resolve_field_names(prefix))
759 resolved += filter(lambda x: x in field_mapping, unresolved)
760 unresolved = filter(lambda x: x not in field_mapping, unresolved)
761 if len(unresolved)>0:
762 raise Exception('could not resolve the length fields required for list %s' % field.c_field_name)
764 list_length = _c_accessor_get_expr(expr, field_mapping)
766 # default: list with fixed size elements
767 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
769 # list with variable-sized elements
770 if not field.type.member.fixed_size():
772 if context in ('unserialize', 'sizeof', 'unpack'):
773 int_i = ' unsigned int i;'
774 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
775 if int_i not in temp_vars:
776 temp_vars.append(int_i)
777 if xcb_tmp_len not in temp_vars:
778 temp_vars.append(xcb_tmp_len)
779 # loop over all list elements and call sizeof repeatedly
780 # this should be a bit faster than using the iterators
781 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
782 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
783 (space, field.type.c_sizeof_name))
784 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
785 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
786 code_lines.append("%s }" % space)
788 elif 'serialize' == context:
789 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
790 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
791 code_lines.append('%s for(i=0; i<%s; i++) { ' % (space, list_length))
792 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
793 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
794 code_lines.append('%s }' % space)
795 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
798 # _c_serialize_helper_list_field()
800 def _c_serialize_helper_fields_fixed_size(context, self, field,
801 code_lines, temp_vars,
803 # keep the C code a bit more readable by giving the field name
804 if not self.is_bitcase:
805 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
807 scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
808 typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
809 code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
811 abs_field_name = _c_helper_absolute_name(prefix, field)
812 # default for simple cases: call sizeof()
813 length = "sizeof(%s)" % field.c_field_type
815 if context in ('unserialize', 'unpack', 'sizeof'):
816 # default: simple cast
817 value = ' %s = *(%s *)xcb_tmp;' % (abs_field_name, field.c_field_type)
819 # padding - we could probably just ignore it
820 if field.type.is_pad and field.type.nmemb > 1:
822 for i in range(field.type.nmemb):
823 code_lines.append('%s %s[%d] = *(%s *)xcb_tmp;' %
824 (space, abs_field_name, i, field.c_field_type))
825 # total padding = sizeof(pad0) * nmemb
826 length += " * %d" % field.type.nmemb
828 if field.type.is_list:
829 # no such case in the protocol, cannot be tested and therefore ignored for now
830 raise Exception('list with fixed number of elemens unhandled in _unserialize()')
832 elif 'serialize' == context:
833 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
835 if field.type.is_expr:
836 # need to register a temporary variable for the expression in case we know its type
837 if field.type.c_type is None:
838 raise Exception("type for field '%s' (expression '%s') unkown" %
839 (field.field_name, _c_accessor_get_expr(field.type.expr)))
841 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, _cpp(field.field_name),
842 _c_accessor_get_expr(field.type.expr, prefix)))
843 value += "&xcb_expr_%s;" % _cpp(field.field_name)
845 elif field.type.is_pad:
846 if field.type.nmemb == 1:
849 # we could also set it to 0, see definition of xcb_send_request()
850 value = ' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;'
851 length += "*%d" % field.type.nmemb
854 # non-list type with fixed size
855 if field.type.nmemb == 1:
856 value += "&%s;" % (abs_field_name)
858 # list with nmemb (fixed size) elements
860 value += '%s;' % (abs_field_name)
861 length = '%d' % field.type.nmemb
863 return (value, length)
864 # _c_serialize_helper_fields_fixed_size()
866 def _c_serialize_helper_fields_variable_size(context, self, field,
867 code_lines, temp_vars,
869 prefix_str = _c_helper_absolute_name(prefix)
871 if context in ('unserialize', 'unpack', 'sizeof'):
873 var_field_name = 'xcb_tmp'
875 # special case: intermixed fixed and variable size fields
876 if self.var_followed_by_fixed_fields and 'unserialize' == context:
877 value = ' %s = xcb_tmp;' % field.c_field_name
878 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
879 # special case: switch
880 if 'unpack' == context:
881 value = ' %s%s = (%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
883 elif 'serialize' == context:
884 # variable size fields appear as parameters to _serialize() if the
885 # 'toplevel' container is not a switch
886 prefix_string = prefix_str if prefix[0][2].is_switch else ''
887 var_field_name = "%s%s" % (prefix_string, field.c_field_name)
888 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s;' % var_field_name
892 code_lines.append('%s /* %s */' % (space, field.c_field_name))
894 if field.type.is_list:
896 # in any context, list is already a pointer, so the default assignment is ok
897 code_lines.append("%s%s" % (space, value))
899 length = _c_serialize_helper_list_field(context, self, field,
900 code_lines, temp_vars,
903 elif field.type.is_switch:
905 if context == 'serialize':
906 # the _serialize() function allocates the correct amount memory if given a NULL pointer
907 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *)0;'
908 length = _c_serialize_helper_switch_field(context, self, field,
909 'xcb_parts[xcb_parts_idx].iov_base',
913 # in all remaining special cases - call _sizeof()
914 length = "%s(%s)" % (field.type.c_sizeof_name, var_field_name)
916 return (value, length)
917 # _c_serialize_helper_fields_variable_size
919 def _c_serialize_helper_fields(context, self,
920 code_lines, temp_vars,
921 space, prefix, is_bitcase):
924 prev_field_was_variable = False
926 for field in self.fields:
927 if not ((field.wire and not field.auto) or field.visible):
930 # switch/bitcase: fixed size fields must be considered explicitly
931 if field.type.fixed_size():
932 if self.is_bitcase or self.var_followed_by_fixed_fields:
933 if prev_field_was_variable and need_padding:
935 # count += _c_serialize_helper_insert_padding(context, code_lines, space,
936 # self.var_followed_by_fixed_fields)
937 prev_field_was_variable = False
939 # prefix for fixed size fields
940 fixed_prefix = prefix
942 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
943 code_lines, temp_vars,
948 # fields with variable size
950 # switch/bitcase: always calculate padding before and after variable sized fields
951 if need_padding or is_bitcase:
952 count += _c_serialize_helper_insert_padding(context, code_lines, space,
953 self.var_followed_by_fixed_fields)
955 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
956 code_lines, temp_vars,
958 prev_field_was_variable = True
960 # save (un)serialization C code
962 code_lines.append('%s%s' % (space, value))
964 if field.type.fixed_size():
965 if is_bitcase or self.var_followed_by_fixed_fields:
966 # keep track of (un)serialized object's size
967 code_lines.append('%s xcb_block_len += %s;' % (space, length))
968 if context in ('unserialize', 'unpack', 'sizeof'):
969 code_lines.append('%s xcb_tmp += %s;' % (space, length))
971 # variable size objects or bitcase:
972 # value & length might have been inserted earlier for special cases
974 # special case: intermixed fixed and variable size fields
975 if (not field.type.fixed_size() and
976 self.var_followed_by_fixed_fields and 'unserialize' == context):
977 temp_vars.append(' int %s_len;' % field.c_field_name)
978 code_lines.append('%s %s_len = %s;' % (space, field.c_field_name, length))
979 code_lines.append('%s xcb_block_len += %s_len;' % (space, field.c_field_name))
980 code_lines.append('%s xcb_tmp += %s_len;' % (space, field.c_field_name))
982 code_lines.append('%s xcb_block_len += %s;' % (space, length))
983 # increase pointer into the byte stream accordingly
984 if context in ('unserialize', 'sizeof', 'unpack'):
985 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
987 if 'serialize' == context:
989 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
990 code_lines.append('%s xcb_parts_idx++;' % space)
994 if self.var_followed_by_fixed_fields:
998 # _c_serialize_helper_fields()
1000 def _c_serialize_helper(context, complex_type,
1001 code_lines, temp_vars,
1002 space='', prefix=[]):
1003 # count tracks the number of fields to serialize
1006 if hasattr(complex_type, 'type'):
1007 self = complex_type.type
1008 complex_name = complex_type.name
1011 if self.var_followed_by_fixed_fields and 'unserialize' == context:
1012 complex_name = 'xcb_out'
1014 complex_name = '_aux'
1016 # special case: switch is serialized by evaluating each bitcase separately
1018 count += _c_serialize_helper_switch(context, self, complex_name,
1019 code_lines, temp_vars,
1022 # all other data types can be evaluated one field a time
1024 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
1025 if context in ('unserialize', 'unpack', 'sizeof') and not self.var_followed_by_fixed_fields:
1026 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
1027 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
1028 # probably not needed
1029 #_c_serialize_helper_insert_padding(context, code_lines, space, False)
1031 count += _c_serialize_helper_fields(context, self,
1032 code_lines, temp_vars,
1033 space, prefix, False)
1035 count += _c_serialize_helper_insert_padding(context, code_lines, space, False)
1038 # _c_serialize_helper()
1040 def _c_serialize(context, self):
1042 depending on the context variable, generate _serialize(), _unserialize(), _unpack(), or _sizeof()
1043 for the ComplexType variable self
1049 # _serialize() returns the buffer size
1052 if self.is_switch and 'unserialize' == context:
1055 cases = { 'serialize' : self.c_serialize_name,
1056 'unserialize' : self.c_unserialize_name,
1057 'unpack' : self.c_unpack_name,
1058 'sizeof' : self.c_sizeof_name }
1059 func_name = cases[context]
1061 param_fields, wire_fields, params = get_serialize_params(context, self)
1062 variable_size_fields = 0
1063 # maximum space required for type definition of function arguments
1066 # determine N(variable_fields)
1067 for field in param_fields:
1068 # if self.is_switch, treat all fields as if they are variable sized
1069 if not field.type.fixed_size() or self.is_switch:
1070 variable_size_fields += 1
1071 # determine maxtypelen
1073 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1076 indent = ' '*(len(func_name)+2)
1079 typespec, pointerspec, field_name = p
1080 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1081 param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
1082 # insert function name
1083 param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
1084 param_str = map(lambda x: "%s," % x, param_str)
1085 for s in param_str[:-1]:
1087 _h("%s);" % param_str[-1].rstrip(','))
1088 _c("%s)" % param_str[-1].rstrip(','))
1095 if 'serialize' == context:
1096 if not self.is_switch and not self.var_followed_by_fixed_fields:
1097 _c(' %s *xcb_out = *_buffer;', self.c_type)
1098 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
1099 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
1101 _c(' char *xcb_out = *_buffer;')
1102 _c(' unsigned int xcb_buffer_len = 0;')
1103 prefix = [('_aux', '->', self)]
1106 elif context in ('unserialize', 'unpack'):
1107 _c(' char *xcb_tmp = (char *)_buffer;')
1108 if not self.is_switch:
1109 if not self.var_followed_by_fixed_fields:
1110 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1111 prefix = [('_aux', '->', self)]
1113 _c(' %s xcb_out;', self.c_type)
1114 prefix = [('xcb_out', '.', self)]
1116 aux_var = '_aux' # default for unpack: single pointer
1117 # note: unserialize not generated for switch
1118 if 'unserialize' == context:
1119 aux_var = '(*_aux)' # unserialize: double pointer (!)
1120 prefix = [(aux_var, '->', self)]
1122 _c(' unsigned int xcb_buffer_len = 0;')
1123 _c(' unsigned int xcb_block_len = 0;')
1124 _c(' unsigned int xcb_pad = 0;')
1126 elif 'sizeof' == context:
1127 param_names = [p[2] for p in params]
1129 # switch: call _unpack()
1130 _c(' %s _aux;', self.c_type)
1131 _c(' return %s(%s, &_aux);', self.c_unpack_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1134 elif self.var_followed_by_fixed_fields:
1135 # special case: call _unserialize()
1136 _c(' %s *_aux = NULL;', self.c_type)
1137 _c(' return %s(%s, &_aux);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1141 _c(' char *xcb_tmp = (char *)_buffer;')
1142 prefix = [('_aux', '->', self)]
1144 count = _c_serialize_helper(context, self, code_lines, temp_vars, prefix=prefix)
1145 # update variable size fields (only important for context=='serialize'
1146 variable_size_fields = count
1147 if 'serialize' == context:
1148 temp_vars.append(' unsigned int xcb_pad = 0;')
1149 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
1150 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
1151 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
1152 temp_vars.append(' unsigned int xcb_block_len = 0;')
1153 temp_vars.append(' unsigned int i;')
1154 temp_vars.append(' char *xcb_tmp;')
1155 elif 'sizeof' == context:
1156 # neither switch nor intermixed fixed and variable size fields:
1157 # evaluate parameters directly
1158 if not (self.is_switch or self.var_followed_by_fixed_fields):
1160 # look if we have to declare an '_aux' variable at all
1161 if len(filter(lambda x: x.find('_aux')!=-1, code_lines))>0:
1162 if not self.var_followed_by_fixed_fields:
1163 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1165 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1167 _c(' unsigned int xcb_buffer_len = 0;')
1168 _c(' unsigned int xcb_block_len = 0;')
1169 _c(' unsigned int xcb_pad = 0;')
1175 for l in code_lines:
1178 # variable sized fields have been collected, now
1179 # allocate memory and copy everything into a continuous memory area
1180 # note: this is not necessary in case of unpack
1181 if context in ('serialize', 'unserialize'):
1183 _c(' if (NULL == %s) {', aux_ptr)
1184 _c(' /* allocate memory */')
1185 _c(' %s = malloc(xcb_buffer_len);', aux_ptr)
1186 if 'serialize' == context:
1187 _c(' *_buffer = xcb_out;')
1191 # serialize: handle variable size fields in a loop
1192 if 'serialize' == context:
1193 if not self.is_switch and not self.var_followed_by_fixed_fields:
1194 if len(wire_fields)>0:
1195 _c(' *xcb_out = *_aux;')
1196 # copy variable size fields into the buffer
1197 if variable_size_fields > 0:
1199 if not self.is_switch and not self.var_followed_by_fixed_fields:
1200 _c(' xcb_tmp = (char*)++xcb_out;')
1201 _c(' xcb_tmp += xcb_out_pad;')
1203 _c(' xcb_tmp = xcb_out;')
1205 # variable sized fields
1206 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1207 _c(' if (0 != xcb_parts[i].iov_base && 0 != xcb_parts[i].iov_len)')
1208 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1209 _c(' if (0 != xcb_parts[i].iov_len)')
1210 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1213 # unserialize: assign variable size fields individually
1214 if 'unserialize' == context:
1215 _c(' *%s = xcb_out;', aux_ptr)
1216 _c(' xcb_tmp = (char *)(*_aux+1);')
1217 for field in param_fields:
1218 if not field.type.fixed_size():
1219 _c(' memcpy(xcb_tmp, %s, %s_len);', field.c_field_name, field.c_field_name)
1220 _c(' xcb_tmp += %s_len;', field.c_field_name)
1223 _c(' return xcb_buffer_len;')
1227 def _c_iterator_get_end(field, accum):
1229 Figures out what C code is needed to find the end of a variable-length structure field.
1230 For nested structures, recurses into its last variable-sized field.
1231 For lists, calls the end function
1233 if field.type.is_container:
1234 accum = field.c_accessor_name + '(' + accum + ')'
1235 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1236 if field.type.is_list:
1237 # XXX we can always use the first way
1238 if field.type.member.is_simple:
1239 return field.c_end_name + '(' + accum + ')'
1241 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1243 def _c_iterator(self, name):
1245 Declares the iterator structure and next/end functions for a given type.
1250 _h(' * @brief %s', self.c_iterator_type)
1252 _h('typedef struct %s {', self.c_iterator_type)
1253 _h(' %s *data; /**< */', self.c_type)
1254 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1255 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1256 _h('} %s;', self.c_iterator_type)
1262 _h(' * Get the next element of the iterator')
1263 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1265 _h(' * Get the next element in the iterator. The member rem is')
1266 _h(' * decreased by one. The member data points to the next')
1267 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1271 _hc('/*****************************************************************************')
1273 _hc(' ** void %s', self.c_next_name)
1275 _hc(' ** @param %s *i', self.c_iterator_type)
1276 _hc(' ** @returns void')
1278 _hc(' *****************************************************************************/')
1281 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1282 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1285 if not self.fixed_size():
1286 _c(' %s *R = i->data;', self.c_type)
1289 # FIXME - how to determine the size of a variable size union??
1290 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1292 if self.need_sizeof:
1293 _c(' xcb_generic_iterator_t child;')
1294 _c(' child.data = (%s *)(((char *)R) + %s(R));',
1295 self.c_type, self.c_sizeof_name)
1296 _c(' i->index = (char *) child.data - (char *) i->data;')
1298 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1299 _c(' i->index = child.index;')
1301 _c(' i->data = (%s *) child.data;', self.c_type)
1306 _c(' i->index += sizeof(%s);', self.c_type)
1312 _h(' * Return the iterator pointing to the last element')
1313 _h(' * @param i An %s', self.c_iterator_type)
1314 _h(' * @return The iterator pointing to the last element')
1316 _h(' * Set the current element in the iterator to the last element.')
1317 _h(' * The member rem is set to 0. The member data points to the')
1318 _h(' * last element.')
1322 _hc('/*****************************************************************************')
1324 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1326 _hc(' ** @param %s i', self.c_iterator_type)
1327 _hc(' ** @returns xcb_generic_iterator_t')
1329 _hc(' *****************************************************************************/')
1331 _hc('xcb_generic_iterator_t')
1332 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1333 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1335 _c(' xcb_generic_iterator_t ret;')
1337 if self.fixed_size():
1338 _c(' ret.data = i.data + i.rem;')
1339 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1342 _c(' while(i.rem > 0)')
1343 _c(' %s(&i);', self.c_next_name)
1344 _c(' ret.data = i.data;')
1345 _c(' ret.rem = i.rem;')
1346 _c(' ret.index = i.index;')
1351 def _c_accessor_get_length(expr, field_mapping=None):
1353 Figures out what C code is needed to get a length field.
1354 The field_mapping parameter can be used to change the absolute name of a length field.
1355 For fields that follow a variable-length field, use the accessor.
1356 Otherwise, just reference the structure field directly.
1359 lenfield_name = expr.lenfield_name
1360 if lenfield_name is not None:
1361 if field_mapping is not None:
1362 lenfield_name = field_mapping[lenfield_name][0]
1364 if expr.lenfield is not None and expr.lenfield.prev_varsized_field is not None:
1365 # special case: variable and fixed size fields are intermixed
1366 # if the lenfield is among the fixed size fields, there is no need
1367 # to call a special accessor function like <expr.lenfield.c_accessor_name + '(' + prefix + ')'>
1368 return field_mapping(expr.lenfield_name)
1369 elif expr.lenfield_name is not None:
1370 return lenfield_name
1372 return str(expr.nmemb)
1374 def _c_accessor_get_expr(expr, field_mapping):
1376 Figures out what C code is needed to get the length of a list field.
1377 The field_mapping parameter can be used to change the absolute name of a length field.
1378 Recurses for math operations.
1379 Returns bitcount for value-mask fields.
1380 Otherwise, uses the value of the length field.
1382 lenexp = _c_accessor_get_length(expr, field_mapping)
1385 return '(' + '~' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1386 elif expr.op == 'popcount':
1387 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, field_mapping) + ')'
1388 elif expr.op == 'enumref':
1389 enum_name = expr.lenfield_type.name
1390 constant_name = expr.lenfield_name
1391 c_name = _n(enum_name + (constant_name,)).upper()
1393 elif expr.op == 'sumof':
1394 # locate the referenced list object
1395 list_obj = expr.lenfield_type
1397 for f in expr.lenfield_parent.fields:
1398 if f.field_name == expr.lenfield_name:
1403 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1404 list_name = field_mapping[field.c_field_name][0]
1405 c_length_func = "%s(%s)" % (field.c_length_name, list_name)
1406 # note: xcb_sumof() has only been defined for integers
1407 c_length_func = _c_accessor_get_expr(field.type.expr, field_mapping)
1408 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1409 elif expr.op != None:
1410 return ('(' + _c_accessor_get_expr(expr.lhs, field_mapping) +
1411 ' ' + expr.op + ' ' +
1412 _c_accessor_get_expr(expr.rhs, field_mapping) + ')')
1414 return 'xcb_popcount(' + lenexp + ')'
1418 def _c_accessors_field(self, field):
1420 Declares the accessor functions for a non-list field that follows a variable-length field.
1422 c_type = self.c_type
1424 # special case: switch
1425 switch_obj = self if self.is_switch else None
1427 switch_obj = self.parents[-1]
1428 if switch_obj is not None:
1429 c_type = switch_obj.c_type
1431 if field.type.is_simple:
1434 _hc('/*****************************************************************************')
1436 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1438 _hc(' ** @param const %s *R', c_type)
1439 _hc(' ** @returns %s', field.c_field_type)
1441 _hc(' *****************************************************************************/')
1443 _hc('%s', field.c_field_type)
1444 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1445 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1447 if field.prev_varsized_field is None:
1448 _c(' return (%s *) (R + 1);', field.c_field_type)
1450 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1451 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1452 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1457 _hc('/*****************************************************************************')
1459 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1461 _hc(' ** @param const %s *R', c_type)
1462 _hc(' ** @returns %s *', field.c_field_type)
1464 _hc(' *****************************************************************************/')
1466 if field.type.is_switch and switch_obj is None:
1467 return_type = 'void *'
1469 return_type = '%s *' % field.c_field_type
1472 _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
1473 _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
1475 if field.prev_varsized_field is None:
1476 _c(' return (%s) (R + 1);', return_type)
1477 # note: the special case 'variable fields followed by fixed size fields'
1478 # is not of any consequence here, since the ordering gets
1479 # 'corrected' in the reply function
1481 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1482 _c(' return (%s) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1483 return_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1487 def _c_accessors_list(self, field):
1489 Declares the accessor functions for a list field.
1490 Declares a direct-accessor function only if the list members are fixed size.
1491 Declares length and get-iterator functions always.
1494 c_type = self.c_type
1496 # special case: switch
1497 # in case of switch, 2 params have to be supplied to certain accessor functions:
1498 # 1. the anchestor object (request or reply)
1499 # 2. the (anchestor) switch object
1500 # the reason is that switch is either a child of a request/reply or nested in another switch,
1501 # so whenever we need to access a length field, we might need to refer to some anchestor type
1502 switch_obj = self if self.is_switch else None
1504 switch_obj = self.parents[-1]
1505 if switch_obj is not None:
1506 c_type = switch_obj.c_type
1510 parents = self.parents if hasattr(self, 'parents') else [self]
1511 # 'R': parents[0] is always the 'toplevel' container type
1512 params.append(('const %s *R' % parents[0].c_type, parents[0]))
1513 fields.update(_c_helper_field_mapping(parents[0], [('R', '->', parents[0])], flat=True))
1514 # auxiliary object for 'R' parameters
1517 if switch_obj is not None:
1518 # now look where the fields are defined that are needed to evaluate
1519 # the switch expr, and store the parent objects in accessor_params and
1520 # the fields in switch_fields
1522 # 'S': name for the 'toplevel' switch
1523 toplevel_switch = parents[1]
1524 params.append(('const %s *S' % toplevel_switch.c_type, toplevel_switch))
1525 fields.update(_c_helper_field_mapping(toplevel_switch, [('S', '->', toplevel_switch)], flat=True))
1527 # initialize prefix for everything "below" S
1528 prefix_str = '/* %s */ S' % toplevel_switch.name[-1]
1529 prefix = [(prefix_str, '->', toplevel_switch)]
1531 # look for fields in the remaining containers
1532 for p in parents[2:] + [self]:
1533 # the separator between parent and child is always '.' here,
1534 # because of nested switch statements
1535 if not p.is_bitcase or (p.is_bitcase and p.has_name):
1536 prefix.append((p.name[-1], '.', p))
1537 fields.update(_c_helper_field_mapping(p, prefix, flat=True))
1539 # auxiliary object for 'S' parameter
1544 if list.member.fixed_size():
1545 idx = 1 if switch_obj is not None else 0
1548 _hc('/*****************************************************************************')
1550 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1552 _hc(' ** @param %s', params[idx][0])
1553 _hc(' ** @returns %s *', field.c_field_type)
1555 _hc(' *****************************************************************************/')
1557 _hc('%s *', field.c_field_type)
1559 _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
1560 _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
1563 if switch_obj is not None:
1564 _c(' return %s;', fields[field.c_field_name][0])
1565 elif field.prev_varsized_field is None:
1566 _c(' return (%s *) (R + 1);', field.c_field_type)
1568 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1569 _c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1570 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1575 _hc('/*****************************************************************************')
1577 _hc(' ** int %s', field.c_length_name)
1579 _hc(' ** @param const %s *R', c_type)
1580 _hc(' ** @returns int')
1582 _hc(' *****************************************************************************/')
1585 if switch_obj is not None:
1586 _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
1587 spacing = ' '*(len(field.c_length_name)+2)
1588 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1589 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1590 length = _c_accessor_get_expr(field.type.expr, fields)
1592 _h('%s (const %s *R /**< */);', field.c_length_name, c_type)
1593 _c('%s (const %s *R /**< */)', field.c_length_name, c_type)
1594 length = _c_accessor_get_expr(field.type.expr, fields)
1596 _c(' return %s;', length)
1599 if field.type.member.is_simple:
1602 _hc('/*****************************************************************************')
1604 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1606 _hc(' ** @param const %s *R', c_type)
1607 _hc(' ** @returns xcb_generic_iterator_t')
1609 _hc(' *****************************************************************************/')
1611 _hc('xcb_generic_iterator_t')
1612 if switch_obj is not None:
1613 _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
1614 spacing = ' '*(len(field.c_end_name)+2)
1615 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1616 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1618 _h('%s (const %s *R /**< */);', field.c_end_name, c_type)
1619 _c('%s (const %s *R /**< */)', field.c_end_name, c_type)
1621 _c(' xcb_generic_iterator_t i;')
1623 param = 'R' if switch_obj is None else 'S'
1624 if switch_obj is not None:
1625 _c(' i.data = %s + %s;', fields[field.c_field_name][0],
1626 _c_accessor_get_expr(field.type.expr, fields))
1627 elif field.prev_varsized_field == None:
1628 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype,
1629 _c_accessor_get_expr(field.type.expr, fields))
1631 _c(' xcb_generic_iterator_t child = %s;',
1632 _c_iterator_get_end(field.prev_varsized_field, 'R'))
1633 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype,
1634 _c_accessor_get_expr(field.type.expr, fields))
1637 _c(' i.index = (char *) i.data - (char *) %s;', param)
1644 _hc('/*****************************************************************************')
1646 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1648 _hc(' ** @param const %s *R', c_type)
1649 _hc(' ** @returns %s', field.c_iterator_type)
1651 _hc(' *****************************************************************************/')
1654 _hc('%s', field.c_iterator_type)
1655 if switch_obj is not None:
1656 _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
1657 spacing = ' '*(len(field.c_iterator_name)+2)
1658 _h('%sconst %s *S /**< */);', spacing, S_obj.c_type)
1659 _c('%sconst %s *S /**< */)', spacing, S_obj.c_type)
1661 _h('%s (const %s *R /**< */);', field.c_iterator_name, c_type)
1662 _c('%s (const %s *R /**< */)', field.c_iterator_name, c_type)
1664 _c(' %s i;', field.c_iterator_type)
1666 if switch_obj is not None:
1667 _c(' i.data = %s;', fields[field.c_field_name][0])
1668 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1669 elif field.prev_varsized_field == None:
1670 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1672 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1673 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));',
1674 field.c_field_type, field.c_field_type)
1675 if switch_obj is None:
1676 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, fields))
1677 _c(' i.index = (char *) i.data - (char *) %s;', 'R' if switch_obj is None else 'S' )
1681 def _c_accessors(self, name, base):
1683 Declares the accessor functions for the fields of a structure.
1685 # no accessors for switch itself -
1686 # switch always needs to be unpacked explicitly
1687 # if self.is_switch:
1691 for field in self.fields:
1692 if field.type.is_list and not field.type.fixed_size():
1693 _c_accessors_list(self, field)
1694 elif field.prev_varsized_field is not None or not field.type.fixed_size():
1695 _c_accessors_field(self, field)
1697 def c_simple(self, name):
1699 Exported function that handles cardinal type declarations.
1700 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1702 _c_type_setup(self, name, ())
1704 if (self.name != name):
1709 _h('typedef %s %s;', _t(self.name), my_name)
1712 _c_iterator(self, name)
1714 def _c_complex(self):
1716 Helper function for handling all structure types.
1717 Called for all structs, requests, replies, events, errors.
1722 _h(' * @brief %s', self.c_type)
1724 _h('typedef %s %s {', self.c_container, self.c_type)
1730 for field in self.fields:
1731 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1732 varfield = field.c_field_name
1735 struct_fields.append(field)
1737 for field in struct_fields:
1738 length = len(field.c_field_type)
1739 # account for '*' pointer_spec
1740 if not field.type.fixed_size():
1742 maxtypelen = max(maxtypelen, length)
1744 def _c_complex_field(self, field, space=''):
1745 if (field.type.fixed_size() or
1746 # in case of switch with switch children, don't make the field a pointer
1747 # necessary for unserialize to work
1748 (self.is_switch and field.type.is_switch)):
1749 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1750 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1752 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1753 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1755 if not self.is_switch:
1756 for field in struct_fields:
1757 _c_complex_field(self, field)
1759 for b in self.bitcases:
1762 _h(' struct _%s {', b.c_field_name)
1764 for field in b.type.fields:
1765 _c_complex_field(self, field, space)
1767 _h(' } %s;', b.c_field_name)
1769 _h('} %s;', self.c_type)
1771 def c_struct(self, name):
1773 Exported function that handles structure declarations.
1775 _c_type_setup(self, name, ())
1777 _c_accessors(self, name, name)
1778 _c_iterator(self, name)
1780 def c_union(self, name):
1782 Exported function that handles union declarations.
1784 _c_type_setup(self, name, ())
1786 _c_iterator(self, name)
1788 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1790 Declares a request function.
1793 # Four stunningly confusing possibilities here:
1796 # ------------------------------
1798 # 0 flag CHECKED flag Normal Mode
1799 # void_cookie req_cookie
1800 # ------------------------------
1801 # "req_checked" "req_unchecked"
1802 # CHECKED flag 0 flag Abnormal Mode
1803 # void_cookie req_cookie
1804 # ------------------------------
1807 # Whether we are _checked or _unchecked
1808 checked = void and not regular
1809 unchecked = not void and not regular
1811 # What kind of cookie we return
1812 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1814 # What flag is passed to xcb_request
1815 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1817 # Global extension id variable or NULL for xproto
1818 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1820 # What our function name is
1821 func_name = self.c_request_name if not aux else self.c_aux_name
1823 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1825 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1829 maxtypelen = len('xcb_connection_t')
1831 # special case: list with variable size elements
1832 list_with_var_size_elems = False
1834 for field in self.fields:
1836 # The field should appear as a call parameter
1837 param_fields.append(field)
1838 if field.wire and not field.auto:
1839 # We need to set the field up in the structure
1840 wire_fields.append(field)
1841 if field.type.need_serialize or field.type.need_sizeof:
1842 serial_fields.append(field)
1844 for field in param_fields:
1845 c_field_const_type = field.c_field_const_type
1846 if field.type.need_serialize and not aux:
1847 c_field_const_type = "const void"
1848 if len(c_field_const_type) > maxtypelen:
1849 maxtypelen = len(c_field_const_type)
1850 if field.type.is_list and not field.type.member.fixed_size():
1851 list_with_var_size_elems = True
1857 _h(' * Delivers a request to the X server')
1858 _h(' * @param c The connection')
1859 _h(' * @return A cookie')
1861 _h(' * Delivers a request to the X server.')
1864 _h(' * This form can be used only if the request will not cause')
1865 _h(' * a reply to be generated. Any returned error will be')
1866 _h(' * saved for handling by xcb_request_check().')
1868 _h(' * This form can be used only if the request will cause')
1869 _h(' * a reply to be generated. Any returned error will be')
1870 _h(' * placed in the event queue.')
1874 _hc('/*****************************************************************************')
1876 _hc(' ** %s %s', cookie_type, func_name)
1879 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1880 _hc(' ** @param xcb_connection_t%s *c', spacing)
1882 for field in param_fields:
1883 c_field_const_type = field.c_field_const_type
1884 if field.type.need_serialize and not aux:
1885 c_field_const_type = "const void"
1886 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1887 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1889 _hc(' ** @returns %s', cookie_type)
1891 _hc(' *****************************************************************************/')
1893 _hc('%s', cookie_type)
1895 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1896 comma = ',' if len(param_fields) else ');'
1897 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1898 comma = ',' if len(param_fields) else ')'
1899 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1901 func_spacing = ' ' * (len(func_name) + 2)
1902 count = len(param_fields)
1903 for field in param_fields:
1905 c_field_const_type = field.c_field_const_type
1906 c_pointer = field.c_pointer
1907 if field.type.need_serialize and not aux:
1908 c_field_const_type = "const void"
1910 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1911 comma = ',' if count else ');'
1912 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1913 spacing, c_pointer, field.c_field_name, comma)
1914 comma = ',' if count else ')'
1915 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1916 spacing, c_pointer, field.c_field_name, comma)
1919 if not self.var_followed_by_fixed_fields:
1920 for field in param_fields:
1921 if not field.type.fixed_size():
1923 if field.type.need_serialize:
1924 # _serialize() keeps track of padding automatically
1926 dimension = count + 2
1929 _c(' static const xcb_protocol_request_t xcb_req = {')
1930 _c(' /* count */ %d,', count)
1931 _c(' /* ext */ %s,', func_ext_global)
1932 _c(' /* opcode */ %s,', self.c_request_name.upper())
1933 _c(' /* isvoid */ %d', 1 if void else 0)
1937 _c(' struct iovec xcb_parts[%d];', dimension)
1938 _c(' %s xcb_ret;', func_cookie)
1939 _c(' %s xcb_out;', self.c_type)
1940 if self.var_followed_by_fixed_fields:
1941 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
1942 _c(' void *xcb_aux = 0;')
1945 for idx, f in enumerate(serial_fields):
1947 _c(' void *xcb_aux%d = 0;' % (idx))
1948 if list_with_var_size_elems:
1949 _c(' unsigned int i;')
1950 _c(' unsigned int xcb_tmp_len;')
1951 _c(' char *xcb_tmp;')
1953 # simple request call tracing
1954 # _c(' printf("in function %s\\n");' % func_name)
1957 for field in wire_fields:
1958 if field.type.fixed_size():
1959 if field.type.is_expr:
1960 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr, None))
1961 elif field.type.is_pad:
1962 if field.type.nmemb == 1:
1963 _c(' xcb_out.%s = 0;', field.c_field_name)
1965 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
1967 if field.type.nmemb == 1:
1968 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
1970 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
1972 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
1973 serialize_args = get_serialize_params(context, type_obj,
1976 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
1978 # calls in order to free dyn. all. memory
1982 if not self.var_followed_by_fixed_fields:
1983 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
1984 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
1985 _c(' xcb_parts[3].iov_base = 0;')
1986 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
1990 for field in param_fields:
1991 if not field.type.fixed_size():
1992 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
1993 # default: simple cast to char *
1994 if not field.type.need_serialize and not field.type.need_sizeof:
1995 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1996 if field.type.is_list:
1997 if field.type.member.fixed_size():
1998 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
1999 _c_accessor_get_expr(field.type.expr, None),
2000 field.type.member.c_wiretype)
2002 list_length = _c_accessor_get_expr(field.type.expr, None)
2005 _c(" xcb_parts[%d].iov_len = 0;" % count)
2006 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
2007 _c(" for(i=0; i<%s; i++) {" % list_length)
2008 _c(" xcb_tmp_len = %s(xcb_tmp);" %
2009 (field.type.c_sizeof_name))
2010 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
2011 _c(" xcb_tmp += xcb_tmp_len;")
2014 # not supposed to happen
2015 raise Exception("unhandled variable size field %s" % field.c_field_name)
2018 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
2019 idx = serial_fields.index(field)
2020 aux_var = '&xcb_aux%d' % idx
2021 context = 'serialize' if aux else 'sizeof'
2022 _c(' xcb_parts[%d].iov_len = ', count)
2024 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
2025 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
2026 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
2027 free_calls.append(' free(xcb_aux%d);' % idx)
2029 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
2030 func_name = field.type.c_sizeof_name
2031 _c(' %s (%s);', func_name, serialize_args)
2034 if not (field.type.need_serialize or field.type.need_sizeof):
2035 # the _serialize() function keeps track of padding automatically
2036 _c(' xcb_parts[%d].iov_base = 0;', count)
2037 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
2040 # elif self.var_followed_by_fixed_fields:
2042 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
2043 # request header: opcodes + length
2044 _c(' xcb_parts[2].iov_len = 2*sizeof(uint8_t) + sizeof(uint16_t);')
2047 buffer_var = '&xcb_aux'
2048 serialize_args = get_serialize_args(self, buffer_var, '&xcb_out', 'serialize')
2049 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
2050 _c(' xcb_parts[%d].iov_base = (char *) xcb_aux;', count)
2051 free_calls.append(' free(xcb_aux);')
2052 # no padding necessary - _serialize() keeps track of padding automatically
2055 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
2057 # free dyn. all. data, if any
2058 for f in free_calls:
2060 _c(' return xcb_ret;')
2063 def _c_reply(self, name):
2065 Declares the function that returns the reply structure.
2067 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
2068 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
2069 spacing3 = ' ' * (len(self.c_reply_name) + 2)
2071 # check if _unserialize() has to be called for any field
2072 def look_for_special_cases(complex_obj):
2073 unserialize_fields = []
2074 # no unserialize call in case of switch
2075 if not complex_obj.is_switch:
2076 for field in complex_obj.fields:
2077 # three cases: 1. field with special case
2078 # 2. container that contains special case field
2079 # 3. list with special case elements
2080 if field.type.var_followed_by_fixed_fields:
2081 unserialize_fields.append(field)
2082 elif field.type.is_container:
2083 unserialize_fields += look_for_special_cases(field.type)
2084 elif field.type.is_list:
2085 if field.type.member.var_followed_by_fixed_fields:
2086 unserialize_fields.append(field)
2087 if field.type.member.is_container:
2088 unserialize_fields += look_for_special_cases(field.type.member)
2089 return unserialize_fields
2091 unserialize_fields = look_for_special_cases(self.reply)
2095 _h(' * Return the reply')
2096 _h(' * @param c The connection')
2097 _h(' * @param cookie The cookie')
2098 _h(' * @param e The xcb_generic_error_t supplied')
2100 _h(' * Returns the reply of the request asked by')
2102 _h(' * The parameter @p e supplied to this function must be NULL if')
2103 _h(' * %s(). is used.', self.c_unchecked_name)
2104 _h(' * Otherwise, it stores the error if any.')
2106 _h(' * The returned value must be freed by the caller using free().')
2110 _hc('/*****************************************************************************')
2112 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
2114 _hc(' ** @param xcb_connection_t%s *c', spacing1)
2115 _hc(' ** @param %s cookie', self.c_cookie_type)
2116 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
2117 _hc(' ** @returns %s *', self.c_reply_type)
2119 _hc(' *****************************************************************************/')
2121 _hc('%s *', self.c_reply_type)
2122 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
2123 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
2124 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
2125 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
2128 if len(unserialize_fields)>0:
2129 # certain variable size fields need to be unserialized explicitly
2130 _c(' %s *reply = (%s *) xcb_wait_for_reply(c, cookie.sequence, e);',
2131 self.c_reply_type, self.c_reply_type)
2133 for field in unserialize_fields:
2134 if field.type.is_list:
2135 _c(' %s %s_iter = %s(reply);', field.c_iterator_type, field.c_field_name, field.c_iterator_name)
2136 _c(' int %s_len = %s(reply);', field.c_field_name, field.c_length_name)
2137 _c(' %s *%s_data;', field.c_field_type, field.c_field_name)
2139 raise Exception('not implemented: call _unserialize() in reply for non-list type %s', field.c_field_type)
2140 # call _unserialize(), using the reply as source and target buffer
2141 _c(' /* special cases: transform parts of the reply to match XCB data structures */')
2142 for field in unserialize_fields:
2143 if field.type.is_list:
2144 _c(' for(i=0; i<%s_len; i++) {', field.c_field_name)
2145 _c(' %s_data = %s_iter.data;', field.c_field_name, field.c_field_name)
2146 _c(' %s((const void *)%s_data, &%s_data);', field.type.c_unserialize_name,
2147 field.c_field_name, field.c_field_name)
2148 _c(' %s(&%s_iter);', field.type.c_next_name, field.c_field_name)
2150 # return the transformed reply
2151 _c(' return reply;')
2154 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
2158 def _c_opcode(name, opcode):
2160 Declares the opcode define for requests, events, and errors.
2164 _h('/** Opcode for %s. */', _n(name))
2165 _h('#define %s %s', _n(name).upper(), opcode)
2167 def _c_cookie(self, name):
2169 Declares the cookie type for a non-void request.
2174 _h(' * @brief %s', self.c_cookie_type)
2176 _h('typedef struct %s {', self.c_cookie_type)
2177 _h(' unsigned int sequence; /**< */')
2178 _h('} %s;', self.c_cookie_type)
2180 def c_request(self, name):
2182 Exported function that handles request declarations.
2184 _c_type_setup(self, name, ('request',))
2187 # Cookie type declaration
2188 _c_cookie(self, name)
2191 _c_opcode(name, self.opcode)
2193 # Request structure declaration
2197 _c_type_setup(self.reply, name, ('reply',))
2198 # Reply structure definition
2199 _c_complex(self.reply)
2200 # Request prototypes
2201 _c_request_helper(self, name, self.c_cookie_type, False, True)
2202 _c_request_helper(self, name, self.c_cookie_type, False, False)
2204 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
2205 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
2207 _c_accessors(self.reply, name + ('reply',), name)
2208 _c_reply(self, name)
2210 # Request prototypes
2211 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2212 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2214 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2215 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2218 def c_event(self, name):
2220 Exported function that handles event declarations.
2222 _c_type_setup(self, name, ('event',))
2225 _c_opcode(name, self.opcodes[name])
2227 if self.name == name:
2228 # Structure definition
2233 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2235 def c_error(self, name):
2237 Exported function that handles error declarations.
2239 _c_type_setup(self, name, ('error',))
2242 _c_opcode(name, self.opcodes[name])
2244 if self.name == name:
2245 # Structure definition
2250 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2253 # Main routine starts here
2255 # Must create an "output" dictionary before any xcbgen imports.
2256 output = {'open' : c_open,
2258 'simple' : c_simple,
2260 'struct' : c_struct,
2262 'request' : c_request,
2267 # Boilerplate below this point
2269 # Check for the argument that specifies path to the xcbgen python package.
2271 opts, args = getopt.getopt(sys.argv[1:], 'p:')
2272 except getopt.GetoptError, err:
2274 print 'Usage: c_client.py [-p path] file.xml'
2277 for (opt, arg) in opts:
2279 sys.path.append(arg)
2281 # Import the module class
2283 from xcbgen.state import Module
2286 print 'Failed to load the xcbgen Python package!'
2287 print 'Make sure that xcb/proto installed it on your Python path.'
2288 print 'If not, you will need to create a .pth file or define $PYTHONPATH'
2289 print 'to extend the path.'
2290 print 'Refer to the README file in xcb/proto for more info.'
2294 # Parse the xml header
2295 module = Module(args[0], output)
2297 # Build type-registry and resolve type dependencies