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 switch data types
28 # due to weird dependencies, I see no way to do this more elegant at the moment
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_sizeof_name = _n(name + ('sizeof',))
296 # if hasattr(self, 'reply'):
297 # if self.reply is not None:
298 # self.c_serialize_name = _n(name + ('reply', 'serialize'))
299 # self.c_unserialize_name = _n(name + ('reply', 'unserialize'))
300 # indicates rare structs where variable size fields are followed fixed size fields
301 self.var_followed_by_fixed_fields = False
303 # whether a request or reply has a switch field
305 self.need_serialize = True
306 self.c_container = 'struct'
307 for bitcase in self.bitcases:
308 bitcase.c_field_name = _cpp(bitcase.field_name)
309 _c_type_setup(bitcase.type, bitcase.field_type, ())
311 elif self.is_container:
313 self.c_container = 'union' if self.is_union else 'struct'
314 prev_varsized_field = None
315 prev_varsized_offset = 0
316 first_field_after_varsized = None
318 for field in self.fields:
319 _c_type_setup(field.type, field.field_type, ())
320 if field.type.is_list:
321 _c_type_setup(field.type.member, field.field_type, ())
322 if (field.type.nmemb is None):
323 # if field.type.member.need_serialize:
324 # self.need_serialize = True
325 self.need_sizeof = True
326 # print "-> variable size list elements: %s (%s %s)" % (self.c_type, field.field_type, field.field_name)
328 field.c_field_type = _t(field.field_type)
329 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
330 field.c_field_name = _cpp(field.field_name)
331 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
332 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
333 # correct the c_pointer field for variable size non-list types
334 if not field.type.fixed_size() and field.c_pointer == ' ':
335 field.c_pointer = '*'
336 if field.type.is_list and not field.type.member.fixed_size():
337 field.c_pointer = '*'
338 if field.type.is_switch:
339 field.c_pointer = '*'
340 field.c_field_const_type = 'const ' + field.c_field_type
342 elif not field.type.fixed_size() and not field.type.is_bitcase:
343 #self.need_serialize = True
344 self.need_sizeof = True
346 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
347 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
348 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
349 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
351 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
353 field.prev_varsized_field = prev_varsized_field
354 field.prev_varsized_offset = prev_varsized_offset
356 if prev_varsized_offset == 0:
357 first_field_after_varsized = field
358 field.first_field_after_varsized = first_field_after_varsized
360 if field.type.fixed_size():
361 prev_varsized_offset += field.type.size
362 # special case: intermixed fixed and variable size fields
363 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
364 if not self.is_union:
365 self.need_serialize = True
366 self.var_followed_by_fixed_fields = True
368 self.last_varsized_field = field
369 prev_varsized_field = field
370 prev_varsized_offset = 0
372 # very special case - if self.var_followed_by_fixed_fields==True,
373 # we have to generate accessor functions also for fixed size fields
374 # now there might a naming conflict if the length field ends with _length
375 if self.var_followed_by_fixed_fields:
376 if field.type.is_list:
377 if field.type.expr.lenfield_name is not None:
378 full_lenfield_name = _n(name + (field.type.expr.lenfield_name,))
379 if full_lenfield_name == field.c_length_name:
380 field.c_length_name += '_'
382 if self.need_serialize:
383 # when _unserialize() is wanted, create _sizeof() as well for consistency reasons
384 self.need_sizeof = True
386 # as switch does never appear at toplevel,
387 # continue here with type construction
389 if self.c_type not in finished_switch:
390 finished_switch.append(self.c_type)
391 # special: switch C structs get pointer fields for variable-sized members
393 # FIXME: declare switch (un)packing functions
394 _c_accessors(self, name, name)
396 # FIXME - in case of request/reply, serialize() is not always needed
397 if not self.is_bitcase:
398 if self.need_serialize:
399 if self.c_serialize_name not in finished_serializers:
400 finished_serializers.append(self.c_serialize_name)
404 if self.c_sizeof_name not in finished_sizeof:
405 finished_sizeof.append(self.c_sizeof_name)
406 _c_sizeof_helper(self)
409 def get_request_fields(self):
413 for field in self.fields:
415 # the field should appear as a parameter in the function call
416 param_fields.append(field)
417 if field.wire and not field.auto:
418 if field.type.fixed_size() and not self.is_switch:
419 # field in the xcb_out structure
420 wire_fields.append(field)
421 # fields like 'pad0' are skipped!
423 return (param_fields, wire_fields)
424 # get_request_fields()
426 def get_expr_fields(self):
427 # get the fields referenced by switch or list expression
428 def get_expr_field_names(expr):
430 if expr.lenfield_name is not None:
431 return [expr.lenfield_name]
433 # constant value expr
437 return get_expr_field_names(expr.rhs)
438 elif expr.op == 'popcount':
439 return get_expr_field_names(expr.rhs)
440 elif expr.op == 'sumof':
441 return [expr.lenfield_name]
442 elif expr.op == 'enumref':
445 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
446 # get_expr_field_names()
448 # resolve the field names with the parent structure(s)
449 unresolved_fields = get_expr_field_names(self.expr)
450 if unresolved_fields is None:
452 expr_fields = dict.fromkeys(unresolved_fields)
453 for p in reversed(self.parent):
454 parent_fields = dict((f.field_name, f) for f in p.fields)
455 for f in parent_fields.keys():
456 if f in unresolved_fields:
457 expr_fields[f] = parent_fields[f]
458 unresolved_fields.remove(f)
459 if len(unresolved_fields) == 0:
462 if None in expr_fields.values():
463 raise Exception("could not resolve all fields for %s" % self.name)
465 params = expr_fields.values()
469 def resolve_fields(anchestor, complex_obj=None):
470 """find fields referenced by anchestor or descendents with external scope"""
474 if complex_obj is None:
475 complex_obj = anchestor
476 for field in complex_obj.fields:
477 all_fields.append(field)
478 if field.type.is_switch or field.type.is_list:
479 expr_fields += get_expr_fields(field.type)
480 if field.type.is_container:
481 expr_fields += resolve_fields(anchestor, field.type)
482 # try to resolve expr fields
483 for e in expr_fields:
484 if e not in all_fields:
489 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
490 def add_param(params, param):
491 if param not in params:
494 param_fields, wire_fields = get_request_fields(self)
496 param_fields = get_expr_fields(self)
498 # _serialize function parameters
499 # cannot use set() for params, as series is important
501 if 'serialize' == context:
502 params.append(('void', '**', buffer_var))
503 elif context in ('unserialize', 'sizeof'):
504 params.append(('const void', '*', buffer_var))
506 # look for special cases
507 unresolved_fields = resolve_fields(self)
508 for f in unresolved_fields:
509 add_param(params, (f.c_field_type, '', f.c_field_name))
511 # make sure all required length fields are present
512 for p in param_fields:
513 if p.visible and not p.wire and not p.auto:
514 typespec = p.c_field_type
516 add_param(params, (typespec, pointerspec, p.c_field_name))
518 # parameter fields if any
520 for p in get_expr_fields(self):
521 typespec = p.c_field_const_type
522 pointerspec = p.c_pointer
523 add_param(params, (typespec, pointerspec, p.c_field_name))
525 # aux argument - structure to be serialized
526 if 'serialize' == context:
527 add_param(params, ('const %s' % self.c_type, '*', aux_var))
528 elif 'unserialize' == context:
530 add_param(params, ('%s' % self.c_type, '*', aux_var))
532 add_param(params, ('%s' % self.c_type, '**', aux_var))
533 if not self.is_switch and 'serialize' == context:
534 for p in param_fields:
535 if not p.type.fixed_size():
536 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
537 return (param_fields, wire_fields, params)
538 # get_serialize_params()
540 def _c_serialize_helper_prefix(prefix, aux_var='_aux', aux_sep='->'):
541 # prefix is a list of (field_name, anchestor object) tuples
542 # concatenate field names
544 for name, sep, obj in prefix:
547 sep = '.' if (obj.is_bitcase and obj.has_name) else '->'
550 lenfield_prefix = '' if prefix_str.find(aux_var)==0 else aux_var
553 if lenfield_prefix != '':
554 lenfield_prefix += aux_sep
555 lenfield_prefix += prefix_str
556 return (prefix_str, lenfield_prefix)
557 # _c_serialize_helper_prefix
559 def _c_field_mapping(context, complex_type, prefix):
560 def get_prefix(field, prefix):
561 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
563 if context in ('serialize', 'unserialize'):
564 if field.type.fixed_size() or complex_type.is_switch:
565 prefix_str = '_aux->'
567 raise Exception("unknown context '%s' in c_field_mapping" % context)
570 def get_field_name(fields, complex_type, prefix):
571 for f in complex_type.fields:
572 prefix_str = get_prefix(f, prefix)
574 fname = "%s%s" % (prefix_str, f.c_field_name)
575 if fields.has_key(f.field_name):
578 raise Exception("field name %s has been registered before" % f.field_name)
579 fields[f.field_name] = (fname, f)
580 if f.type.is_container:
581 get_field_name(fields, f.type, prefix+[(f.c_field_name, '', f.type)])
584 # dict(field_name : (c_field_name, field))
586 get_field_name(fields, complex_type, prefix)
588 # switch: get the fields referenced by the switch expr as well
589 # these may not belong to any structure
590 if complex_type.is_switch:
592 # FIXME: fields += get_serialize_params(context, complex_type)
597 def _c_serialize_helper_insert_padding(context, code_lines, space):
598 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
599 code_lines.append('%s /* padding */' % space)
600 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
601 code_lines.append('%s if (0 != xcb_pad) {' % space)
603 if 'serialize' == context:
604 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
605 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
606 code_lines.append('%s xcb_parts_idx++;' % space)
607 elif 'unserialize' == context:
608 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
610 code_lines.append('%s xcb_buffer_len += xcb_pad;' % space)
611 code_lines.append('%s xcb_pad = 0;' % space)
612 code_lines.append('%s }' % space)
613 code_lines.append('%s xcb_block_len = 0;' % space)
616 # _c_serialize_helper_insert_padding()
618 def _c_serialize_helper_switch(context, self, complex_name,
619 code_lines, temp_vars,
622 switch_prefix = prefix + [(complex_name, '->', self)]
623 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(switch_prefix)
624 switch_expr = _c_accessor_get_expr(self.expr)
626 for b in self.bitcases:
627 bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix_str)
628 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
629 b_prefix = switch_prefix
631 b_prefix = switch_prefix + [(b.c_field_name, '.', b.type)]
632 count += _c_serialize_helper_fields(context, b.type,
633 code_lines, temp_vars,
637 code_lines.append(' }')
639 if 'serialize' == context:
640 count += _c_serialize_helper_insert_padding(context, code_lines, space)
641 if 'unserialize' == context:
643 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
644 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
647 # _c_serialize_helper_switch
649 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
650 # switch is handled by this function as a special case
651 param_fields, wire_fields, params = get_serialize_params(context, self)
652 args = get_expr_fields(field.type)
653 field_mapping = _c_field_mapping(context, self, prefix)
655 # determine which params to pass to _unserialize() and their prefixes
656 switch_len_fields = resolve_fields(self, field.type)
657 bitcase_unresolved = resolve_fields(self, self)
658 if len(bitcase_unresolved) != 0:
659 raise Exception('unresolved fields within bitcase is not supported at this point')
661 for a in switch_len_fields:
662 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
664 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
665 # switch_field_name = field_mapping[field.field_name][0]
666 # call _unserialize() to determine the actual size
667 length = "%s(xcb_tmp, %s&%s)" % (field.type.c_unserialize_name,
668 c_field_names, c_switch_variable) #switch_field_name)
670 # _c_serialize_helper_switch_field()
672 def _c_serialize_helper_list_field(context, self, field,
673 code_lines, temp_vars,
676 helper function for (un)serialize to cope with lists of variable length
678 expr = field.type.expr
679 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
680 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
681 param_names = [p[2] for p in params]
683 # look if the list's lenfield is a struct member or a function argument
684 # special case: if the list has a length field, its name will be returned
685 # unchanged by calling c_accessor_get_length(expr)
686 if expr.lenfield_name == _c_accessor_get_length(expr):
687 if expr.lenfield_name in param_names:
688 # the length field appears as separate argument in unserialize,
689 # so no need for a prefix
691 sep = '.' if (self.is_bitcase and self.has_name) else '->'
693 # special case: unserializing of structs where variable and
694 # fixed size fields are intermixed
695 if self.var_followed_by_fixed_fields and 'unserialize' == context:
696 if lenfield_prefix == '_aux':
697 lenfield_prefix = 'xcb_out'
700 list_length = _c_accessor_get_expr(expr, lenfield_prefix, sep)
702 # default: list with fixed size elements
703 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
704 # list with variable-sized elements
705 if not field.type.member.fixed_size():
707 if context in ('unserialize', 'sizeof'):
708 int_i = ' unsigned int i;'
709 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
710 if int_i not in temp_vars:
711 temp_vars.append(int_i)
712 if xcb_tmp_len not in temp_vars:
713 temp_vars.append(xcb_tmp_len)
714 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
715 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
716 (space, field.type.c_sizeof_name))
717 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
718 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
719 code_lines.append("%s }" % space)
720 elif 'serialize' == context:
721 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
722 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
723 code_lines.append('%s for(i=0; i<%s; i++) { '
724 % (space, _c_accessor_get_expr(expr, lenfield_prefix, sep)))
725 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_sizeof_name))
726 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
727 code_lines.append('%s }' % space)
728 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
731 # _c_serialize_helper_list_field()
733 def _c_serialize_helper_fields_fixed_size(context, self, field,
734 code_lines, temp_vars,
736 if not self.is_bitcase:
737 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
739 scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
740 typename = reduce(lambda x,y: "%s.%s" % (x, y), scoped_name)
741 code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
742 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
744 length = "sizeof(%s)" % field.c_field_type
746 if context in ('unserialize', 'sizeof'):
747 value = ' %s%s = *(%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
748 if field.type.is_pad and field.type.nmemb > 1:
750 for i in range(field.type.nmemb):
751 code_lines.append('%s %s%s[%d] = *(%s *)xcb_tmp;' %
752 (space, prefix_str, field.c_field_name, i, field.c_field_type))
753 length += " * %d" % field.type.nmemb
755 if field.type.is_list:
756 raise Exception('list with fixed number of elemens unhandled in _unserialize()')
757 elif 'serialize' == context:
758 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
760 if field.type.is_expr:
761 # need to register a temporary variable for the expression
762 if field.type.c_type is None:
763 raise Exception("type for field '%s' (expression '%s') unkown" %
764 (field.field_name, _c_accessor_get_expr(field.type.expr)))
765 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, field.field_name,
766 _c_accessor_get_expr(field.type.expr, prefix)))
767 value += "&xcb_expr_%s;" % field.field_name
769 elif field.type.is_pad:
770 if field.type.nmemb == 1:
773 # FIXME - possible segmentation fault!!
774 value = ' memset(xcb_parts[xcb_parts_idx].iov_base, 0, %d);' % field.type.nmemb
775 length += "*%d" % field.type.nmemb
778 # non-list type with fixed size
779 if field.type.nmemb == 1:
780 value += "&%s%s;" % (prefix_str, field.c_field_name)
781 # list with nmemb (fixed size) elements
783 value += '%s%s;' % (prefix_str, field.c_field_name)
784 length = '%d' % field.type.nmemb
786 return (value, length)
787 # _c_serialize_helper_fields_fixed_size()
789 def _c_serialize_helper_fields_variable_size(context, self, field,
790 code_lines, temp_vars,
792 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
794 if context in ('unserialize', 'sizeof'):
796 if self.var_followed_by_fixed_fields and 'unserialize' == context:
797 value = ' %s = xcb_tmp;' % field.c_field_name
798 temp_vars.append(' %s *%s;' % (field.type.c_type, field.c_field_name))
799 elif 'serialize' == context:
800 address_of = '&' if (self.is_bitcase and self.has_name) else ''
801 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s%s%s;' % (address_of, prefix_str, field.c_field_name)
804 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
805 code_lines.append('%s /* %s */' % (space, field.c_field_name))
807 if field.type.is_list:
808 length = _c_serialize_helper_list_field(context, self, field,
809 code_lines, temp_vars,
811 elif field.type.is_switch:
812 prev = filter(lambda x: x.find('xcb_switch_field'), temp_vars)
813 var_name = 'xcb_switch_field%d' % len(prev)
814 temp_vars.append(' %s %s;' % (field.type.c_type, var_name))
815 length = _c_serialize_helper_switch_field(context, self, field, var_name, prefix)
817 length = "%s(xcb_tmp)" % (field.type.c_sizeof_name)
819 return (value, length)
820 # _c_serialize_helper_fields_variable_size
822 def _c_serialize_helper_fields(context, self,
823 code_lines, temp_vars,
824 space, prefix, is_bitcase):
827 prev_field_was_variable = False
829 for field in self.fields:
830 if not ((field.wire and not field.auto) or field.visible):
833 # switch/bitcase: fixed size fields must be considered explicitly
834 if field.type.fixed_size():
835 if self.is_bitcase or self.var_followed_by_fixed_fields:
836 if prev_field_was_variable and need_padding:
838 _c_serialize_helper_insert_padding(context, code_lines, space)
839 prev_field_was_variable = False
840 fixed_prefix = prefix
841 if self.var_followed_by_fixed_fields and len(prefix)==0:
842 if 'unserialize' == context:
843 fixed_prefix = [('xcb_out', '.', self)]
845 fixed_prefix = [('_aux', '->', self)]
846 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
847 code_lines, temp_vars,
852 # fields with variable size
854 # switch/bitcase: always calculate padding before and after variable sized fields
855 if need_padding or is_bitcase:
856 _c_serialize_helper_insert_padding(context, code_lines, space)
858 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
859 code_lines, temp_vars,
862 prev_field_was_variable = True
864 # save (un)serialization C code
866 code_lines.append('%s%s' % (space, value))
867 if field.type.fixed_size() and is_bitcase:
868 code_lines.append('%s xcb_block_len += %s;' % (space, length))
869 if context in ('unserialize', 'sizeof'):
870 code_lines.append('%s xcb_tmp += %s;' % (space, length))
874 code_lines.append('%s xcb_block_len = %s;' % (space, length))
875 if (not field.type.fixed_size() and
876 self.var_followed_by_fixed_fields and
877 'unserialize' == context):
878 temp_vars.append(' int %s_len;' % field.c_field_name)
879 code_lines.append(' %s_len = xcb_block_len;' % field.c_field_name)
880 if context in ('unserialize', 'sizeof'):
881 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
882 if 'serialize' == context:
884 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_block_len;' % space)
885 code_lines.append('%s xcb_parts_idx++;' % space)
890 # _c_serialize_helper_fields()
892 def _c_serialize_helper(context, complex_type,
893 code_lines, temp_vars,
894 space='', prefix=[]):
896 if hasattr(complex_type, 'type'):
897 self = complex_type.type
898 complex_name = complex_type.name
901 if self.var_followed_by_fixed_fields and 'unserialize' == context:
902 complex_name = 'xcb_out'
904 complex_name = '_aux'
906 # special case: switch is serialized by evaluating each bitcase separately
908 count += _c_serialize_helper_switch(context, self, complex_name,
909 code_lines, temp_vars,
912 # all other data types can be evaluated one field a time
914 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
915 if context in ('unserialize', 'sizeof') and not self.var_followed_by_fixed_fields:
916 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
917 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
918 _c_serialize_helper_insert_padding(context, code_lines, space)
920 count += _c_serialize_helper_fields(context, self,
921 code_lines, temp_vars,
922 space, prefix, False)
924 count += _c_serialize_helper_insert_padding(context, code_lines, space)
927 # _c_serialize_helper()
929 def _c_serialize(self):
934 # _serialize() returns the buffer size
937 variable_size_fields = 0
938 # maximum space required for type definition of function arguments
940 param_fields, wire_fields, params = get_serialize_params('serialize', self)
942 # determine N(variable_fields)
943 for field in param_fields:
944 # if self.is_switch, treat all fields as if they are variable sized
945 if not field.type.fixed_size() or self.is_switch:
946 variable_size_fields += 1
947 # determine maxtypelen
949 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
952 for idx, p in enumerate(params):
954 typespec, pointerspec, field_name = p
955 indent = ' '*(len(self.c_serialize_name)+2)
956 # p==0: function declaration
958 line = "%s (" % self.c_serialize_name
960 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
961 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
962 if idx < len(params)-1:
969 if not self.is_switch:
970 _c(' %s *xcb_out = *_buffer;', self.c_type)
971 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
972 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
974 _c(' char *xcb_out = *_buffer;')
975 _c(' unsigned int xcb_buffer_len = 0;')
976 if variable_size_fields > 0:
979 count = _c_serialize_helper('serialize', self,
980 code_lines, temp_vars)
981 # update variable size fields
982 variable_size_fields = count
983 temp_vars.append(' unsigned int xcb_pad = 0;')
984 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
985 temp_vars.append(' struct iovec xcb_parts[%d];' % count)
986 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
987 temp_vars.append(' unsigned int xcb_block_len = 0;')
988 temp_vars.append(' unsigned int i;')
989 temp_vars.append(' char *xcb_tmp;')
995 if variable_size_fields > 0:
1000 # variable sized fields have been collected, now
1001 # allocate memory and copy everything into a continuous memory area
1002 _c(' if (NULL == xcb_out) {')
1003 _c(' /* allocate memory */')
1004 _c(' *_buffer = malloc(xcb_buffer_len);')
1005 _c(' xcb_out = *_buffer;')
1009 # fill in struct members
1010 if not self.is_switch:
1011 if len(wire_fields)>0:
1012 _c(' *xcb_out = *_aux;')
1014 # copy variable size fields into the buffer
1015 if variable_size_fields > 0:
1017 if not self.is_switch:
1018 _c(' xcb_tmp = (char*)++xcb_out;')
1019 _c(' xcb_tmp += xcb_out_pad;')
1021 _c(' xcb_tmp = xcb_out;')
1023 # variable sized fields
1024 _c(' for(i=0; i<xcb_parts_idx; i++) {')
1025 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
1026 _c(' xcb_tmp += xcb_parts[i].iov_len;')
1029 _c(' return xcb_buffer_len;')
1033 def _c_unserialize(self):
1039 # _unserialize() returns the buffer size as well
1043 variable_size_fields = 0
1044 # maximum space required for type definition of function arguments
1046 param_fields, wire_fields, params = get_serialize_params('unserialize', self)
1048 # determine N(variable_fields)
1049 for field in param_fields:
1050 # if self.is_switch, treat all fields as if they are variable sized
1051 if not field.type.fixed_size() or self.is_switch:
1052 variable_size_fields += 1
1053 # determine maxtypelen
1055 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1058 for idx, p in enumerate(params):
1060 typespec, pointerspec, field_name = p
1061 indent = ' '*(len(self.c_unserialize_name)+2)
1062 # p==0: function declaration
1064 line = "%s (" % self.c_unserialize_name
1066 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1067 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
1068 if idx < len(params)-1:
1075 _c(' char *xcb_tmp = (char *)_buffer;')
1076 if not self.is_switch:
1077 if not self.var_followed_by_fixed_fields:
1078 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1080 _c(' %s xcb_out;', self.c_type)
1081 _c(' unsigned int xcb_buffer_len = 0;')
1082 _c(' unsigned int xcb_block_len = 0;')
1083 _c(' unsigned int xcb_pad = 0;')
1087 _c_serialize_helper('unserialize', self,
1088 code_lines, temp_vars)
1093 for l in code_lines:
1096 if not self.is_switch:
1097 if self.var_followed_by_fixed_fields:
1100 _c(' return xcb_buffer_len;')
1104 def _c_sizeof_helper(self):
1110 # _unserialize() returns the buffer size as well
1113 variable_size_fields = 0
1114 # maximum space required for type definition of function arguments
1116 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
1118 # determine N(variable_fields)
1119 for field in param_fields:
1120 # if self.is_switch, treat all fields as if they are variable sized
1121 if not field.type.fixed_size() or self.is_switch:
1122 variable_size_fields += 1
1123 # determine maxtypelen
1125 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1128 for idx, p in enumerate(params):
1130 typespec, pointerspec, field_name = p
1131 indent = ' '*(len(self.c_sizeof_name)+2)
1132 # p==0: function declaration
1134 line = "%s (" % self.c_sizeof_name
1136 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1137 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
1138 if idx < len(params)-1:
1145 # if self.is_switch: call serialize
1147 _c(' %s _aux;', self.c_type)
1148 param_names = [p[2] for p in params]
1149 _c(' return %s(%s, &_aux);', self.c_unserialize_name, reduce(lambda x,y: "%s, %s" % (x, y), param_names))
1150 # otherwise: evaluate parameters directly
1152 _c(' char *xcb_tmp = (char *)_buffer;')
1153 if not self.var_followed_by_fixed_fields:
1154 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1156 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1157 _c(' unsigned int xcb_buffer_len = 0;')
1158 _c(' unsigned int xcb_block_len = 0;')
1159 _c(' unsigned int xcb_pad = 0;')
1162 _c_serialize_helper('sizeof', self,
1163 code_lines, temp_vars)
1168 for l in code_lines:
1171 if not self.is_switch:
1172 if self.var_followed_by_fixed_fields:
1174 _c(' return xcb_buffer_len;')
1177 # _c_sizeof_helper()
1179 def _c_iterator_get_end(field, accum):
1181 Figures out what C code is needed to find the end of a variable-length structure field.
1182 For nested structures, recurses into its last variable-sized field.
1183 For lists, calls the end function
1185 if field.type.is_container:
1186 accum = field.c_accessor_name + '(' + accum + ')'
1187 # XXX there could be fixed-length fields at the end
1188 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1189 if field.type.is_list:
1190 # XXX we can always use the first way
1191 if field.type.member.is_simple:
1192 return field.c_end_name + '(' + accum + ')'
1194 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1196 def _c_iterator(self, name):
1198 Declares the iterator structure and next/end functions for a given type.
1203 _h(' * @brief %s', self.c_iterator_type)
1205 _h('typedef struct %s {', self.c_iterator_type)
1206 _h(' %s *data; /**< */', self.c_type)
1207 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1208 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1209 _h('} %s;', self.c_iterator_type)
1215 _h(' * Get the next element of the iterator')
1216 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1218 _h(' * Get the next element in the iterator. The member rem is')
1219 _h(' * decreased by one. The member data points to the next')
1220 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1224 _hc('/*****************************************************************************')
1226 _hc(' ** void %s', self.c_next_name)
1228 _hc(' ** @param %s *i', self.c_iterator_type)
1229 _hc(' ** @returns void')
1231 _hc(' *****************************************************************************/')
1234 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1235 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1238 if not self.fixed_size():
1239 _c(' %s *R = i->data;', self.c_type)
1241 # FIXME - how to determine the size of a variable size union??
1242 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1244 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1246 _c(' i->data = (%s *) child.data;', self.c_type)
1247 _c(' i->index = child.index;')
1251 _c(' i->index += sizeof(%s);', self.c_type)
1257 _h(' * Return the iterator pointing to the last element')
1258 _h(' * @param i An %s', self.c_iterator_type)
1259 _h(' * @return The iterator pointing to the last element')
1261 _h(' * Set the current element in the iterator to the last element.')
1262 _h(' * The member rem is set to 0. The member data points to the')
1263 _h(' * last element.')
1267 _hc('/*****************************************************************************')
1269 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1271 _hc(' ** @param %s i', self.c_iterator_type)
1272 _hc(' ** @returns xcb_generic_iterator_t')
1274 _hc(' *****************************************************************************/')
1276 _hc('xcb_generic_iterator_t')
1277 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1278 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1280 _c(' xcb_generic_iterator_t ret;')
1282 if self.fixed_size():
1283 _c(' ret.data = i.data + i.rem;')
1284 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1287 _c(' while(i.rem > 0)')
1288 _c(' %s(&i);', self.c_next_name)
1289 _c(' ret.data = i.data;')
1290 _c(' ret.rem = i.rem;')
1291 _c(' ret.index = i.index;')
1296 def _c_accessor_get_length(expr, prefix='', sep='->'):
1298 Figures out what C code is needed to get a length field.
1299 For fields that follow a variable-length field, use the accessor.
1300 Otherwise, just reference the structure field directly.
1302 prefarrow = '' if prefix == '' else prefix + sep
1304 if expr.lenfield != None and expr.lenfield.prev_varsized_field != None:
1305 # special case: variable and fixed size fields are intermixed
1306 # if the lenfield is among the fixed size fields, there is no need
1307 # to call a special accessor function!
1308 retval = expr.lenfield.c_accessor_name + '(' + prefix + ')'
1309 if prefix in ('', '_aux', 'xcb_out'):
1310 prefix_str = '' if prefix=='' else '%s' % (prefarrow)
1311 retval = '%s%s' % (prefix_str, expr.lenfield_name)
1313 elif expr.lenfield_name != None:
1314 if prefix.endswith(sep):
1315 return prefix + expr.lenfield_name
1317 return prefarrow + expr.lenfield_name
1319 return str(expr.nmemb)
1321 def _c_accessor_get_expr(expr, prefix='', sep='->'):
1323 Figures out what C code is needed to get the length of a list field.
1324 Recurses for math operations.
1325 Returns bitcount for value-mask fields.
1326 Otherwise, uses the value of the length field.
1328 lenexp = _c_accessor_get_length(expr, prefix, sep)
1331 return '(' + '~' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1332 elif expr.op == 'popcount':
1333 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1334 elif expr.op == 'enumref':
1335 enum_name = expr.lenfield_type.name
1336 constant_name = expr.lenfield_name
1337 c_name = _n(enum_name + (constant_name,)).upper()
1339 elif expr.op == 'sumof':
1340 # 1. locate the referenced list object
1341 list_obj = expr.lenfield_type
1343 for f in expr.lenfield_parent.fields:
1344 if f.field_name == expr.lenfield_name:
1348 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1349 if prefix != '' and not prefix.endswith(sep):
1351 list_name = "%s%s" % (prefix, field.c_field_name)
1352 c_length_func = "%s(%s%s)" % (field.c_length_name, prefix, field.c_field_name)
1354 c_length_func = _c_accessor_get_expr(field.type.expr, prefix='', sep='')
1355 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1356 elif expr.op != None:
1357 return '(' + _c_accessor_get_expr(expr.lhs, prefix, sep) + ' ' + expr.op + ' ' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1359 return 'xcb_popcount(' + lenexp + ')'
1363 def _c_accessors_field(self, field):
1365 Declares the accessor functions for a non-list field that follows a variable-length field.
1367 if field.type.is_simple:
1370 _hc('/*****************************************************************************')
1372 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1374 _hc(' ** @param const %s *R', self.c_type)
1375 _hc(' ** @returns %s', field.c_field_type)
1377 _hc(' *****************************************************************************/')
1379 _hc('%s', field.c_field_type)
1380 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1381 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1383 if field.prev_varsized_field is None:
1384 _c(' return (%s *) (R + 1);', field.c_field_type)
1386 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1387 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1388 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1393 _hc('/*****************************************************************************')
1395 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1397 _hc(' ** @param const %s *R', self.c_type)
1398 _hc(' ** @returns %s *', field.c_field_type)
1400 _hc(' *****************************************************************************/')
1402 _hc('%s *', field.c_field_type)
1403 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1404 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1406 if field.prev_varsized_field is None:
1407 _c(' return (%s *) (R + 1);', field.c_field_type)
1409 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1410 _c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1411 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1414 def _c_accessors_list(self, field):
1416 Declares the accessor functions for a list field.
1417 Declares a direct-accessor function only if the list members are fixed size.
1418 Declares length and get-iterator functions always.
1424 if list.member.fixed_size():
1427 _hc('/*****************************************************************************')
1429 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1431 _hc(' ** @param const %s *R', self.c_type)
1432 _hc(' ** @returns %s *', field.c_field_type)
1434 _hc(' *****************************************************************************/')
1436 _hc('%s *', field.c_field_type)
1437 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1438 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1441 if field.prev_varsized_field is None:
1442 _c(' return (%s *) (R + 1);', field.c_field_type)
1444 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1445 _c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);', field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1451 _hc('/*****************************************************************************')
1453 _hc(' ** int %s', field.c_length_name)
1455 _hc(' ** @param const %s *R', self.c_type)
1456 _hc(' ** @returns int')
1458 _hc(' *****************************************************************************/')
1461 _h('%s (const %s *R /**< */);', field.c_length_name, self.c_type)
1462 _c('%s (const %s *R /**< */)', field.c_length_name, self.c_type)
1464 _c(' return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1467 if field.type.member.is_simple:
1470 _hc('/*****************************************************************************')
1472 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1474 _hc(' ** @param const %s *R', self.c_type)
1475 _hc(' ** @returns xcb_generic_iterator_t')
1477 _hc(' *****************************************************************************/')
1479 _hc('xcb_generic_iterator_t')
1480 _h('%s (const %s *R /**< */);', field.c_end_name, self.c_type)
1481 _c('%s (const %s *R /**< */)', field.c_end_name, self.c_type)
1483 _c(' xcb_generic_iterator_t i;')
1485 if field.prev_varsized_field == None:
1486 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1488 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1489 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1492 _c(' i.index = (char *) i.data - (char *) R;')
1499 _hc('/*****************************************************************************')
1501 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1503 _hc(' ** @param const %s *R', self.c_type)
1504 _hc(' ** @returns %s', field.c_iterator_type)
1506 _hc(' *****************************************************************************/')
1508 _hc('%s', field.c_iterator_type)
1509 _h('%s (const %s *R /**< */);', field.c_iterator_name, self.c_type)
1510 _c('%s (const %s *R /**< */)', field.c_iterator_name, self.c_type)
1512 _c(' %s i;', field.c_iterator_type)
1514 if field.prev_varsized_field == None:
1515 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1517 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1518 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', field.c_field_type, field.c_field_type)
1520 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1521 _c(' i.index = (char *) i.data - (char *) R;')
1525 def _c_accessors(self, name, base):
1527 Declares the accessor functions for the fields of a structure.
1529 for field in self.fields:
1530 # no accessors for switch -
1531 # switch always needs to be unserialized explicitly
1534 if field.type.is_list and not field.type.fixed_size():
1535 _c_accessors_list(self, field)
1536 elif field.prev_varsized_field != None or not field.type.fixed_size():
1537 _c_accessors_field(self, field)
1539 def c_simple(self, name):
1541 Exported function that handles cardinal type declarations.
1542 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1544 _c_type_setup(self, name, ())
1546 if (self.name != name):
1551 _h('typedef %s %s;', _t(self.name), my_name)
1554 _c_iterator(self, name)
1556 def _c_complex(self):
1558 Helper function for handling all structure types.
1559 Called for all structs, requests, replies, events, errors.
1564 _h(' * @brief %s', self.c_type)
1566 _h('typedef %s %s {', self.c_container, self.c_type)
1572 for field in self.fields:
1573 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1574 varfield = field.c_field_name
1576 # if varfield != None and not field.type.is_pad and field.wire:
1577 # errmsg = '%s: warning: variable field %s followed by fixed field %s\n' % (self.c_type, varfield, field.c_field_name)
1578 # sys.stderr.write(errmsg)
1581 struct_fields.append(field)
1583 for field in struct_fields:
1584 length = len(field.c_field_type)
1585 # account for '*' pointer_spec
1586 if not field.type.fixed_size():
1588 maxtypelen = max(maxtypelen, length)
1590 def _c_complex_field(self, field, space=''):
1591 if (field.type.fixed_size() or
1592 # in case of switch with switch children, don't make the field a pointer
1593 # necessary for unserialize to work
1594 (self.is_switch and field.type.is_switch)):
1595 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1596 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1598 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1599 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1601 if not self.is_switch:
1602 for field in struct_fields:
1603 _c_complex_field(self, field)
1605 for b in self.bitcases:
1608 _h(' struct _%s {', b.c_field_name)
1610 for field in b.type.fields:
1611 _c_complex_field(self, field, space)
1613 _h(' } %s;', b.c_field_name)
1615 _h('} %s;', self.c_type)
1617 def c_struct(self, name):
1619 Exported function that handles structure declarations.
1621 _c_type_setup(self, name, ())
1623 _c_accessors(self, name, name)
1624 _c_iterator(self, name)
1626 def c_union(self, name):
1628 Exported function that handles union declarations.
1630 _c_type_setup(self, name, ())
1632 _c_iterator(self, name)
1634 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1636 Declares a request function.
1639 # Four stunningly confusing possibilities here:
1642 # ------------------------------
1644 # 0 flag CHECKED flag Normal Mode
1645 # void_cookie req_cookie
1646 # ------------------------------
1647 # "req_checked" "req_unchecked"
1648 # CHECKED flag 0 flag Abnormal Mode
1649 # void_cookie req_cookie
1650 # ------------------------------
1653 # Whether we are _checked or _unchecked
1654 checked = void and not regular
1655 unchecked = not void and not regular
1657 # What kind of cookie we return
1658 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1660 # What flag is passed to xcb_request
1661 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1663 # Global extension id variable or NULL for xproto
1664 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1666 # What our function name is
1667 func_name = self.c_request_name if not aux else self.c_aux_name
1669 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1671 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1675 maxtypelen = len('xcb_connection_t')
1677 # special case: list with variable size elements
1678 list_with_var_size_elems = False
1680 for field in self.fields:
1682 # The field should appear as a call parameter
1683 param_fields.append(field)
1684 if field.wire and not field.auto:
1685 # We need to set the field up in the structure
1686 wire_fields.append(field)
1687 if field.type.need_serialize or field.type.need_sizeof:
1688 serial_fields.append(field)
1690 for field in param_fields:
1691 c_field_const_type = field.c_field_const_type
1692 if field.type.need_serialize and not aux:
1693 c_field_const_type = "const void"
1694 if len(c_field_const_type) > maxtypelen:
1695 maxtypelen = len(c_field_const_type)
1696 if field.type.is_list and not field.type.member.fixed_size():
1697 list_with_var_size_elems = True
1703 _h(' * Delivers a request to the X server')
1704 _h(' * @param c The connection')
1705 _h(' * @return A cookie')
1707 _h(' * Delivers a request to the X server.')
1710 _h(' * This form can be used only if the request will not cause')
1711 _h(' * a reply to be generated. Any returned error will be')
1712 _h(' * saved for handling by xcb_request_check().')
1714 _h(' * This form can be used only if the request will cause')
1715 _h(' * a reply to be generated. Any returned error will be')
1716 _h(' * placed in the event queue.')
1720 _hc('/*****************************************************************************')
1722 _hc(' ** %s %s', cookie_type, func_name)
1725 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1726 _hc(' ** @param xcb_connection_t%s *c', spacing)
1728 for field in param_fields:
1729 c_field_const_type = field.c_field_const_type
1730 if field.type.need_serialize and not aux:
1731 c_field_const_type = "const void"
1732 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1733 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1735 _hc(' ** @returns %s', cookie_type)
1737 _hc(' *****************************************************************************/')
1739 _hc('%s', cookie_type)
1741 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1742 comma = ',' if len(param_fields) else ');'
1743 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1744 comma = ',' if len(param_fields) else ')'
1745 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1747 func_spacing = ' ' * (len(func_name) + 2)
1748 count = len(param_fields)
1749 for field in param_fields:
1751 c_field_const_type = field.c_field_const_type
1752 c_pointer = field.c_pointer
1753 if field.type.need_serialize and not aux:
1754 c_field_const_type = "const void"
1756 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1757 comma = ',' if count else ');'
1758 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1759 spacing, c_pointer, field.c_field_name, comma)
1760 comma = ',' if count else ')'
1761 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1762 spacing, c_pointer, field.c_field_name, comma)
1765 if not self.var_followed_by_fixed_fields:
1766 for field in param_fields:
1767 if not field.type.fixed_size():
1769 if field.type.need_serialize:
1770 # _serialize() keeps track of padding automatically
1772 dimension = count + 2
1773 if self.var_followed_by_fixed_fields:
1774 # there will be only one call to _serialize() and no need for additional padding
1778 _c(' static const xcb_protocol_request_t xcb_req = {')
1779 _c(' /* count */ %d,', count)
1780 _c(' /* ext */ %s,', func_ext_global)
1781 _c(' /* opcode */ %s,', self.c_request_name.upper())
1782 _c(' /* isvoid */ %d', 1 if void else 0)
1786 _c(' struct iovec xcb_parts[%d];', dimension)
1787 _c(' %s xcb_ret;', func_cookie)
1788 _c(' %s xcb_out;', self.c_type)
1789 if self.var_followed_by_fixed_fields:
1790 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
1793 for idx, f in enumerate(serial_fields):
1795 _c(' void *xcb_aux%d = 0;' % (idx))
1796 if list_with_var_size_elems:
1797 _c(' unsigned int i;')
1798 _c(' unsigned int xcb_tmp_len;')
1799 _c(' char *xcb_tmp;')
1801 # _c(' printf("in function %s\\n");' % func_name)
1804 for field in wire_fields:
1805 if field.type.fixed_size():
1806 if field.type.is_expr:
1807 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr))
1808 elif field.type.is_pad:
1809 if field.type.nmemb == 1:
1810 _c(' xcb_out.%s = 0;', field.c_field_name)
1812 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
1814 if field.type.nmemb == 1:
1815 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
1817 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
1819 def get_serialize_args(type_obj, c_field_name, aux_var, context='serialize'):
1820 serialize_args = get_serialize_params(context, type_obj,
1823 return reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
1825 # calls in order to free dyn. all. memory
1828 if not self.var_followed_by_fixed_fields:
1830 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
1831 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
1832 _c(' xcb_parts[3].iov_base = 0;')
1833 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
1837 for field in param_fields:
1838 if not field.type.fixed_size():
1839 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
1840 # default: simple cast to char *
1841 if not field.type.need_serialize and not field.type.need_sizeof:
1842 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1843 if field.type.is_list:
1844 if field.type.member.fixed_size():
1845 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
1846 _c_accessor_get_expr(field.type.expr), field.type.member.c_wiretype)
1848 expr = field.type.expr
1849 prefix_str, lenfield_prefix = _c_serialize_helper_prefix([('xcb_out', '.', self)],
1851 param_fields, wire_fields, params = get_serialize_params('sizeof', self)
1852 param_names = [p[2] for p in params]
1855 # look if the list's lenfield is a struct member or a function argument
1856 # special case: if the list has a length field, its name will be returned
1857 # unchanged by calling c_accessor_get_length(expr)
1858 if expr.lenfield_name == _c_accessor_get_length(expr):
1859 if expr.lenfield_name in param_names:
1860 # the length field appears as separate argument,
1861 # so no need for a prefix
1862 lenfield_prefix = ''
1864 list_length = _c_accessor_get_expr(expr, lenfield_prefix, sep)
1867 _c(" xcb_parts[%d].iov_len = 0;" % count)
1868 _c(" xcb_tmp = (char *)%s;", field.c_field_name)
1869 _c(" for(i=0; i<%s; i++) {" % list_length)
1870 _c(" xcb_tmp_len = %s(xcb_tmp);" %
1871 (field.type.c_sizeof_name))
1872 _c(" xcb_parts[%d].iov_len += xcb_tmp_len;" % count)
1873 _c(" xcb_tmp += xcb_tmp_len;")
1876 # not supposed to happen
1877 raise Exception("unhandled variable size field %s" % field.c_field_name)
1880 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1881 idx = serial_fields.index(field)
1882 aux_var = '&xcb_aux%d' % idx
1883 context = 'serialize' if aux else 'sizeof'
1884 _c(' xcb_parts[%d].iov_len = ', count)
1886 serialize_args = get_serialize_args(field.type, aux_var, field.c_field_name, context)
1887 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
1888 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
1889 free_calls.append(' free(xcb_aux%d);' % idx)
1891 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, context)
1892 func_name = field.type.c_sizeof_name
1893 _c(' %s (%s);', func_name, serialize_args)
1896 if not (field.type.need_serialize or field.type.need_sizeof):
1897 # the _serialize() function keeps track of padding automatically
1898 _c(' xcb_parts[%d].iov_base = 0;', count)
1899 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
1902 # elif self.var_followed_by_fixed_fields:
1905 buffer_var = 'xcb_parts[%d].iov_base' % count
1906 serialize_args = get_serialize_args(self, '&%s' % buffer_var, '&xcb_out', 'serialize')
1907 _c(' %s = (char *) 0;', buffer_var)
1908 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
1909 free_calls.append(' free(xcb_parts[%d].iov_base);' % count)
1910 # no padding necessary - _serialize() keeps track of padding automatically
1913 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
1915 # free dyn. all. data, if any
1916 for f in free_calls:
1918 _c(' return xcb_ret;')
1921 def _c_reply(self, name):
1923 Declares the function that returns the reply structure.
1925 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
1926 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
1927 spacing3 = ' ' * (len(self.c_reply_name) + 2)
1931 _h(' * Return the reply')
1932 _h(' * @param c The connection')
1933 _h(' * @param cookie The cookie')
1934 _h(' * @param e The xcb_generic_error_t supplied')
1936 _h(' * Returns the reply of the request asked by')
1938 _h(' * The parameter @p e supplied to this function must be NULL if')
1939 _h(' * %s(). is used.', self.c_unchecked_name)
1940 _h(' * Otherwise, it stores the error if any.')
1942 _h(' * The returned value must be freed by the caller using free().')
1946 _hc('/*****************************************************************************')
1948 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
1950 _hc(' ** @param xcb_connection_t%s *c', spacing1)
1951 _hc(' ** @param %s cookie', self.c_cookie_type)
1952 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
1953 _hc(' ** @returns %s *', self.c_reply_type)
1955 _hc(' *****************************************************************************/')
1957 _hc('%s *', self.c_reply_type)
1958 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
1959 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
1960 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
1961 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
1963 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
1966 def _c_opcode(name, opcode):
1968 Declares the opcode define for requests, events, and errors.
1972 _h('/** Opcode for %s. */', _n(name))
1973 _h('#define %s %s', _n(name).upper(), opcode)
1975 def _c_cookie(self, name):
1977 Declares the cookie type for a non-void request.
1982 _h(' * @brief %s', self.c_cookie_type)
1984 _h('typedef struct %s {', self.c_cookie_type)
1985 _h(' unsigned int sequence; /**< */')
1986 _h('} %s;', self.c_cookie_type)
1988 def c_request(self, name):
1990 Exported function that handles request declarations.
1992 _c_type_setup(self, name, ('request',))
1995 # Cookie type declaration
1996 _c_cookie(self, name)
1999 _c_opcode(name, self.opcode)
2001 # Request structure declaration
2005 _c_type_setup(self.reply, name, ('reply',))
2006 # Reply structure definition
2007 _c_complex(self.reply)
2008 # Request prototypes
2009 _c_request_helper(self, name, self.c_cookie_type, False, True)
2010 _c_request_helper(self, name, self.c_cookie_type, False, False)
2012 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
2013 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
2015 _c_accessors(self.reply, name + ('reply',), name)
2016 _c_reply(self, name)
2018 # Request prototypes
2019 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
2020 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
2022 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
2023 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
2026 def c_event(self, name):
2028 Exported function that handles event declarations.
2030 _c_type_setup(self, name, ('event',))
2033 _c_opcode(name, self.opcodes[name])
2035 if self.name == name:
2036 # Structure definition
2041 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
2043 def c_error(self, name):
2045 Exported function that handles error declarations.
2047 _c_type_setup(self, name, ('error',))
2050 _c_opcode(name, self.opcodes[name])
2052 if self.name == name:
2053 # Structure definition
2058 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
2061 # Main routine starts here
2063 # Must create an "output" dictionary before any xcbgen imports.
2064 output = {'open' : c_open,
2066 'simple' : c_simple,
2068 'struct' : c_struct,
2070 'request' : c_request,
2075 # Boilerplate below this point
2077 # Check for the argument that specifies path to the xcbgen python package.
2079 opts, args = getopt.getopt(sys.argv[1:], 'p:')
2080 except getopt.GetoptError, err:
2082 print 'Usage: c_client.py [-p path] file.xml'
2085 for (opt, arg) in opts:
2087 sys.path.append(arg)
2089 # Import the module class
2091 from xcbgen.state import Module
2094 print 'Failed to load the xcbgen Python package!'
2095 print 'Make sure that xcb/proto installed it on your Python path.'
2096 print 'If not, you will need to create a .pth file or define $PYTHONPATH'
2097 print 'to extend the path.'
2098 print 'Refer to the README file in xcb/proto for more info.'
2102 # Parse the xml header
2103 module = Module(args[0], output)
2105 # Build type-registry and resolve type dependencies