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',
26 # global variable to keep track of serializers
27 # due to weird dependencies, I see no way to do this more elegant at the moment
28 finished_serializers = []
32 Writes the given line to the header file.
34 _hlines[_hlevel].append(fmt % args)
38 Writes the given line to the source file.
40 _clines[_clevel].append(fmt % args)
44 Writes the given line to both the header and source files.
49 # XXX See if this level thing is really necessary.
52 Changes the array that header lines are written to.
53 Supports writing different sections of the header file.
56 while len(_hlines) <= idx:
62 Changes the array that source lines are written to.
63 Supports writing to different sections of the source file.
66 while len(_clines) <= idx:
72 Does C-name conversion on a single string fragment.
73 Uses a regexp with some hard-coded special cases.
75 if str in _cname_special_cases:
76 return _cname_special_cases[str]
78 split = _cname_re.finditer(str)
79 name_parts = [match.group(0) for match in split]
80 return '_'.join(name_parts)
84 Checks for certain C++ reserved words and fixes them.
86 if str in _cplusplus_annoyances:
87 return _cplusplus_annoyances[str]
93 Does C-name conversion on an extension name.
94 Has some additional special cases on top of _n_item.
96 if str in _extension_special_cases:
97 return _n_item(str).lower()
103 Does C-name conversion on a tuple of strings.
104 Different behavior depending on length of tuple, extension/not extension, etc.
105 Basically C-name converts the individual pieces, then joins with underscores.
110 parts = [list[0], _n_item(list[1])]
112 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
114 parts = [list[0]] + [_n_item(i) for i in list[1:]]
115 return '_'.join(parts).lower()
119 Does C-name conversion on a tuple of strings representing a type.
120 Same as _n but adds a "_t" on the end.
125 parts = [list[0], _n_item(list[1]), 't']
127 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
129 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
130 return '_'.join(parts).lower()
135 Exported function that handles module open.
136 Opens the files and writes out the auto-generated comment, header file includes, etc.
140 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
142 # Build the type-name collision avoidance table used by c_enum
143 build_collision_table()
149 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
150 _hc(' * Edit at your peril.')
155 _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
156 _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
160 _h('#ifndef __%s_H', _ns.header.upper())
161 _h('#define __%s_H', _ns.header.upper())
163 _h('#include "xcb.h"')
165 _c('#include <stdlib.h>')
166 _c('#include <string.h>')
167 _c('#include <assert.h>')
168 _c('#include "xcbext.h"')
169 _c('#include "%s.h"', _ns.header)
172 for (n, h) in self.imports:
173 _hc('#include "%s.h"', h)
176 _h('#ifdef __cplusplus')
182 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
183 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
185 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
188 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
192 Exported function that handles module close.
193 Writes out all the stored content lines, then closes the files.
200 _h('#ifdef __cplusplus')
212 hfile = open('%s.h' % _ns.header, 'w')
220 cfile = open('%s.c' % _ns.header, 'w')
227 def build_collision_table():
231 for v in module.types.values():
233 namecount[name] = (namecount.get(name) or 0) + 1
235 def c_enum(self, name):
237 Exported function that handles enum declarations.
241 if namecount[tname] > 1:
242 tname = _t(name + ('enum',))
246 _h('typedef enum %s {', tname)
248 count = len(self.values)
250 for (enam, eval) in self.values:
252 equals = ' = ' if eval != '' else ''
253 comma = ',' if count > 0 else ''
254 _h(' %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
258 def _c_type_setup(self, name, postfix):
260 Sets up all the C-related state by adding additional data fields to
261 all Field and Type objects. Here is where we figure out most of our
262 variable and function names.
264 Recurses into child fields and list member types.
266 # Do all the various names in advance
267 self.c_type = _t(name + postfix)
268 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
270 self.c_iterator_type = _t(name + ('iterator',))
271 self.c_next_name = _n(name + ('next',))
272 self.c_end_name = _n(name + ('end',))
274 self.c_request_name = _n(name)
275 self.c_checked_name = _n(name + ('checked',))
276 self.c_unchecked_name = _n(name + ('unchecked',))
277 self.c_reply_name = _n(name + ('reply',))
278 self.c_reply_type = _t(name + ('reply',))
279 self.c_cookie_type = _t(name + ('cookie',))
281 self.c_aux_name = _n(name + ('aux',))
282 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
283 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
284 self.c_serialize_name = _n(name + ('serialize',))
285 self.c_unserialize_name = _n(name + ('unserialize',))
287 # whether a request or reply has a switch field
288 self.need_aux = False
289 self.need_serialize = False
291 self.need_serialize = True
292 for bitcase in self.bitcases:
293 _c_type_setup(bitcase.type, bitcase.field_type, ())
295 if self.is_container:
297 self.c_container = 'union' if self.is_union else 'struct'
298 prev_varsized_field = None
299 prev_varsized_offset = 0
300 first_field_after_varsized = None
302 for field in self.fields:
303 # information about a fields anchestors
304 if self.is_reply or hasattr(self, 'in_reply'):
305 field.type.in_reply = True
307 _c_type_setup(field.type, field.field_type, ())
308 if field.type.is_list:
309 _c_type_setup(field.type.member, field.field_type, ())
310 # FIXME - structures with variable sized members, sort out when serialize() is needed
311 if (field.type.nmemb is None): # and not field.type.member.fixed_size():
312 self.need_serialize = True
314 field.c_field_type = _t(field.field_type)
315 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
316 field.c_field_name = _cpp(field.field_name)
317 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
318 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
319 if field.type.is_switch:
320 field.c_pointer = '*'
321 field.c_field_const_type = 'const ' + field.c_field_type
324 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
325 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
326 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
327 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
328 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
330 field.prev_varsized_field = prev_varsized_field
331 field.prev_varsized_offset = prev_varsized_offset
333 if prev_varsized_offset == 0:
334 first_field_after_varsized = field
335 field.first_field_after_varsized = first_field_after_varsized
337 if field.type.fixed_size():
338 prev_varsized_offset += field.type.size
340 self.last_varsized_field = field
341 prev_varsized_field = field
342 prev_varsized_offset = 0
344 # as switch does never appear at toplevel,
345 # continue here with type construction
347 print "switch", self.name
348 # special: switch C structs get pointer fields for variable-sized members
350 # declare switch (un)packing functions
351 _c_accessors(self, name, name)
353 if self.need_serialize and not self.is_bitcase:
354 if self.c_serialize_name not in finished_serializers:
355 # if not hasattr(self, 'in_reply'):
358 finished_serializers.append(self.c_serialize_name)
361 def get_request_fields(self):
365 for field in self.fields:
367 # the field should appear as a parameter in the function call
368 param_fields.append(field)
369 if field.wire and not field.auto:
370 if field.type.fixed_size() and not self.is_switch:
371 # need to set the field up in the xcb_out structure
372 wire_fields.append(field)
373 # fields like 'pad0' are skipped!
375 return (param_fields, wire_fields)
376 # get_request_fields()
378 def unserialize_fields(complex_type, code_lines=[], space='', prefix='', bitcase=False):
382 lenfield_prefix = "_aux"
385 lenfield_prefix += "->%s" % prefix
387 if hasattr(complex_type, 'type'):
388 self = complex_type.type
389 complex_name = complex_type.name
392 complex_name = '_aux'
394 param_fields, wire_fields, params = get_serialize_params(self, unserialize=True)
395 param_names = [p[2] for p in params]
398 switch_expr = _c_accessor_get_expr(self.expr)
400 for b in self.bitcases:
401 bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix)
402 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
403 unserialize_fields(b.type, code_lines, space="%s " % space,
404 prefix="%s%s" % (prefix_str, complex_name), bitcase=True)
405 code_lines.append(' }')
407 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
408 #code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
409 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
413 # if not inside switch, simply cast the buffer to the respective xcb_out type
415 code_lines.append('%s /* %s */' % (space, self.c_type))
416 code_lines.append('%s xcb_buffer_len = sizeof(%s);' % (space, self.c_type))
417 code_lines.append('%s /* padding */' % space)
418 code_lines.append('%s xcb_buffer_len += -xcb_buffer_len & 3;' % space)
419 code_lines.append('%s xcb_tmp += xcb_buffer_len;' % space)
421 for field in self.fields:
422 if not ((field.wire and not field.auto) or field.visible):
425 length = "sizeof(%s)" % field.c_field_type
427 # 1. fields with fixed size need only be filled explicitly inside switch
428 if field.type.fixed_size():
431 value = ' _aux->%s = (%s) *xcb_tmp;' % (field.c_field_name, field.type.c_type)
435 # 2. fields with variable size
436 elif not field.type.fixed_size():
437 # unserialize: always calculate padding before variable sized fields in bitcase
439 if need_padding or bitcase:
440 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
441 code_lines.append('%s if (0 != xcb_pad) {' % space)
442 code_lines.append('%s xcb_tmp += xcb_pad;' % space)
443 code_lines.append('%s xcb_buffer_len += xcb_pad;' % space)
444 code_lines.append('%s xcb_block_len = 0;' % space)
445 code_lines.append('%s xcb_pad = 0;' % space)
446 code_lines.append('%s }' % space)
448 # value = ' *%s = (%s *) xcb_tmp;' % (field.c_field_name, field.type.c_type)
450 if field.type.is_list:
451 # FIXME - list with variable-sized elements
452 if field.type.size is None:
453 errmsg = '%s: warning: list object with variable-sized members not supported for field %s\n'
454 sys.stderr.write(errmsg % (self.c_type, field.c_field_name))
455 expr = field.type.expr
456 # look if the list's lenfield is a struct member or a function argument
457 lf_prefix = lenfield_prefix
458 if expr.lenfield_name == _c_accessor_get_length(expr):
459 if expr.lenfield_name in param_names:
461 length = '%s * sizeof(%s)' % (_c_accessor_get_expr(field.type.expr, lf_prefix), field.type.member.c_wiretype)
462 elif field.type.is_switch:
463 # switch is handled by this function as a special case
464 unserialize_fields(field.type, code_lines, space, prefix="%s%s" % (prefix_str, field.c_field_name))
466 # FIXME - variable sized field that is not a list
467 errmsg = '%s: warning: non-list object of variable size not supported for field %s\n'
468 sys.stderr.write(errmsg % (self.c_type, field.c_field_name))
469 length = '%s * sizeof(%s)' % ('undefined', field.type.c_wiretype)
471 # save serialization C code
472 if value is not None:
473 if field.type.fixed_size():
474 # field appears in the request structure
475 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
477 code_lines.append('%s /* %s */' % (space, field.c_field_name))
481 code_lines.append('%s%s' % (space, value))
482 if field.type.fixed_size():
483 code_lines.append('%s xcb_block_len += %s;' % (space, length))
484 code_lines.append('%s xcb_tmp += %s;' % (space, length))
486 # take account of padding
487 code_lines.append('%s xcb_block_len = %s;' % (space, length))
488 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
489 code_lines.append('%s xcb_tmp += xcb_block_len + xcb_pad;' % space)
490 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
491 code_lines.append('%s xcb_block_len = 0;' % space)
492 code_lines.append('%s xcb_pad = 0;' % space)
495 # unserialize_fields()
498 def serialize_fields(complex_type, code_lines=[], temp_vars=set(),
499 space='', prefix='', serialize_fixed_size_fields=False,
502 helper routine to build up iovec arrays that will later be copied into a single buffer
504 complex_type - encapsulating Type/Field
505 code_lines, temp_vars - containers for generated code & variable declarations
506 space - extra space to be inserted before any statement
507 prefix - prefix to be used for struct members, needed for switch/bitcase mapping
508 bitcase - flags whether fields are bitcase members
511 # count -> no. of entries in xcb_parts array
513 # flag to mark wether explicit padding needs to be inserted
516 lenfield_prefix = "_aux"
519 lenfield_prefix += "->%s" % prefix
522 if hasattr(complex_type, 'type'):
523 self = complex_type.type
524 complex_name = complex_type.name
527 complex_name = '_aux'
529 def insert_padding(count):
530 code_lines.append('%s /* padding */' % space)
531 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
532 code_lines.append('%s if (0 != xcb_pad) {' % space)
533 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
534 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
535 code_lines.append('%s xcb_parts_idx++;' % space)
536 code_lines.append('%s }' % space)
537 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
538 code_lines.append('%s xcb_pad = 0;' % space)
539 code_lines.append('%s xcb_block_len = 0;' % space)
544 # special case - if self.is_switch, all fields need to be serialized conditionally
546 switch_expr = _c_accessor_get_expr(self.expr)
549 for b in self.bitcases:
550 bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix)
551 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
553 count += serialize_fields(b.type, code_lines, temp_vars, '%s ' % space,
554 prefix="%s%s" % (prefix_str, complex_name),
555 serialize_fixed_size_fields=True, bitcase=True)
556 code_lines.append(' }')
557 count = insert_padding(count)
560 for field in self.fields:
563 # sort out invisible fields
564 if not ((field.wire and not field.auto) or field.visible):
567 length = "sizeof(%s)" % field.c_field_type
569 # 1. fields with fixed size
570 # fixed size fields are not always handled here,
571 # dependent on serialize_fixed_size_fields
572 if field.type.fixed_size() and bitcase:
573 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
576 if field.type.is_expr:
577 # need to register a temporary variable for the expression
578 if field.type.c_type is None:
579 raise Exception("type for field '%s' (expression '%s') unkown" %
580 (field.field_name, _c_accessor_get_expr(field.type.expr)))
581 temp_vars.add(' %s xcb_expr_%s = %s;' % (field.type.c_type, field.field_name,
582 _c_accessor_get_expr(field.type.expr, prefix)))
583 value += "&xcb_expr_%s;" % field.field_name
585 elif field.type.is_pad:
586 if field.type.nmemb == 1:
589 value = ' memset(xcb_parts[xcb_parts_idx].iov_base, 0, %d);' % field.type.nmemb
590 length += "*%d" % field.type.nmemb
593 # non-list type with fixed size
594 if field.type.nmemb == 1:
595 value += "&%s%s;" % (prefix_str, field.c_field_name)
596 # list with nmemb (fixed size) elements
598 value += '%s%s;' % (prefix_str, field.c_field_name)
599 length = '%d' % field.type.nmemb
601 # 2. fields with variable size
602 elif not field.type.fixed_size():
603 # always calculate padding before variable sized fields
604 if bitcase or need_padding:
605 count = insert_padding(count)
606 code_lines.append('%s xcb_block_len = 0;' % space)
609 code_lines.append('%s /* %s */' % (space, field.c_field_name))
610 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s%s;' % (prefix_str, field.c_field_name)
611 code_lines.append('%s%s' % (space, value))
613 if field.type.is_list:
614 # list of variable length with variable size elements
615 if field.type.size is None:
616 errmsg = '%s: warning: list object with variable-sized members not supported for field %s\n'
617 sys.stderr.write(errmsg % (self.c_type, field.c_field_name))
618 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = 0;' % space)
619 code_lines.append('%s xcb_tmp = (char *) %s%s;' % (space, prefix_str, field.c_field_name))
620 code_lines.append('%s for(i=0; i<%s; i++) {'
621 % (space, _c_accessor_get_expr(field.type.expr, lenfield_prefix)))
622 code_lines.append('%s xcb_block_len = %s(xcb_tmp);' % (space, field.type.c_unserialize_name))
623 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len += xcb_block_len;' % space)
624 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
625 code_lines.append('%s }' % space)
626 code_lines.append('%s xcb_block_len = xcb_parts[xcb_parts_idx].iov_len;' % space)
628 # list of variable length with fixed size elements
630 length = '%s * sizeof(%s)' % (_c_accessor_get_expr(field.type.expr, lenfield_prefix),
631 field.type.member.c_wiretype)
633 elif field.type.is_switch:
634 # switch is handled at the beginning of this function as a special case
635 # count += serialize_fields(field.type, code_lines, temp_vars, space,
636 # prefix="%s%s" % (prefix_str, field.c_field_name))
637 # FIXME - call another serialize
638 sys.stderr.write("FIXME: call %s" % field.type.c_serialize_name)
640 # FIXME - variable sized field that is not a list
641 errmsg = '%s: warning: non-list object of variable size not supported for field %s\n'
642 sys.stderr.write(errmsg % (self.c_type, field.c_field_name))
643 length = '%s * sizeof(%s)' % ('undefined', field.type.c_wiretype)
645 # 3. save serialization C code
646 if value is not None:
647 # set xcb_parts[].iov_base and xcb_parts[].iov_len
648 # insert a comment so one can easily trace back to the XML
649 if field.type.fixed_size():
650 # field belongs to some anchestor structure
651 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
652 code_lines.append('%s%s' % (space, value))
654 code_lines.append('%s xcb_block_len += %s;' % (space, length))
655 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_block_len;' % space)
657 # increase xcb_parts index
658 code_lines.append('%s xcb_parts_idx++;' % space)
661 if not field.type.fixed_size():
663 count = insert_padding(count)
665 # raise Exception("obsolete - should not be reached")
666 # code_lines.append('%s xcb_unpadded = xcb_parts[xcb_parts_idx].iov_len;' % space)
671 def _c_switch_aux_params(self):
672 # get the fields referenced by the switch expression
673 def get_expr_fields(expr):
675 if expr.lenfield_name is not None:
676 return [expr.lenfield_name]
679 return get_expr_fields(expr.rhs)
680 elif expr.op == 'popcount':
681 return get_expr_fields(expr.rhs)
682 elif expr.op == 'sumof':
683 return [expr.lenfield_name]
684 elif expr.op == 'enumref':
687 return get_expr_fields(expr.lhs) + get_expr_fields(expr.rhs)
690 # resolve the field names with the parent structure(s)
691 unresolved_fields = get_expr_fields(self.expr)
692 expr_fields = dict.fromkeys(unresolved_fields)
693 for p in reversed(self.parent):
694 parent_fields = dict((f.field_name, f) for f in p.fields)
695 if len(unresolved_fields) == 0:
697 for f in parent_fields.keys():
698 if f in unresolved_fields:
699 expr_fields[f] = parent_fields[f]
700 unresolved_fields.remove(f)
702 if None in expr_fields.values():
703 raise Exception("could not resolve all fields for <switch> %s" % self.name)
706 for name, field in expr_fields.iteritems():
707 params.append((field, name))
710 # _c_switch_aux_params()
712 def get_serialize_params(self, buffer_var='_buffer', aux_var='_aux', unserialize=False):
713 param_fields, wire_fields = get_request_fields(self)
715 switch_params = _c_switch_aux_params(self)
716 param_fields += [s[0] for s in switch_params]
718 # _serialize function parameters
720 params = [('void', '**', buffer_var)]
722 params = [('const void', '*', buffer_var)]
724 # make sure all required length fields are present
725 for p in param_fields:
726 if p.visible and not p.wire and not p.auto:
727 typespec = p.c_field_type
729 params.append((typespec, pointerspec, p.c_field_name))
731 # parameter fields if any
733 for p in switch_params:
734 typespec = p[0].c_field_const_type
735 pointerspec = p[0].c_pointer
736 params.append((typespec, pointerspec, p[0].c_field_name))
737 # aux argument - structure to be serialized
739 params.append(('const %s' % self.c_type, '*', aux_var))
741 params.append(('%s' % self.c_type, '*', aux_var))
742 if not self.is_switch and not unserialize:
743 for p in param_fields:
744 if not p.type.fixed_size():
745 params.append((p.c_field_const_type, p.c_pointer, p.c_field_name))
746 return (param_fields, wire_fields, params)
747 # get_serialize_params()
749 def _c_serialize(self):
754 # _serialize() returns the buffer size
757 variable_size_fields = 0
758 # maximum space required for type definition of function arguments
760 param_fields, wire_fields, params = get_serialize_params(self)
762 # determine N(variable_fields)
763 for field in param_fields:
764 # if self.is_switch, treat all fields as if they are variable sized
765 if not field.type.fixed_size() or self.is_switch:
766 variable_size_fields += 1
767 # determine maxtypelen
769 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
772 for p in range(len(params)):
774 typespec, pointerspec, field_name = params[p]
775 indent = ' '*(len(self.c_serialize_name)+2)
776 # p==0: function declaration
778 line = "%s (" % self.c_serialize_name
780 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
781 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
782 if p < len(params)-1:
789 if not self.is_switch:
790 _c(' %s *xcb_out = *_buffer;', self.c_type)
791 _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type)
792 _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type)
794 _c(' char *xcb_out = *_buffer;')
795 _c(' unsigned int xcb_buffer_len = 0;')
796 if variable_size_fields > 0:
799 count = serialize_fields(self, code_lines, temp_vars,
800 serialize_fixed_size_fields=False)
801 # update variable size fields
802 variable_size_fields = count
803 _c(' unsigned int xcb_pad = 0;')
804 _c(' char xcb_pad0[3] = {0, 0, 0};')
805 _c(' struct iovec xcb_parts[%d];', count+1)
806 _c(' unsigned int xcb_parts_idx = 0;')
807 _c(' unsigned int xcb_block_len = 0;')
810 _c(' char *xcb_tmp;')
811 _c(' unsigned int i;')
815 if variable_size_fields > 0:
819 # _c(' /* padding */')
820 # _c(' xcb_pad = -xcb_block_len & 3;')
821 # _c(' if (0 != xcb_pad) {')
822 # _c(' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;')
823 # _c(' xcb_parts[xcb_parts_idx].iov_len = xcb_pad;')
824 # _c(' xcb_parts_idx++;')
826 # _c(' xcb_buffer_len += xcb_block_len + xcb_pad;')
829 # variable sized fields have been collected, now
830 # allocate memory and copy everything into a continuous memory area
831 _c(' if (NULL == xcb_out) {')
832 _c(' /* allocate memory */')
833 _c(' *_buffer = malloc(xcb_buffer_len);')
834 _c(' xcb_out = *_buffer;')
838 # fill in struct members
839 if not self.is_switch:
840 if len(wire_fields)>0:
841 _c(' *xcb_out = *_aux;')
843 # copy variable size fields into the buffer
844 if variable_size_fields > 0:
846 if not self.is_switch:
847 _c(' xcb_tmp = (char*)++xcb_out;')
848 _c(' xcb_tmp += xcb_out_pad;')
850 _c(' xcb_tmp = xcb_out;')
852 # variable sized fields
853 _c(' for(i=0; i<xcb_parts_idx; i++) {')
854 # _c(' if (0 != xcb_parts[i].iov_base) {')
855 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
857 _c(' xcb_tmp += xcb_parts[i].iov_len;')
860 _c(' return xcb_buffer_len;')
864 def _c_unserialize(self):
870 # _unserialize() returns the buffer size as well
874 variable_size_fields = 0
875 # maximum space required for type definition of function arguments
877 param_fields, wire_fields, params = get_serialize_params(self, unserialize=True)
879 # determine N(variable_fields)
880 for field in param_fields:
881 # if self.is_switch, treat all fields as if they are variable sized
882 if not field.type.fixed_size() or self.is_switch:
883 variable_size_fields += 1
884 # determine maxtypelen
886 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
889 for p in range(len(params)):
891 typespec, pointerspec, field_name = params[p]
892 indent = ' '*(len(self.c_unserialize_name)+2)
893 # p==0: function declaration
895 line = "%s (" % self.c_unserialize_name
897 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
898 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
899 if p < len(params)-1:
906 _c(' char *xcb_tmp = (char *)_buffer;')
907 if not self.is_switch:
908 _c(' const %s *_aux = (%s *)_buffer;', self.c_type, self.c_type)
909 _c(' unsigned int xcb_buffer_len = 0;')
910 _c(' unsigned int xcb_block_len = 0;')
911 _c(' unsigned int xcb_pad = 0;')
915 unserialize_fields(self, code_lines)
919 _c(' return xcb_buffer_len;')
923 def _c_iterator_get_end(field, accum):
925 Figures out what C code is needed to find the end of a variable-length structure field.
926 For nested structures, recurses into its last variable-sized field.
927 For lists, calls the end function
929 if field.type.is_container:
930 accum = field.c_accessor_name + '(' + accum + ')'
931 # XXX there could be fixed-length fields at the end
932 return _c_iterator_get_end(field.type.last_varsized_field, accum)
933 if field.type.is_list:
934 # XXX we can always use the first way
935 if field.type.member.is_simple:
936 return field.c_end_name + '(' + accum + ')'
938 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
940 def _c_iterator(self, name):
942 Declares the iterator structure and next/end functions for a given type.
947 _h(' * @brief %s', self.c_iterator_type)
949 _h('typedef struct %s {', self.c_iterator_type)
950 _h(' %s *data; /**< */', self.c_type)
951 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
952 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
953 _h('} %s;', self.c_iterator_type)
959 _h(' * Get the next element of the iterator')
960 _h(' * @param i Pointer to a %s', self.c_iterator_type)
962 _h(' * Get the next element in the iterator. The member rem is')
963 _h(' * decreased by one. The member data points to the next')
964 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
968 _hc('/*****************************************************************************')
970 _hc(' ** void %s', self.c_next_name)
972 _hc(' ** @param %s *i', self.c_iterator_type)
973 _hc(' ** @returns void')
975 _hc(' *****************************************************************************/')
978 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
979 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
982 if not self.fixed_size():
983 _c(' %s *R = i->data;', self.c_type)
984 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
986 _c(' i->data = (%s *) child.data;', self.c_type)
987 _c(' i->index = child.index;')
991 _c(' i->index += sizeof(%s);', self.c_type)
997 _h(' * Return the iterator pointing to the last element')
998 _h(' * @param i An %s', self.c_iterator_type)
999 _h(' * @return The iterator pointing to the last element')
1001 _h(' * Set the current element in the iterator to the last element.')
1002 _h(' * The member rem is set to 0. The member data points to the')
1003 _h(' * last element.')
1007 _hc('/*****************************************************************************')
1009 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
1011 _hc(' ** @param %s i', self.c_iterator_type)
1012 _hc(' ** @returns xcb_generic_iterator_t')
1014 _hc(' *****************************************************************************/')
1016 _hc('xcb_generic_iterator_t')
1017 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
1018 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
1020 _c(' xcb_generic_iterator_t ret;')
1022 if self.fixed_size():
1023 _c(' ret.data = i.data + i.rem;')
1024 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
1027 _c(' while(i.rem > 0)')
1028 _c(' %s(&i);', self.c_next_name)
1029 _c(' ret.data = i.data;')
1030 _c(' ret.rem = i.rem;')
1031 _c(' ret.index = i.index;')
1036 def _c_accessor_get_length(expr, prefix=''):
1038 Figures out what C code is needed to get a length field.
1039 For fields that follow a variable-length field, use the accessor.
1040 Otherwise, just reference the structure field directly.
1042 prefarrow = '' if prefix == '' else prefix + '->'
1044 if expr.lenfield != None and expr.lenfield.prev_varsized_field != None:
1045 return expr.lenfield.c_accessor_name + '(' + prefix + ')'
1046 elif expr.lenfield_name != None:
1047 return prefarrow + expr.lenfield_name
1049 return str(expr.nmemb)
1051 def _c_accessor_get_expr(expr, prefix=''):
1053 Figures out what C code is needed to get the length of a list field.
1054 Recurses for math operations.
1055 Returns bitcount for value-mask fields.
1056 Otherwise, uses the value of the length field.
1058 lenexp = _c_accessor_get_length(expr, prefix)
1061 return '(' + '~' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1062 elif expr.op == 'popcount':
1063 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1064 elif expr.op == 'enumref':
1065 enum_name = expr.lenfield_type.name
1066 constant_name = expr.lenfield_name
1067 c_name = _n(enum_name + (constant_name,)).upper()
1069 elif expr.op == 'sumof':
1070 # 1. locate the referenced list object
1071 list_obj = expr.lenfield_type
1073 for f in expr.lenfield_parent.fields:
1074 if f.field_name == expr.lenfield_name:
1078 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1080 prefix = "%s->" % prefix
1081 list_name = "%s%s" % (prefix, field.c_field_name)
1082 c_length_func = "%s(%s%s)" % (field.c_length_name, prefix, field.c_field_name)
1083 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1084 elif expr.op != None:
1085 return '(' + _c_accessor_get_expr(expr.lhs, prefix) + ' ' + expr.op + ' ' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1087 return 'xcb_popcount(' + lenexp + ')'
1091 def _c_accessors_field(self, field):
1093 Declares the accessor functions for a non-list field that follows a variable-length field.
1095 if field.type.is_simple:
1098 _hc('/*****************************************************************************')
1100 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1102 _hc(' ** @param const %s *R', self.c_type)
1103 _hc(' ** @returns %s', field.c_field_type)
1105 _hc(' *****************************************************************************/')
1107 _hc('%s', field.c_field_type)
1108 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1109 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1111 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1112 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1113 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1118 _hc('/*****************************************************************************')
1120 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1122 _hc(' ** @param const %s *R', self.c_type)
1123 _hc(' ** @returns %s *', field.c_field_type)
1125 _hc(' *****************************************************************************/')
1127 _hc('%s *', field.c_field_type)
1128 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1129 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1131 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1132 _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)
1135 def _c_accessors_list(self, field):
1137 Declares the accessor functions for a list field.
1138 Declares a direct-accessor function only if the list members are fixed size.
1139 Declares length and get-iterator functions always.
1145 if list.member.fixed_size():
1148 _hc('/*****************************************************************************')
1150 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1152 _hc(' ** @param const %s *R', self.c_type)
1153 _hc(' ** @returns %s *', field.c_field_type)
1155 _hc(' *****************************************************************************/')
1157 _hc('%s *', field.c_field_type)
1158 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1159 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1162 if field.prev_varsized_field == None:
1163 _c(' return (%s *) (R + 1);', field.c_field_type)
1165 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1166 _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)
1172 _hc('/*****************************************************************************')
1174 _hc(' ** int %s', field.c_length_name)
1176 _hc(' ** @param const %s *R', self.c_type)
1177 _hc(' ** @returns int')
1179 _hc(' *****************************************************************************/')
1182 _h('%s (const %s *R /**< */);', field.c_length_name, self.c_type)
1183 _c('%s (const %s *R /**< */)', field.c_length_name, self.c_type)
1185 _c(' return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1188 if field.type.member.is_simple:
1191 _hc('/*****************************************************************************')
1193 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1195 _hc(' ** @param const %s *R', self.c_type)
1196 _hc(' ** @returns xcb_generic_iterator_t')
1198 _hc(' *****************************************************************************/')
1200 _hc('xcb_generic_iterator_t')
1201 _h('%s (const %s *R /**< */);', field.c_end_name, self.c_type)
1202 _c('%s (const %s *R /**< */)', field.c_end_name, self.c_type)
1204 _c(' xcb_generic_iterator_t i;')
1206 if field.prev_varsized_field == None:
1207 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1209 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1210 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1213 _c(' i.index = (char *) i.data - (char *) R;')
1220 _hc('/*****************************************************************************')
1222 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1224 _hc(' ** @param const %s *R', self.c_type)
1225 _hc(' ** @returns %s', field.c_iterator_type)
1227 _hc(' *****************************************************************************/')
1229 _hc('%s', field.c_iterator_type)
1230 _h('%s (const %s *R /**< */);', field.c_iterator_name, self.c_type)
1231 _c('%s (const %s *R /**< */)', field.c_iterator_name, self.c_type)
1233 _c(' %s i;', field.c_iterator_type)
1235 if field.prev_varsized_field == None:
1236 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1238 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1239 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', field.c_field_type, field.c_field_type)
1241 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1242 _c(' i.index = (char *) i.data - (char *) R;')
1246 def _c_accessors(self, name, base):
1248 Declares the accessor functions for the fields of a structure.
1250 for field in self.fields:
1251 if field.type.is_list and not field.type.fixed_size():
1252 _c_accessors_list(self, field)
1253 elif field.prev_varsized_field != None:
1254 _c_accessors_field(self, field)
1256 def c_simple(self, name):
1258 Exported function that handles cardinal type declarations.
1259 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1261 _c_type_setup(self, name, ())
1263 if (self.name != name):
1268 _h('typedef %s %s;', _t(self.name), my_name)
1271 _c_iterator(self, name)
1273 def _c_complex(self):
1275 Helper function for handling all structure types.
1276 Called for all structs, requests, replies, events, errors.
1281 _h(' * @brief %s', self.c_type)
1283 _h('typedef %s %s {', self.c_container, self.c_type)
1289 for field in self.fields:
1290 if not field.type.fixed_size() and not self.is_switch:
1291 varfield = field.c_field_name
1293 if varfield != None and not field.type.is_pad and field.wire:
1294 errmsg = '%s: warning: variable field %s followed by fixed field %s\n' % (self.c_type, varfield, field.c_field_name)
1295 sys.stderr.write(errmsg)
1298 struct_fields.append(field)
1300 for field in struct_fields:
1301 length = len(field.c_field_type)
1302 if field.type.fixed_size():
1304 if length > maxtypelen:
1307 for field in struct_fields:
1308 if field.type.fixed_size():
1309 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1310 _h(' %s%s %s%s; /**< */', field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1312 spacing = ' ' * (maxtypelen - (len(field.c_field_type) - 1))
1313 _h(' %s%s *%s%s; /**< */', field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1315 _h('} %s;', self.c_type)
1317 def c_struct(self, name):
1319 Exported function that handles structure declarations.
1321 _c_type_setup(self, name, ())
1323 _c_accessors(self, name, name)
1324 _c_iterator(self, name)
1326 def c_union(self, name):
1328 Exported function that handles union declarations.
1330 _c_type_setup(self, name, ())
1332 _c_iterator(self, name)
1334 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1336 Declares a request function.
1339 # Four stunningly confusing possibilities here:
1342 # ------------------------------
1344 # 0 flag CHECKED flag Normal Mode
1345 # void_cookie req_cookie
1346 # ------------------------------
1347 # "req_checked" "req_unchecked"
1348 # CHECKED flag 0 flag Abnormal Mode
1349 # void_cookie req_cookie
1350 # ------------------------------
1353 # Whether we are _checked or _unchecked
1354 checked = void and not regular
1355 unchecked = not void and not regular
1357 # What kind of cookie we return
1358 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1360 # What flag is passed to xcb_request
1361 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1363 # Global extension id variable or NULL for xproto
1364 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1366 # What our function name is
1367 func_name = self.c_request_name if not aux else self.c_aux_name
1369 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1371 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1375 maxtypelen = len('xcb_connection_t')
1378 for field in self.fields:
1380 # The field should appear as a call parameter
1381 param_fields.append(field)
1382 if field.wire and not field.auto:
1383 # We need to set the field up in the structure
1384 wire_fields.append(field)
1385 if field.type.need_serialize:
1386 serial_fields.append(field)
1388 for field in param_fields:
1389 c_field_const_type = field.c_field_const_type
1390 if field.type.need_serialize and not aux:
1391 c_field_const_type = "const void"
1392 if len(c_field_const_type) > maxtypelen:
1393 maxtypelen = len(c_field_const_type)
1399 _h(' * Delivers a request to the X server')
1400 _h(' * @param c The connection')
1401 _h(' * @return A cookie')
1403 _h(' * Delivers a request to the X server.')
1406 _h(' * This form can be used only if the request will not cause')
1407 _h(' * a reply to be generated. Any returned error will be')
1408 _h(' * saved for handling by xcb_request_check().')
1410 _h(' * This form can be used only if the request will cause')
1411 _h(' * a reply to be generated. Any returned error will be')
1412 _h(' * placed in the event queue.')
1416 _hc('/*****************************************************************************')
1418 _hc(' ** %s %s', cookie_type, func_name)
1421 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1422 _hc(' ** @param xcb_connection_t%s *c', spacing)
1424 for field in param_fields:
1425 c_field_const_type = field.c_field_const_type
1426 if field.type.need_serialize and not aux:
1427 c_field_const_type = "const void"
1428 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1429 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1431 _hc(' ** @returns %s', cookie_type)
1433 _hc(' *****************************************************************************/')
1435 _hc('%s', cookie_type)
1437 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1438 comma = ',' if len(param_fields) else ');'
1439 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1440 comma = ',' if len(param_fields) else ')'
1441 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1443 func_spacing = ' ' * (len(func_name) + 2)
1444 count = len(param_fields)
1445 for field in param_fields:
1447 c_field_const_type = field.c_field_const_type
1448 if field.type.need_serialize and not aux:
1449 c_field_const_type = "const void"
1450 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1451 comma = ',' if count else ');'
1452 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1453 spacing, field.c_pointer, field.c_field_name, comma)
1454 comma = ',' if count else ')'
1455 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1456 spacing, field.c_pointer, field.c_field_name, comma)
1459 for field in param_fields:
1460 if not field.type.fixed_size():
1462 if field.type.need_serialize:
1463 # _serialize() keeps track of padding automatically
1467 _c(' static const xcb_protocol_request_t xcb_req = {')
1468 _c(' /* count */ %d,', count)
1469 _c(' /* ext */ %s,', func_ext_global)
1470 _c(' /* opcode */ %s,', self.c_request_name.upper())
1471 _c(' /* isvoid */ %d', 1 if void else 0)
1475 _c(' struct iovec xcb_parts[%d];', count + 2)
1476 _c(' %s xcb_ret;', func_cookie)
1477 _c(' %s xcb_out;', self.c_type)
1478 for idx, f in enumerate(serial_fields):
1480 _c(' %s xcb_aux%d;' % (f.type.c_type, idx))
1482 _c(' printf("in function %s\\n");' % func_name)
1485 for field in wire_fields:
1486 if field.type.fixed_size():
1487 if field.type.is_expr:
1488 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr))
1489 elif field.type.is_pad:
1490 if field.type.nmemb == 1:
1491 _c(' xcb_out.%s = 0;', field.c_field_name)
1493 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
1495 if field.type.nmemb == 1:
1496 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
1498 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
1501 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
1502 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
1503 _c(' xcb_parts[3].iov_base = 0;')
1504 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
1506 # calls in order to free dyn. all. memory
1509 for field in param_fields:
1510 if not field.type.fixed_size():
1511 if not field.type.need_serialize:
1512 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1515 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1517 _c(' xcb_parts[%d].iov_base = (char *) 0;', count)
1518 idx = serial_fields.index(field)
1520 serialize_args = get_serialize_params(field.type,
1522 '&xcb_aux%d' % idx)[2]
1524 serialize_args = get_serialize_params(field.type,
1525 '&xcb_parts[%d].iov_base' % count,
1526 field.c_field_name)[2]
1528 serialize_args = reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
1529 _c(' xcb_parts[%d].iov_len = ', count)
1531 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
1532 free_calls.append(' free(xcb_parts[%d].iov_base);' % count)
1534 _c(' %s (%s);', field.type.c_unserialize_name, serialize_args)
1535 if field.type.is_list:
1536 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
1537 _c_accessor_get_expr(field.type.expr), field.type.member.c_wiretype)
1538 elif not field.type.need_serialize:
1539 # FIXME - _serialize()
1540 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);',
1541 count, 'Uh oh', field.type.c_wiretype)
1544 if not field.type.need_serialize:
1545 # the _serialize() function keeps track of padding automatically
1546 _c(' xcb_parts[%d].iov_base = 0;', count)
1547 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
1551 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
1553 # free dyn. all. data, if any
1554 for f in free_calls:
1556 _c(' return xcb_ret;')
1559 def _c_reply(self, name):
1561 Declares the function that returns the reply structure.
1563 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
1564 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
1565 spacing3 = ' ' * (len(self.c_reply_name) + 2)
1569 _h(' * Return the reply')
1570 _h(' * @param c The connection')
1571 _h(' * @param cookie The cookie')
1572 _h(' * @param e The xcb_generic_error_t supplied')
1574 _h(' * Returns the reply of the request asked by')
1576 _h(' * The parameter @p e supplied to this function must be NULL if')
1577 _h(' * %s(). is used.', self.c_unchecked_name)
1578 _h(' * Otherwise, it stores the error if any.')
1580 _h(' * The returned value must be freed by the caller using free().')
1584 _hc('/*****************************************************************************')
1586 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
1588 _hc(' ** @param xcb_connection_t%s *c', spacing1)
1589 _hc(' ** @param %s cookie', self.c_cookie_type)
1590 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
1591 _hc(' ** @returns %s *', self.c_reply_type)
1593 _hc(' *****************************************************************************/')
1595 _hc('%s *', self.c_reply_type)
1596 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
1597 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
1598 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
1599 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
1601 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
1604 def _c_opcode(name, opcode):
1606 Declares the opcode define for requests, events, and errors.
1610 _h('/** Opcode for %s. */', _n(name))
1611 _h('#define %s %s', _n(name).upper(), opcode)
1613 def _c_cookie(self, name):
1615 Declares the cookie type for a non-void request.
1620 _h(' * @brief %s', self.c_cookie_type)
1622 _h('typedef struct %s {', self.c_cookie_type)
1623 _h(' unsigned int sequence; /**< */')
1624 _h('} %s;', self.c_cookie_type)
1626 def c_request(self, name):
1628 Exported function that handles request declarations.
1630 _c_type_setup(self, name, ('request',))
1633 # Cookie type declaration
1634 _c_cookie(self, name)
1637 _c_opcode(name, self.opcode)
1639 # Request structure declaration
1643 _c_type_setup(self.reply, name, ('reply',))
1644 # Reply structure definition
1645 _c_complex(self.reply)
1646 # Request prototypes
1647 _c_request_helper(self, name, self.c_cookie_type, False, True)
1648 _c_request_helper(self, name, self.c_cookie_type, False, False)
1650 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
1651 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
1653 _c_accessors(self.reply, name + ('reply',), name)
1654 _c_reply(self, name)
1656 # Request prototypes
1657 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
1658 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
1660 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
1661 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
1664 def c_event(self, name):
1666 Exported function that handles event declarations.
1668 _c_type_setup(self, name, ('event',))
1671 _c_opcode(name, self.opcodes[name])
1673 if self.name == name:
1674 # Structure definition
1679 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
1681 def c_error(self, name):
1683 Exported function that handles error declarations.
1685 _c_type_setup(self, name, ('error',))
1688 _c_opcode(name, self.opcodes[name])
1690 if self.name == name:
1691 # Structure definition
1696 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
1699 # Main routine starts here
1701 # Must create an "output" dictionary before any xcbgen imports.
1702 output = {'open' : c_open,
1704 'simple' : c_simple,
1706 'struct' : c_struct,
1708 'request' : c_request,
1713 # Boilerplate below this point
1715 # Check for the argument that specifies path to the xcbgen python package.
1717 opts, args = getopt.getopt(sys.argv[1:], 'p:')
1718 except getopt.GetoptError, err:
1720 print 'Usage: c_client.py [-p path] file.xml'
1723 for (opt, arg) in opts:
1725 sys.path.append(arg)
1727 # Import the module class
1729 from xcbgen.state import Module
1732 print 'Failed to load the xcbgen Python package!'
1733 print 'Make sure that xcb/proto installed it on your Python path.'
1734 print 'If not, you will need to create a .pth file or define $PYTHONPATH'
1735 print 'to extend the path.'
1736 print 'Refer to the README file in xcb/proto for more info.'
1740 # Parse the xml header
1741 module = Module(args[0], output)
1743 # Build type-registry and resolve type dependencies