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 = []
34 Writes the given line to the header file.
36 _hlines[_hlevel].append(fmt % args)
40 Writes the given line to the source file.
42 _clines[_clevel].append(fmt % args)
46 Writes the given line to both the header and source files.
51 # XXX See if this level thing is really necessary.
54 Changes the array that header lines are written to.
55 Supports writing different sections of the header file.
58 while len(_hlines) <= idx:
64 Changes the array that source lines are written to.
65 Supports writing to different sections of the source file.
68 while len(_clines) <= idx:
74 Does C-name conversion on a single string fragment.
75 Uses a regexp with some hard-coded special cases.
77 if str in _cname_special_cases:
78 return _cname_special_cases[str]
80 split = _cname_re.finditer(str)
81 name_parts = [match.group(0) for match in split]
82 return '_'.join(name_parts)
86 Checks for certain C++ reserved words and fixes them.
88 if str in _cplusplus_annoyances:
89 return _cplusplus_annoyances[str]
90 elif str in _c_keywords:
91 return _c_keywords[str]
97 Does C-name conversion on an extension name.
98 Has some additional special cases on top of _n_item.
100 if str in _extension_special_cases:
101 return _n_item(str).lower()
107 Does C-name conversion on a tuple of strings.
108 Different behavior depending on length of tuple, extension/not extension, etc.
109 Basically C-name converts the individual pieces, then joins with underscores.
114 parts = [list[0], _n_item(list[1])]
116 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
118 parts = [list[0]] + [_n_item(i) for i in list[1:]]
119 return '_'.join(parts).lower()
123 Does C-name conversion on a tuple of strings representing a type.
124 Same as _n but adds a "_t" on the end.
129 parts = [list[0], _n_item(list[1]), 't']
131 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
133 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
134 return '_'.join(parts).lower()
139 Exported function that handles module open.
140 Opens the files and writes out the auto-generated comment, header file includes, etc.
144 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
146 # Build the type-name collision avoidance table used by c_enum
147 build_collision_table()
153 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
154 _hc(' * Edit at your peril.')
159 _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
160 _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
164 _h('#ifndef __%s_H', _ns.header.upper())
165 _h('#define __%s_H', _ns.header.upper())
167 _h('#include "xcb.h"')
169 _c('#include <stdlib.h>')
170 _c('#include <string.h>')
171 _c('#include <assert.h>')
172 _c('#include "xcbext.h"')
173 _c('#include "%s.h"', _ns.header)
176 for (n, h) in self.imports:
177 _hc('#include "%s.h"', h)
180 _h('#ifdef __cplusplus')
186 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
187 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
189 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
192 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
196 Exported function that handles module close.
197 Writes out all the stored content lines, then closes the files.
204 _h('#ifdef __cplusplus')
216 hfile = open('%s.h' % _ns.header, 'w')
224 cfile = open('%s.c' % _ns.header, 'w')
231 def build_collision_table():
235 for v in module.types.values():
237 namecount[name] = (namecount.get(name) or 0) + 1
239 def c_enum(self, name):
241 Exported function that handles enum declarations.
245 if namecount[tname] > 1:
246 tname = _t(name + ('enum',))
250 _h('typedef enum %s {', tname)
252 count = len(self.values)
254 for (enam, eval) in self.values:
256 equals = ' = ' if eval != '' else ''
257 comma = ',' if count > 0 else ''
258 _h(' %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
262 def _c_type_setup(self, name, postfix):
264 Sets up all the C-related state by adding additional data fields to
265 all Field and Type objects. Here is where we figure out most of our
266 variable and function names.
268 Recurses into child fields and list member types.
270 # Do all the various names in advance
271 self.c_type = _t(name + postfix)
272 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
274 self.c_iterator_type = _t(name + ('iterator',))
275 self.c_next_name = _n(name + ('next',))
276 self.c_end_name = _n(name + ('end',))
278 self.c_request_name = _n(name)
279 self.c_checked_name = _n(name + ('checked',))
280 self.c_unchecked_name = _n(name + ('unchecked',))
281 self.c_reply_name = _n(name + ('reply',))
282 self.c_reply_type = _t(name + ('reply',))
283 self.c_cookie_type = _t(name + ('cookie',))
285 self.c_aux_name = _n(name + ('aux',))
286 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
287 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
288 self.c_serialize_name = _n(name + ('serialize',))
289 self.c_unserialize_name = _n(name + ('unserialize',))
290 # if hasattr(self, 'reply'):
291 # if self.reply is not None:
292 # self.c_serialize_name = _n(name + ('reply', 'serialize'))
293 # self.c_unserialize_name = _n(name + ('reply', 'unserialize'))
294 # indicates rare structs where variable size fields are followed fixed size fields
295 self.var_followed_by_fixed_fields = False
297 # whether a request or reply has a switch field
298 self.need_aux = False
299 self.need_serialize = False
301 self.need_serialize = True
302 self.c_container = 'struct'
303 for bitcase in self.bitcases:
304 bitcase.c_field_name = _cpp(bitcase.field_name)
305 _c_type_setup(bitcase.type, bitcase.field_type, ())
307 elif self.is_container:
309 self.c_container = 'union' if self.is_union else 'struct'
310 prev_varsized_field = None
311 prev_varsized_offset = 0
312 first_field_after_varsized = None
314 for field in self.fields:
315 _c_type_setup(field.type, field.field_type, ())
316 if field.type.is_list:
317 _c_type_setup(field.type.member, field.field_type, ())
318 # FIXME - structures with variable sized members, sort out when serialize() is needed
319 if (field.type.nmemb is None): # and not field.type.member.fixed_size():
320 self.need_serialize = True
322 field.c_field_type = _t(field.field_type)
323 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
324 field.c_field_name = _cpp(field.field_name)
325 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
326 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
327 if field.type.is_switch:
328 field.c_pointer = '*'
329 field.c_field_const_type = 'const ' + field.c_field_type
331 elif not field.type.fixed_size() and not field.type.is_bitcase:
332 self.need_serialize = True
334 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
335 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
336 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
337 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
339 # special case - c_field_name ends with _length as well
340 # if field.c_accessor_name.endswith('_length'):
341 # raise Exception(field.c_field_name)
342 #if field.c_field_name.endswith('length'):
343 # c_field_name = field.c_field_name.rsplit('length', 1)
344 # field.c_field_name = c_field_name[0] + "_length"
345 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
347 field.prev_varsized_field = prev_varsized_field
348 field.prev_varsized_offset = prev_varsized_offset
350 if prev_varsized_offset == 0:
351 first_field_after_varsized = field
352 field.first_field_after_varsized = first_field_after_varsized
354 if field.type.fixed_size():
355 prev_varsized_offset += field.type.size
356 if prev_varsized_field is not None and not field.type.is_pad and field.wire:
357 if not self.is_union:
358 self.need_serialize = True
359 self.var_followed_by_fixed_fields = True
361 self.last_varsized_field = field
362 prev_varsized_field = field
363 prev_varsized_offset = 0
365 # very special case - if self.var_followed_by_fixed_fields==True,
366 # we have to generate accessor functions also for fixed size fields
367 # now there might a naming conflict if the length field ends with _length
368 if self.var_followed_by_fixed_fields:
369 if field.type.is_list:
370 if field.type.expr.lenfield_name is not None:
371 full_lenfield_name = _n(name + (field.type.expr.lenfield_name,))
372 if full_lenfield_name == field.c_length_name:
373 field.c_length_name += '_'
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 # FIXME: declare switch (un)packing functions
383 _c_accessors(self, name, name)
385 # FIXME - in case of request/reply, serialize() is not always needed
386 if self.need_serialize and not self.is_bitcase:
387 if self.c_serialize_name not in finished_serializers:
388 finished_serializers.append(self.c_serialize_name)
393 def get_request_fields(self):
397 for field in self.fields:
399 # the field should appear as a parameter in the function call
400 param_fields.append(field)
401 if field.wire and not field.auto:
402 if field.type.fixed_size() and not self.is_switch:
403 # field in the xcb_out structure
404 wire_fields.append(field)
405 # fields like 'pad0' are skipped!
407 return (param_fields, wire_fields)
408 # get_request_fields()
410 def get_expr_fields(self):
411 # get the fields referenced by switch or list expression
412 def get_expr_field_names(expr):
414 if expr.lenfield_name is not None:
415 return [expr.lenfield_name]
417 # constant value expr
421 return get_expr_field_names(expr.rhs)
422 elif expr.op == 'popcount':
423 return get_expr_field_names(expr.rhs)
424 elif expr.op == 'sumof':
425 return [expr.lenfield_name]
426 elif expr.op == 'enumref':
429 return get_expr_field_names(expr.lhs) + get_expr_field_names(expr.rhs)
430 # get_expr_field_names()
432 # resolve the field names with the parent structure(s)
433 unresolved_fields = get_expr_field_names(self.expr)
434 if unresolved_fields is None:
436 expr_fields = dict.fromkeys(unresolved_fields)
437 for p in reversed(self.parent):
438 parent_fields = dict((f.field_name, f) for f in p.fields)
439 for f in parent_fields.keys():
440 if f in unresolved_fields:
441 expr_fields[f] = parent_fields[f]
442 unresolved_fields.remove(f)
443 if len(unresolved_fields) == 0:
446 if None in expr_fields.values():
447 raise Exception("could not resolve all fields for %s" % self.name)
449 params = expr_fields.values()
453 def resolve_fields(anchestor, complex_obj=None):
454 """find fields referenced by anchestor or descendents with external scope"""
458 if complex_obj is None:
459 complex_obj = anchestor
460 for field in complex_obj.fields:
461 all_fields.append(field)
462 if field.type.is_switch or field.type.is_list:
463 expr_fields += get_expr_fields(field.type)
464 if field.type.is_container:
465 expr_fields += resolve_fields(anchestor, field.type)
466 # try to resolve expr fields
467 for e in expr_fields:
468 if e not in all_fields:
472 def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'):
473 def add_param(params, param):
474 if param not in params:
477 param_fields, wire_fields = get_request_fields(self)
479 param_fields = get_expr_fields(self)
481 # _serialize function parameters
482 # cannot use set() for params, as series is important
484 if 'serialize' == context:
485 params.append(('void', '**', buffer_var))
486 elif 'unserialize' == context:
487 params.append(('const void', '*', buffer_var))
489 # look for special cases
490 unresolved_fields = resolve_fields(self)
491 for f in unresolved_fields:
492 add_param(params, (f.c_field_type, '', f.c_field_name))
494 # make sure all required length fields are present
495 for p in param_fields:
496 if p.visible and not p.wire and not p.auto:
497 typespec = p.c_field_type
499 add_param(params, (typespec, pointerspec, p.c_field_name))
501 # parameter fields if any
503 for p in get_expr_fields(self):
504 typespec = p.c_field_const_type
505 pointerspec = p.c_pointer
506 add_param(params, (typespec, pointerspec, p.c_field_name))
508 # aux argument - structure to be serialized
509 if 'serialize' == context:
510 add_param(params, ('const %s' % self.c_type, '*', aux_var))
511 elif 'unserialize' == context and self.is_switch:
512 add_param(params, ('%s' % self.c_type, '*', aux_var))
513 if not self.is_switch and 'serialize' == context:
514 for p in param_fields:
515 if not p.type.fixed_size():
516 add_param(params, (p.c_field_const_type, '*', p.c_field_name))
517 return (param_fields, wire_fields, params)
518 # get_serialize_params()
520 def _c_serialize_helper_prefix(prefix):
521 # prefix is a list of (field_name, anchestor object) tuples
522 # concatenate field names
524 for name, sep, obj in prefix:
527 sep = '.' if (obj.is_bitcase and obj.has_name) else '->'
529 lenfield_prefix = '' if prefix_str.find('_aux')==0 else "_aux"
531 if lenfield_prefix != '':
532 lenfield_prefix += '->'
533 lenfield_prefix += prefix_str
534 return (prefix_str, lenfield_prefix)
535 # _c_serialize_helper_prefix
537 def _c_field_mapping(context, complex_type, prefix):
538 def get_prefix(field, prefix):
539 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
541 if context in ('serialize', 'unserialize'):
542 if field.type.fixed_size() or complex_type.is_switch:
543 prefix_str = '_aux->'
545 raise Exception("unknown context '%s' in c_field_mapping" % context)
548 def get_field_name(fields, complex_type, prefix):
549 for f in complex_type.fields:
550 prefix_str = get_prefix(f, prefix)
552 fname = "%s%s" % (prefix_str, f.c_field_name)
553 if fields.has_key(f.field_name):
556 raise Exception("field name %s has been registered before" % f.field_name)
557 fields[f.field_name] = (fname, f)
558 if f.type.is_container:
559 get_field_name(fields, f.type, prefix+[(f.c_field_name, '', f.type)])
562 # dict(field_name : (c_field_name, field))
564 get_field_name(fields, complex_type, prefix)
566 # switch: get the fields referenced by the switch expr as well
567 # these may not belong to any structure
568 if complex_type.is_switch:
570 # FIXME: fields += get_serialize_params(context, complex_type)
575 def _c_serialize_helper_insert_padding(context, code_lines, space):
576 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
577 code_lines.append('%s /* padding */' % space)
578 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
579 code_lines.append('%s if (0 != xcb_pad) {' % space)
581 if 'serialize' == context:
582 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
583 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
584 code_lines.append('%s xcb_parts_idx++;' % space)
585 elif 'unserialize' == context:
586 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
588 code_lines.append('%s xcb_buffer_len += xcb_pad;' % space)
589 code_lines.append('%s xcb_pad = 0;' % space)
590 code_lines.append('%s }' % space)
591 code_lines.append('%s xcb_block_len = 0;' % space)
594 # _c_serialize_helper_insert_padding()
596 def _c_serialize_helper_switch(context, self, complex_name,
597 code_lines, temp_vars,
600 switch_prefix = prefix + [(complex_name, '->', self)]
601 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(switch_prefix)
602 switch_expr = _c_accessor_get_expr(self.expr)
604 for b in self.bitcases:
605 bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix_str)
606 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
607 b_prefix = switch_prefix
609 b_prefix = switch_prefix + [(b.c_field_name, '.', b.type)]
610 _c_serialize_helper_fields(context, b.type,
611 code_lines, temp_vars,
615 code_lines.append(' }')
617 if 'serialize' == context:
618 count = _c_serialize_helper_insert_padding(context, code_lines, space)
619 if 'unserialize' == context:
621 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
622 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
625 # _c_serialize_helper_switch
627 def _c_serialize_helper_switch_field(context, self, field, c_switch_variable, prefix):
628 # switch is handled by this function as a special case
629 param_fields, wire_fields, params = get_serialize_params(context, self)
630 args = get_expr_fields(field.type)
631 field_mapping = _c_field_mapping(context, self, prefix)
633 # determine which params to pass to _unserialize() and their prefixes
634 switch_len_fields = resolve_fields(self, field.type)
635 bitcase_unresolved = resolve_fields(self, self)
636 if len(bitcase_unresolved) != 0:
637 raise Exception('unresolved fields within bitcase is not supported at this point')
639 for a in switch_len_fields:
640 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
642 c_field_names += "%s, " % field_mapping[a.c_field_name][0]
643 # switch_field_name = field_mapping[field.field_name][0]
644 # call _unserialize() to determine the actual size
645 length = "%s(xcb_tmp, %s&%s)" % (field.type.c_unserialize_name,
646 c_field_names, c_switch_variable) #switch_field_name)
648 # _c_serialize_helper_switch_field()
650 def _c_serialize_helper_list_field(context, self, field,
651 code_lines, temp_vars,
654 helper function for (un)serialize to cope with lists of variable length
656 expr = field.type.expr
657 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
658 param_fields, wire_fields, params = get_serialize_params('unserialize', self)
659 param_names = [p[2] for p in params]
661 # look if the list's lenfield is a struct member or a function argument
662 # special case: if the list has a length field, its name will be returned
663 # unchanged by calling c_accessor_get_length(expr)
664 if expr.lenfield_name == _c_accessor_get_length(expr):
665 if expr.lenfield_name in param_names:
666 # the length field appears as separate argument in unserialize,
667 # so no need for a prefix
669 sep = '.' if (self.is_bitcase and self.has_name) else '->'
670 list_length = _c_accessor_get_expr(expr, lenfield_prefix, sep)
672 # default: list with fixed size elements
673 length = '%s * sizeof(%s)' % (list_length, field.type.member.c_wiretype)
674 # list with variable-sized elements
675 if field.type.size is None:
677 if 'unserialize' == context:
678 int_i = ' unsigned int i;'
679 xcb_tmp_len = ' unsigned int xcb_tmp_len;'
680 if int_i not in temp_vars:
681 temp_vars.append(int_i)
682 if xcb_tmp_len not in temp_vars:
683 temp_vars.append(xcb_tmp_len)
684 code_lines.append("%s for(i=0; i<%s; i++) {" % (space, list_length))
685 code_lines.append("%s xcb_tmp_len = %s(xcb_tmp);" %
686 (space, field.type.c_unserialize_name))
687 code_lines.append("%s xcb_block_len += xcb_tmp_len;" % space)
688 code_lines.append("%s xcb_tmp += xcb_tmp_len;" % space)
689 code_lines.append("%s }" % space)
690 elif 'serialize' == context:
691 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
692 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
693 code_lines.append('%s for(i=0; i<%s; i++) { '
694 % (space, _c_accessor_get_expr(expr, lenfield_prefix, sep)))
695 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_unserialize_name))
696 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
697 code_lines.append('%s }' % space)
698 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
701 # _c_serialize_helper_list_field()
703 def _c_serialize_helper_fields_fixed_size(context, self, field,
704 code_lines, temp_vars,
706 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
707 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
709 length = "sizeof(%s)" % field.c_field_type
711 if 'unserialize' == context:
712 value = ' %s%s = *(%s *)xcb_tmp;' % (prefix_str, field.c_field_name, field.c_field_type)
713 if field.type.is_pad and field.type.nmemb > 1:
715 for i in range(field.type.nmemb):
716 code_lines.append('%s %s%s[%d] = *(%s *)xcb_tmp;' %
717 (space, prefix_str, field.c_field_name, i, field.c_field_type))
718 length += " * %d" % field.type.nmemb
720 if field.type.is_list:
721 raise Exception('list with fixed number of elemens unhandled in _unserialize()')
722 elif 'serialize' == context:
723 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
725 if field.type.is_expr:
726 # need to register a temporary variable for the expression
727 if field.type.c_type is None:
728 raise Exception("type for field '%s' (expression '%s') unkown" %
729 (field.field_name, _c_accessor_get_expr(field.type.expr)))
730 temp_vars.append(' %s xcb_expr_%s = %s;' % (field.type.c_type, field.field_name,
731 _c_accessor_get_expr(field.type.expr, prefix)))
732 value += "&xcb_expr_%s;" % field.field_name
734 elif field.type.is_pad:
735 if field.type.nmemb == 1:
738 # FIXME - possible segmentation fault!!
739 value = ' memset(xcb_parts[xcb_parts_idx].iov_base, 0, %d);' % field.type.nmemb
740 length += "*%d" % field.type.nmemb
743 # non-list type with fixed size
744 if field.type.nmemb == 1:
745 value += "&%s%s;" % (prefix_str, field.c_field_name)
746 # list with nmemb (fixed size) elements
748 value += '%s%s;' % (prefix_str, field.c_field_name)
749 length = '%d' % field.type.nmemb
751 return (value, length)
752 # _c_serialize_helper_fields_fixed_size()
754 def _c_serialize_helper_fields_variable_size(context, self, field,
755 code_lines, temp_vars,
757 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
759 if 'unserialize' == context:
761 elif 'serialize' == context:
762 address_of = '&' if (self.is_bitcase and self.has_name) else ''
763 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s%s%s;' % (address_of, prefix_str, field.c_field_name)
766 prefix_str, lenfield_prefix = _c_serialize_helper_prefix(prefix)
767 code_lines.append('%s /* %s */' % (space, field.c_field_name))
769 if field.type.is_list:
770 length = _c_serialize_helper_list_field(context, self, field,
771 code_lines, temp_vars,
773 elif field.type.is_switch:
774 prev = filter(lambda x: x.find('xcb_switch_field'), temp_vars)
775 var_name = 'xcb_switch_field%d' % len(prev)
776 temp_vars.append(' %s %s;' % (field.type.c_type, var_name))
777 length = _c_serialize_helper_switch_field(context, self, field, var_name, prefix)
779 length = "%s(xcb_tmp)" % (field.type.c_unserialize_name)
781 return (value, length)
782 # _c_serialize_helper_fields_variable_size
784 def _c_serialize_helper_fields(context, self,
785 code_lines, temp_vars,
786 space, prefix, is_bitcase):
789 prev_field_was_variable = False
791 for field in self.fields:
792 if not ((field.wire and not field.auto) or field.visible):
795 # switch/bitcase: fixed size fields must be considered explicitly
796 if field.type.fixed_size():
797 if self.is_bitcase or self.var_followed_by_fixed_fields:
798 if prev_field_was_variable and need_padding:
800 _c_serialize_helper_insert_padding(context, code_lines, space)
801 prev_field_was_variable = False
802 fixed_prefix = prefix
803 if self.var_followed_by_fixed_fields and len(prefix)==0:
804 fixed_prefix = [('_aux', '->', self)]
805 value, length = _c_serialize_helper_fields_fixed_size(context, self, field,
806 code_lines, temp_vars,
811 # fields with variable size
813 # switch/bitcase: always calculate padding before and after variable sized fields
814 if need_padding or is_bitcase:
815 _c_serialize_helper_insert_padding(context, code_lines, space)
817 value, length = _c_serialize_helper_fields_variable_size(context, self, field,
818 code_lines, temp_vars,
820 prev_field_was_variable = True
822 # save (un)serialization C code
824 code_lines.append('%s%s' % (space, value))
825 if field.type.fixed_size() and is_bitcase:
826 code_lines.append('%s xcb_block_len += %s;' % (space, length))
827 if 'unserialize' == context:
828 code_lines.append('%s xcb_tmp += %s;' % (space, length))
832 code_lines.append('%s xcb_block_len = %s;' % (space, length))
833 if 'unserialize' == context:
834 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
835 if 'serialize' == context:
837 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_block_len;' % space)
838 code_lines.append('%s xcb_parts_idx++;' % space)
843 # _c_serialize_helper_fields()
845 def _c_serialize_helper(context, complex_type,
846 code_lines, temp_vars,
847 space='', prefix=[]):
849 if hasattr(complex_type, 'type'):
850 self = complex_type.type
851 complex_name = complex_type.name
854 complex_name = '_aux'
856 # special case: switch is serialized by evaluating each bitcase separately
858 count += _c_serialize_helper_switch(context, self, complex_name,
859 code_lines, temp_vars,
862 # all other data types can be evaluated one field a time
864 # unserialize & fixed size fields: simply cast the buffer to the respective xcb_out type
865 if 'unserialize' == context and not self.var_followed_by_fixed_fields:
866 code_lines.append('%s xcb_block_len += sizeof(%s);' % (space, self.c_type))
867 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
868 _c_serialize_helper_insert_padding(context, code_lines, space)
870 count += _c_serialize_helper_fields(context, self,
871 code_lines, temp_vars,
872 space, prefix, False)
874 count += _c_serialize_helper_insert_padding(context, code_lines, space)
877 # _c_serialize_helper()
879 def _c_serialize(self):
884 # _serialize() returns the buffer size
887 variable_size_fields = 0
888 # maximum space required for type definition of function arguments
890 param_fields, wire_fields, params = get_serialize_params('serialize', self)
892 # determine N(variable_fields)
893 for field in param_fields:
894 # if self.is_switch, treat all fields as if they are variable sized
895 if not field.type.fixed_size() or self.is_switch:
896 variable_size_fields += 1
897 # determine maxtypelen
899 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
902 for idx, p in enumerate(params):
904 typespec, pointerspec, field_name = p
905 indent = ' '*(len(self.c_serialize_name)+2)
906 # p==0: function declaration
908 line = "%s (" % self.c_serialize_name
910 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
911 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
912 if idx < len(params)-1:
919 if not self.is_switch:
920 _c(' %s *xcb_out = *_buffer;', self.c_type)
921 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
922 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
924 _c(' char *xcb_out = *_buffer;')
925 _c(' unsigned int xcb_buffer_len = 0;')
926 if variable_size_fields > 0:
929 count =_c_serialize_helper('serialize', self,
930 code_lines, temp_vars)
931 # update variable size fields
932 variable_size_fields = count
933 temp_vars.append(' unsigned int xcb_pad = 0;')
934 temp_vars.append(' char xcb_pad0[3] = {0, 0, 0};')
935 temp_vars.append(' struct iovec xcb_parts[%d];' % (count+1))
936 temp_vars.append(' unsigned int xcb_parts_idx = 0;')
937 temp_vars.append(' unsigned int xcb_block_len = 0;')
938 temp_vars.append(' unsigned int i;')
939 temp_vars.append(' char *xcb_tmp;')
945 if variable_size_fields > 0:
950 # variable sized fields have been collected, now
951 # allocate memory and copy everything into a continuous memory area
952 _c(' if (NULL == xcb_out) {')
953 _c(' /* allocate memory */')
954 _c(' *_buffer = malloc(xcb_buffer_len);')
955 _c(' xcb_out = *_buffer;')
959 # fill in struct members
960 if not self.is_switch:
961 if len(wire_fields)>0:
962 _c(' *xcb_out = *_aux;')
964 # copy variable size fields into the buffer
965 if variable_size_fields > 0:
967 if not self.is_switch:
968 _c(' xcb_tmp = (char*)++xcb_out;')
969 _c(' xcb_tmp += xcb_out_pad;')
971 _c(' xcb_tmp = xcb_out;')
973 # variable sized fields
974 _c(' for(i=0; i<xcb_parts_idx; i++) {')
975 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
976 _c(' xcb_tmp += xcb_parts[i].iov_len;')
979 _c(' return xcb_buffer_len;')
983 def _c_unserialize(self):
989 # _unserialize() returns the buffer size as well
993 variable_size_fields = 0
994 # maximum space required for type definition of function arguments
996 param_fields, wire_fields, params = get_serialize_params('unserialize', self)
998 # determine N(variable_fields)
999 for field in param_fields:
1000 # if self.is_switch, treat all fields as if they are variable sized
1001 if not field.type.fixed_size() or self.is_switch:
1002 variable_size_fields += 1
1003 # determine maxtypelen
1005 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
1008 for idx, p in enumerate(params):
1010 typespec, pointerspec, field_name = p
1011 indent = ' '*(len(self.c_unserialize_name)+2)
1012 # p==0: function declaration
1014 line = "%s (" % self.c_unserialize_name
1016 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
1017 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
1018 if idx < len(params)-1:
1025 _c(' char *xcb_tmp = (char *)_buffer;')
1026 if not self.is_switch:
1027 if not self.var_followed_by_fixed_fields:
1028 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
1030 _c(' %s *_aux = malloc(sizeof(%s));', self.c_type, self.c_type)
1031 _c(' unsigned int xcb_buffer_len = 0;')
1032 _c(' unsigned int xcb_block_len = 0;')
1033 _c(' unsigned int xcb_pad = 0;')
1037 _c_serialize_helper('unserialize', self,
1038 code_lines, temp_vars)
1043 for l in code_lines:
1046 if not self.is_switch:
1047 if self.var_followed_by_fixed_fields:
1050 _c(' return xcb_buffer_len;')
1054 def _c_iterator_get_end(field, accum):
1056 Figures out what C code is needed to find the end of a variable-length structure field.
1057 For nested structures, recurses into its last variable-sized field.
1058 For lists, calls the end function
1060 if field.type.is_container:
1061 accum = field.c_accessor_name + '(' + accum + ')'
1062 # XXX there could be fixed-length fields at the end
1063 return _c_iterator_get_end(field.type.last_varsized_field, accum)
1064 if field.type.is_list:
1065 # XXX we can always use the first way
1066 if field.type.member.is_simple:
1067 return field.c_end_name + '(' + accum + ')'
1069 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
1071 def _c_iterator(self, name):
1073 Declares the iterator structure and next/end functions for a given type.
1078 _h(' * @brief %s', self.c_iterator_type)
1080 _h('typedef struct %s {', self.c_iterator_type)
1081 _h(' %s *data; /**< */', self.c_type)
1082 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
1083 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
1084 _h('} %s;', self.c_iterator_type)
1090 _h(' * Get the next element of the iterator')
1091 _h(' * @param i Pointer to a %s', self.c_iterator_type)
1093 _h(' * Get the next element in the iterator. The member rem is')
1094 _h(' * decreased by one. The member data points to the next')
1095 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
1099 _hc('/*****************************************************************************')
1101 _hc(' ** void %s', self.c_next_name)
1103 _hc(' ** @param %s *i', self.c_iterator_type)
1104 _hc(' ** @returns void')
1106 _hc(' *****************************************************************************/')
1109 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
1110 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
1113 if not self.fixed_size():
1114 _c(' %s *R = i->data;', self.c_type)
1116 # FIXME - how to determine the size of a variable size union??
1117 _c(' /* FIXME - determine the size of the union %s */', self.c_type)
1119 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
1121 _c(' i->data = (%s *) child.data;', self.c_type)
1122 _c(' i->index = child.index;')
1126 _c(' i->index += sizeof(%s);', self.c_type)
1132 _h(' * Return the iterator pointing to the last element')
1133 _h(' * @param i An %s', self.c_iterator_type)
1134 _h(' * @return The iterator pointing to the last element')
1136 _h(' * Set the current element in the iterator to the last element.')
1137 _h(' * The member rem is set to 0. The member data points to the')
1138 _h(' * last element.')
1142 _hc('/*****************************************************************************')
1144 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1146 _hc(' ** @param %s i', self.c_iterator_type)
1147 _hc(' ** @returns xcb_generic_iterator_t')
1149 _hc(' *****************************************************************************/')
1151 _hc('xcb_generic_iterator_t')
1152 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1153 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1155 _c(' xcb_generic_iterator_t ret;')
1157 if self.fixed_size():
1158 _c(' ret.data = i.data + i.rem;')
1159 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1162 _c(' while(i.rem > 0)')
1163 _c(' %s(&i);', self.c_next_name)
1164 _c(' ret.data = i.data;')
1165 _c(' ret.rem = i.rem;')
1166 _c(' ret.index = i.index;')
1171 def _c_accessor_get_length(expr, prefix='', sep='->'):
1173 Figures out what C code is needed to get a length field.
1174 For fields that follow a variable-length field, use the accessor.
1175 Otherwise, just reference the structure field directly.
1177 prefarrow = '' if prefix == '' else prefix + sep
1179 if expr.lenfield != None and expr.lenfield.prev_varsized_field != None:
1180 # special case: variable and fixed size fields are intermixed
1181 retval = expr.lenfield.c_accessor_name + '(' + prefix + ')'
1182 if prefix in ('', '_aux'):
1183 prefix_str = '' if prefix=='' else '%s' % (prefarrow)
1184 retval = '%s%s' % (prefix_str, expr.lenfield_name)
1186 elif expr.lenfield_name != None:
1187 if prefix.endswith(sep):
1188 return prefix + expr.lenfield_name
1190 return prefarrow + expr.lenfield_name
1192 return str(expr.nmemb)
1194 def _c_accessor_get_expr(expr, prefix='', sep='->'):
1196 Figures out what C code is needed to get the length of a list field.
1197 Recurses for math operations.
1198 Returns bitcount for value-mask fields.
1199 Otherwise, uses the value of the length field.
1201 lenexp = _c_accessor_get_length(expr, prefix, sep)
1204 return '(' + '~' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1205 elif expr.op == 'popcount':
1206 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1207 elif expr.op == 'enumref':
1208 enum_name = expr.lenfield_type.name
1209 constant_name = expr.lenfield_name
1210 c_name = _n(enum_name + (constant_name,)).upper()
1212 elif expr.op == 'sumof':
1213 # 1. locate the referenced list object
1214 list_obj = expr.lenfield_type
1216 for f in expr.lenfield_parent.fields:
1217 if f.field_name == expr.lenfield_name:
1221 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1222 if prefix != '' and not prefix.endswith(sep):
1224 list_name = "%s%s" % (prefix, field.c_field_name)
1225 c_length_func = "%s(%s%s)" % (field.c_length_name, prefix, field.c_field_name)
1227 c_length_func = _c_accessor_get_expr(field.type.expr, prefix='', sep='')
1228 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1229 elif expr.op != None:
1230 return '(' + _c_accessor_get_expr(expr.lhs, prefix, sep) + ' ' + expr.op + ' ' + _c_accessor_get_expr(expr.rhs, prefix, sep) + ')'
1232 return 'xcb_popcount(' + lenexp + ')'
1234 return lenexp + '/* bla */'
1236 def _c_accessors_field(self, field):
1238 Declares the accessor functions for a non-list field that follows a variable-length field.
1240 if field.type.is_simple:
1243 _hc('/*****************************************************************************')
1245 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1247 _hc(' ** @param const %s *R', self.c_type)
1248 _hc(' ** @returns %s', field.c_field_type)
1250 _hc(' *****************************************************************************/')
1252 _hc('%s', field.c_field_type)
1253 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1254 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1256 if field.prev_varsized_field is None:
1257 _c(' return (%s *) (R + 1);', field.c_field_type)
1259 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1260 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1261 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1266 _hc('/*****************************************************************************')
1268 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1270 _hc(' ** @param const %s *R', self.c_type)
1271 _hc(' ** @returns %s *', field.c_field_type)
1273 _hc(' *****************************************************************************/')
1275 _hc('%s *', field.c_field_type)
1276 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1277 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1279 if field.prev_varsized_field is None:
1280 _c(' return (%s *) (R + 1);', field.c_field_type)
1282 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1283 _c(' return (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1284 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1287 def _c_accessors_list(self, field):
1289 Declares the accessor functions for a list field.
1290 Declares a direct-accessor function only if the list members are fixed size.
1291 Declares length and get-iterator functions always.
1297 if list.member.fixed_size():
1300 _hc('/*****************************************************************************')
1302 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1304 _hc(' ** @param const %s *R', self.c_type)
1305 _hc(' ** @returns %s *', field.c_field_type)
1307 _hc(' *****************************************************************************/')
1309 _hc('%s *', field.c_field_type)
1310 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1311 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1314 if field.prev_varsized_field is None:
1315 _c(' return (%s *) (R + 1);', field.c_field_type)
1317 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1318 _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)
1324 _hc('/*****************************************************************************')
1326 _hc(' ** int %s', field.c_length_name)
1328 _hc(' ** @param const %s *R', self.c_type)
1329 _hc(' ** @returns int')
1331 _hc(' *****************************************************************************/')
1334 _h('%s (const %s *R /**< */);', field.c_length_name, self.c_type)
1335 _c('%s (const %s *R /**< */)', field.c_length_name, self.c_type)
1337 _c(' return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1340 if field.type.member.is_simple:
1343 _hc('/*****************************************************************************')
1345 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1347 _hc(' ** @param const %s *R', self.c_type)
1348 _hc(' ** @returns xcb_generic_iterator_t')
1350 _hc(' *****************************************************************************/')
1352 _hc('xcb_generic_iterator_t')
1353 _h('%s (const %s *R /**< */);', field.c_end_name, self.c_type)
1354 _c('%s (const %s *R /**< */)', field.c_end_name, self.c_type)
1356 _c(' xcb_generic_iterator_t i;')
1358 if field.prev_varsized_field == None:
1359 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1361 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1362 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1365 _c(' i.index = (char *) i.data - (char *) R;')
1372 _hc('/*****************************************************************************')
1374 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1376 _hc(' ** @param const %s *R', self.c_type)
1377 _hc(' ** @returns %s', field.c_iterator_type)
1379 _hc(' *****************************************************************************/')
1381 _hc('%s', field.c_iterator_type)
1382 _h('%s (const %s *R /**< */);', field.c_iterator_name, self.c_type)
1383 _c('%s (const %s *R /**< */)', field.c_iterator_name, self.c_type)
1385 _c(' %s i;', field.c_iterator_type)
1387 if field.prev_varsized_field == None:
1388 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1390 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1391 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', field.c_field_type, field.c_field_type)
1393 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1394 _c(' i.index = (char *) i.data - (char *) R;')
1398 def _c_accessors(self, name, base):
1400 Declares the accessor functions for the fields of a structure.
1402 for field in self.fields:
1403 # no accessors for switch -
1404 # switch always needs to be unserialized explicitly
1407 if field.type.is_list and not field.type.fixed_size():
1408 _c_accessors_list(self, field)
1409 elif field.prev_varsized_field != None or not field.type.fixed_size():
1410 _c_accessors_field(self, field)
1412 def c_simple(self, name):
1414 Exported function that handles cardinal type declarations.
1415 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1417 _c_type_setup(self, name, ())
1419 if (self.name != name):
1424 _h('typedef %s %s;', _t(self.name), my_name)
1427 _c_iterator(self, name)
1429 def _c_complex(self):
1431 Helper function for handling all structure types.
1432 Called for all structs, requests, replies, events, errors.
1437 _h(' * @brief %s', self.c_type)
1439 _h('typedef %s %s {', self.c_container, self.c_type)
1445 for field in self.fields:
1446 if not field.type.fixed_size() and not self.is_switch and not self.is_union:
1447 varfield = field.c_field_name
1449 # if varfield != None and not field.type.is_pad and field.wire:
1450 # errmsg = '%s: warning: variable field %s followed by fixed field %s\n' % (self.c_type, varfield, field.c_field_name)
1451 # sys.stderr.write(errmsg)
1454 struct_fields.append(field)
1456 for field in struct_fields:
1457 length = len(field.c_field_type)
1458 # account for '*' pointer_spec
1459 if not field.type.fixed_size():
1461 maxtypelen = max(maxtypelen, length)
1463 def _c_complex_field(self, field, space=''):
1464 if (field.type.fixed_size() or
1465 # in case of switch with switch children, don't make the field a pointer
1466 # necessary for unserialize to work
1467 (self.is_switch and field.type.is_switch)):
1468 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1469 _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1471 spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
1472 _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1474 if not self.is_switch:
1475 for field in struct_fields:
1476 _c_complex_field(self, field)
1478 for b in self.bitcases:
1481 _h(' struct _%s {', b.c_field_name)
1483 for field in b.type.fields:
1484 _c_complex_field(self, field, space)
1486 _h(' } %s;', b.c_field_name)
1488 _h('} %s;', self.c_type)
1490 def c_struct(self, name):
1492 Exported function that handles structure declarations.
1494 _c_type_setup(self, name, ())
1496 _c_accessors(self, name, name)
1497 _c_iterator(self, name)
1499 def c_union(self, name):
1501 Exported function that handles union declarations.
1503 _c_type_setup(self, name, ())
1505 _c_iterator(self, name)
1507 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1509 Declares a request function.
1512 # Four stunningly confusing possibilities here:
1515 # ------------------------------
1517 # 0 flag CHECKED flag Normal Mode
1518 # void_cookie req_cookie
1519 # ------------------------------
1520 # "req_checked" "req_unchecked"
1521 # CHECKED flag 0 flag Abnormal Mode
1522 # void_cookie req_cookie
1523 # ------------------------------
1526 # Whether we are _checked or _unchecked
1527 checked = void and not regular
1528 unchecked = not void and not regular
1530 # What kind of cookie we return
1531 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1533 # What flag is passed to xcb_request
1534 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1536 # Global extension id variable or NULL for xproto
1537 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1539 # What our function name is
1540 func_name = self.c_request_name if not aux else self.c_aux_name
1542 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1544 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1548 maxtypelen = len('xcb_connection_t')
1551 for field in self.fields:
1553 # The field should appear as a call parameter
1554 param_fields.append(field)
1555 if field.wire and not field.auto:
1556 # We need to set the field up in the structure
1557 wire_fields.append(field)
1558 if field.type.need_serialize:
1559 serial_fields.append(field)
1561 for field in param_fields:
1562 c_field_const_type = field.c_field_const_type
1563 if field.type.need_serialize and not aux:
1564 c_field_const_type = "const void"
1565 if len(c_field_const_type) > maxtypelen:
1566 maxtypelen = len(c_field_const_type)
1572 _h(' * Delivers a request to the X server')
1573 _h(' * @param c The connection')
1574 _h(' * @return A cookie')
1576 _h(' * Delivers a request to the X server.')
1579 _h(' * This form can be used only if the request will not cause')
1580 _h(' * a reply to be generated. Any returned error will be')
1581 _h(' * saved for handling by xcb_request_check().')
1583 _h(' * This form can be used only if the request will cause')
1584 _h(' * a reply to be generated. Any returned error will be')
1585 _h(' * placed in the event queue.')
1589 _hc('/*****************************************************************************')
1591 _hc(' ** %s %s', cookie_type, func_name)
1594 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1595 _hc(' ** @param xcb_connection_t%s *c', spacing)
1597 for field in param_fields:
1598 c_field_const_type = field.c_field_const_type
1599 if field.type.need_serialize and not aux:
1600 c_field_const_type = "const void"
1601 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1602 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1604 _hc(' ** @returns %s', cookie_type)
1606 _hc(' *****************************************************************************/')
1608 _hc('%s', cookie_type)
1610 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1611 comma = ',' if len(param_fields) else ');'
1612 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1613 comma = ',' if len(param_fields) else ')'
1614 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1616 func_spacing = ' ' * (len(func_name) + 2)
1617 count = len(param_fields)
1618 for field in param_fields:
1620 c_field_const_type = field.c_field_const_type
1621 c_pointer = field.c_pointer
1622 if field.type.need_serialize and not aux:
1623 c_field_const_type = "const void"
1625 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1626 comma = ',' if count else ');'
1627 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1628 spacing, c_pointer, field.c_field_name, comma)
1629 comma = ',' if count else ')'
1630 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1631 spacing, c_pointer, field.c_field_name, comma)
1634 if not self.var_followed_by_fixed_fields:
1635 for field in param_fields:
1636 if not field.type.fixed_size():
1638 if field.type.need_serialize:
1639 # _serialize() keeps track of padding automatically
1642 # there will be only one call to _serialize() and no need for additional padding
1646 _c(' static const xcb_protocol_request_t xcb_req = {')
1647 _c(' /* count */ %d,', count)
1648 _c(' /* ext */ %s,', func_ext_global)
1649 _c(' /* opcode */ %s,', self.c_request_name.upper())
1650 _c(' /* isvoid */ %d', 1 if void else 0)
1654 _c(' struct iovec xcb_parts[%d];', count + 2)
1655 _c(' %s xcb_ret;', func_cookie)
1656 _c(' %s xcb_out;', self.c_type)
1657 if self.var_followed_by_fixed_fields:
1658 _c(' /* in the protocol description, variable size fields are followed by fixed size fields */')
1661 for idx, f in enumerate(serial_fields):
1663 _c(' %s xcb_aux%d;' % (f.type.c_type, idx))
1665 _c(' void *xcb_aux%d = 0;' % (idx))
1667 _c(' printf("in function %s\\n");' % func_name)
1670 for field in wire_fields:
1671 if field.type.fixed_size():
1672 if field.type.is_expr:
1673 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr))
1674 elif field.type.is_pad:
1675 if field.type.nmemb == 1:
1676 _c(' xcb_out.%s = 0;', field.c_field_name)
1678 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
1680 if field.type.nmemb == 1:
1681 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
1683 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
1685 def get_serialize_args(type_obj, c_field_name, aux_var, unserialize=False):
1687 serialize_args = get_serialize_params('unserialize', type_obj,
1691 serialize_args = get_serialize_params('serialize', type_obj,
1694 serialize_args = reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
1695 return serialize_args
1697 # calls in order to free dyn. all. memory
1700 if not self.var_followed_by_fixed_fields:
1702 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
1703 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
1704 _c(' xcb_parts[3].iov_base = 0;')
1705 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
1709 for field in param_fields:
1710 if not field.type.fixed_size():
1711 _c(' /* %s %s */', field.type.c_type, field.c_field_name)
1712 # default: simple cast to char *
1713 if not field.type.need_serialize:
1714 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1715 if field.type.is_list:
1716 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
1717 _c_accessor_get_expr(field.type.expr), field.type.member.c_wiretype)
1719 # not supposed to happen
1720 raise Exception("unhandled variable size field %s" % field.c_field_name)
1723 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1724 idx = serial_fields.index(field)
1725 aux_var = '&xcb_aux%d' % idx
1726 serialize_args = get_serialize_args(field.type, field.c_field_name, aux_var, not aux)
1727 _c(' xcb_parts[%d].iov_len = ', count)
1729 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
1730 _c(' xcb_parts[%d].iov_base = xcb_aux%d;' % (count, idx))
1731 free_calls.append(' free(xcb_aux%d);' % idx)
1733 _c(' %s (%s);', field.type.c_unserialize_name, serialize_args)
1736 if not field.type.need_serialize:
1737 # the _serialize() function keeps track of padding automatically
1738 _c(' xcb_parts[%d].iov_base = 0;', count)
1739 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
1742 # elif self.var_followed_by_fixed_fields:
1745 buffer_var = 'xcb_parts[%d].iov_base' % count
1746 serialize_args = get_serialize_args(self, '&xcb_out', '&%s' % buffer_var, False)
1747 _c(' %s = (char *) 0;', buffer_var)
1748 _c(' xcb_parts[%d].iov_len = %s (%s);', count, self.c_serialize_name, serialize_args)
1749 free_calls.append(' free(xcb_parts[%d].iov_base);' % count)
1750 # no padding necessary - _serialize() keeps track of padding automatically
1753 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
1755 # free dyn. all. data, if any
1756 for f in free_calls:
1758 _c(' return xcb_ret;')
1761 def _c_reply(self, name):
1763 Declares the function that returns the reply structure.
1765 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
1766 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
1767 spacing3 = ' ' * (len(self.c_reply_name) + 2)
1771 _h(' * Return the reply')
1772 _h(' * @param c The connection')
1773 _h(' * @param cookie The cookie')
1774 _h(' * @param e The xcb_generic_error_t supplied')
1776 _h(' * Returns the reply of the request asked by')
1778 _h(' * The parameter @p e supplied to this function must be NULL if')
1779 _h(' * %s(). is used.', self.c_unchecked_name)
1780 _h(' * Otherwise, it stores the error if any.')
1782 _h(' * The returned value must be freed by the caller using free().')
1786 _hc('/*****************************************************************************')
1788 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
1790 _hc(' ** @param xcb_connection_t%s *c', spacing1)
1791 _hc(' ** @param %s cookie', self.c_cookie_type)
1792 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
1793 _hc(' ** @returns %s *', self.c_reply_type)
1795 _hc(' *****************************************************************************/')
1797 _hc('%s *', self.c_reply_type)
1798 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
1799 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
1800 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
1801 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
1803 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
1806 def _c_opcode(name, opcode):
1808 Declares the opcode define for requests, events, and errors.
1812 _h('/** Opcode for %s. */', _n(name))
1813 _h('#define %s %s', _n(name).upper(), opcode)
1815 def _c_cookie(self, name):
1817 Declares the cookie type for a non-void request.
1822 _h(' * @brief %s', self.c_cookie_type)
1824 _h('typedef struct %s {', self.c_cookie_type)
1825 _h(' unsigned int sequence; /**< */')
1826 _h('} %s;', self.c_cookie_type)
1828 def c_request(self, name):
1830 Exported function that handles request declarations.
1832 _c_type_setup(self, name, ('request',))
1835 # Cookie type declaration
1836 _c_cookie(self, name)
1839 _c_opcode(name, self.opcode)
1841 # Request structure declaration
1845 _c_type_setup(self.reply, name, ('reply',))
1846 # Reply structure definition
1847 _c_complex(self.reply)
1848 # Request prototypes
1849 _c_request_helper(self, name, self.c_cookie_type, False, True)
1850 _c_request_helper(self, name, self.c_cookie_type, False, False)
1852 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
1853 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
1855 _c_accessors(self.reply, name + ('reply',), name)
1856 _c_reply(self, name)
1858 # Request prototypes
1859 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
1860 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
1862 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
1863 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
1866 def c_event(self, name):
1868 Exported function that handles event declarations.
1870 _c_type_setup(self, name, ('event',))
1873 _c_opcode(name, self.opcodes[name])
1875 if self.name == name:
1876 # Structure definition
1881 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
1883 def c_error(self, name):
1885 Exported function that handles error declarations.
1887 _c_type_setup(self, name, ('error',))
1890 _c_opcode(name, self.opcodes[name])
1892 if self.name == name:
1893 # Structure definition
1898 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
1901 # Main routine starts here
1903 # Must create an "output" dictionary before any xcbgen imports.
1904 output = {'open' : c_open,
1906 'simple' : c_simple,
1908 'struct' : c_struct,
1910 'request' : c_request,
1915 # Boilerplate below this point
1917 # Check for the argument that specifies path to the xcbgen python package.
1919 opts, args = getopt.getopt(sys.argv[1:], 'p:')
1920 except getopt.GetoptError, err:
1922 print 'Usage: c_client.py [-p path] file.xml'
1925 for (opt, arg) in opts:
1927 sys.path.append(arg)
1929 # Import the module class
1931 from xcbgen.state import Module
1934 print 'Failed to load the xcbgen Python package!'
1935 print 'Make sure that xcb/proto installed it on your Python path.'
1936 print 'If not, you will need to create a .pth file or define $PYTHONPATH'
1937 print 'to extend the path.'
1938 print 'Refer to the README file in xcb/proto for more info.'
1942 # Parse the xml header
1943 module = Module(args[0], output)
1945 # Build type-registry and resolve type dependencies