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',
28 Writes the given line to the header file.
30 _hlines[_hlevel].append(fmt % args)
34 Writes the given line to the source file.
36 _clines[_clevel].append(fmt % args)
40 Writes the given line to both the header and source files.
45 # XXX See if this level thing is really necessary.
48 Changes the array that header lines are written to.
49 Supports writing different sections of the header file.
52 while len(_hlines) <= idx:
58 Changes the array that source lines are written to.
59 Supports writing to different sections of the source file.
62 while len(_clines) <= idx:
68 Does C-name conversion on a single string fragment.
69 Uses a regexp with some hard-coded special cases.
71 if str in _cname_special_cases:
72 return _cname_special_cases[str]
74 split = _cname_re.finditer(str)
75 name_parts = [match.group(0) for match in split]
76 return '_'.join(name_parts)
80 Checks for certain C++ reserved words and fixes them.
82 if str in _cplusplus_annoyances:
83 return _cplusplus_annoyances[str]
89 Does C-name conversion on an extension name.
90 Has some additional special cases on top of _n_item.
92 if str in _extension_special_cases:
93 return _n_item(str).lower()
99 Does C-name conversion on a tuple of strings.
100 Different behavior depending on length of tuple, extension/not extension, etc.
101 Basically C-name converts the individual pieces, then joins with underscores.
106 parts = [list[0], _n_item(list[1])]
108 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]]
110 parts = [list[0]] + [_n_item(i) for i in list[1:]]
111 return '_'.join(parts).lower()
115 Does C-name conversion on a tuple of strings representing a type.
116 Same as _n but adds a "_t" on the end.
121 parts = [list[0], _n_item(list[1]), 't']
123 parts = [list[0], _ext(list[1])] + [_n_item(i) for i in list[2:]] + ['t']
125 parts = [list[0]] + [_n_item(i) for i in list[1:]] + ['t']
126 return '_'.join(parts).lower()
131 Exported function that handles module open.
132 Opens the files and writes out the auto-generated comment, header file includes, etc.
136 _ns.c_ext_global_name = _n(_ns.prefix + ('id',))
138 # Build the type-name collision avoidance table used by c_enum
139 build_collision_table()
145 _hc(' * This file generated automatically from %s by c_client.py.', _ns.file)
146 _hc(' * Edit at your peril.')
151 _h(' * @defgroup XCB_%s_API XCB %s API', _ns.ext_name, _ns.ext_name)
152 _h(' * @brief %s XCB Protocol Implementation.', _ns.ext_name)
156 _h('#ifndef __%s_H', _ns.header.upper())
157 _h('#define __%s_H', _ns.header.upper())
159 _h('#include "xcb.h"')
161 _c('#include <string.h>')
162 _c('#include <assert.h>')
163 _c('#include "xcbext.h"')
164 _c('#include "%s.h"', _ns.header)
167 for (n, h) in self.imports:
168 _hc('#include "%s.h"', h)
171 _h('#ifdef __cplusplus')
177 _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version)
178 _h('#define XCB_%s_MINOR_VERSION %s', _ns.ext_name.upper(), _ns.minor_version)
180 _h('extern xcb_extension_t %s;', _ns.c_ext_global_name)
183 _c('xcb_extension_t %s = { "%s", 0 };', _ns.c_ext_global_name, _ns.ext_xname)
187 Exported function that handles module close.
188 Writes out all the stored content lines, then closes the files.
195 _h('#ifdef __cplusplus')
207 hfile = open('%s.h' % _ns.header, 'w')
215 cfile = open('%s.c' % _ns.header, 'w')
222 def build_collision_table():
226 for v in module.types.values():
228 namecount[name] = (namecount.get(name) or 0) + 1
230 def c_enum(self, name):
232 Exported function that handles enum declarations.
236 if namecount[tname] > 1:
237 tname = _t(name + ('enum',))
241 _h('typedef enum %s {', tname)
243 count = len(self.values)
245 for (enam, eval) in self.values:
247 equals = ' = ' if eval != '' else ''
248 comma = ',' if count > 0 else ''
249 _h(' %s%s%s%s', _n(name + (enam,)).upper(), equals, eval, comma)
253 def _c_type_setup(self, name, postfix):
255 Sets up all the C-related state by adding additional data fields to
256 all Field and Type objects. Here is where we figure out most of our
257 variable and function names.
259 Recurses into child fields and list member types.
261 # Do all the various names in advance
262 self.c_type = _t(name + postfix)
263 self.c_wiretype = 'char' if self.c_type == 'void' else self.c_type
265 self.c_iterator_type = _t(name + ('iterator',))
266 self.c_next_name = _n(name + ('next',))
267 self.c_end_name = _n(name + ('end',))
269 self.c_request_name = _n(name)
270 self.c_checked_name = _n(name + ('checked',))
271 self.c_unchecked_name = _n(name + ('unchecked',))
272 self.c_reply_name = _n(name + ('reply',))
273 self.c_reply_type = _t(name + ('reply',))
274 self.c_cookie_type = _t(name + ('cookie',))
276 self.c_aux_name = _n(name + ('aux',))
277 self.c_aux_checked_name = _n(name + ('aux', 'checked'))
278 self.c_aux_unchecked_name = _n(name + ('aux', 'unchecked'))
279 self.c_serialize_name = _n(name + ('serialize',))
280 self.c_unserialize_name = _n(name + ('unserialize',))
282 # whether a request or reply has a switch field
283 self.need_aux = False
284 self.need_serialize = False
286 self.need_serialize = True
287 for bitcase in self.bitcases:
288 _c_type_setup(bitcase.type, bitcase.field_type, ())
290 if self.is_container:
292 self.c_container = 'union' if self.is_union else 'struct'
293 prev_varsized_field = None
294 prev_varsized_offset = 0
295 first_field_after_varsized = None
297 for field in self.fields:
298 # information about a fields anchestors
299 if self.is_reply or hasattr(self, 'in_reply'):
300 field.type.in_reply = True
302 _c_type_setup(field.type, field.field_type, ())
303 if field.type.is_list:
304 _c_type_setup(field.type.member, field.field_type, ())
306 field.c_field_type = _t(field.field_type)
307 field.c_field_const_type = ('' if field.type.nmemb == 1 else 'const ') + field.c_field_type
308 field.c_field_name = _cpp(field.field_name)
309 field.c_subscript = '[%d]' % field.type.nmemb if (field.type.nmemb > 1) else ''
310 field.c_pointer = ' ' if field.type.nmemb == 1 else '*'
311 if field.type.is_switch:
312 field.c_pointer = '*'
313 field.c_field_const_type = 'const ' + field.c_field_type
316 field.c_iterator_type = _t(field.field_type + ('iterator',)) # xcb_fieldtype_iterator_t
317 field.c_iterator_name = _n(name + (field.field_name, 'iterator')) # xcb_container_field_iterator
318 field.c_accessor_name = _n(name + (field.field_name,)) # xcb_container_field
319 field.c_length_name = _n(name + (field.field_name, 'length')) # xcb_container_field_length
320 field.c_end_name = _n(name + (field.field_name, 'end')) # xcb_container_field_end
322 field.prev_varsized_field = prev_varsized_field
323 field.prev_varsized_offset = prev_varsized_offset
325 if prev_varsized_offset == 0:
326 first_field_after_varsized = field
327 field.first_field_after_varsized = first_field_after_varsized
329 if field.type.fixed_size():
330 prev_varsized_offset += field.type.size
332 self.last_varsized_field = field
333 prev_varsized_field = field
334 prev_varsized_offset = 0
336 # FIXME - structures with variable sized members, sort out when serialize() is needed
338 # as switch does never appear at toplevel,
339 # continue here with type construction
341 # special: switch C structs get pointer fields for variable-sized members
343 # declare switch (un)packing functions
344 _c_accessors(self, name, name)
346 if self.need_serialize:
347 if not hasattr(self, 'in_reply'):
353 def get_request_fields(self):
357 for field in self.fields:
359 # the field should appear as a parameter in the function call
360 param_fields.append(field)
361 if field.wire and not field.auto:
362 if field.type.fixed_size() and not self.is_switch:
363 # need to set the field up in the xcb_out structure
364 wire_fields.append(field)
365 # fields like 'pad0' are skipped!
367 return (param_fields, wire_fields)
368 # get_request_fields()
370 def unserialize_fields(complex_type, code_lines=[], space='', prefix='', bitcase=False):
376 if hasattr(complex_type, 'type'):
377 self = complex_type.type
378 complex_name = complex_type.name
381 complex_name = '_aux'
384 switch_expr = _c_accessor_get_expr(self.expr)
386 for b in self.bitcases:
387 bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix)
388 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
389 unserialize_fields(b.type, code_lines, space="%s " % space,
390 prefix="%s%s" % (prefix_str, complex_name), bitcase=True)
391 code_lines.append(' }')
394 for field in self.fields:
395 if not ((field.wire and not field.auto) or field.visible):
398 length = "sizeof(%s)" % field.c_field_type
400 # 1. fields with fixed size
401 if field.type.fixed_size():
403 value = ' _aux->%s = (%s) *xcb_tmp;' % (field.c_field_name, field.type.c_type)
406 # 2. fields with variable size
409 # unserialize: always calculate padding before variable sized fields
410 code_lines.append('%s if (0 != xcb_block_len) {' % space)
411 code_lines.append('%s xcb_block_len += -xcb_block_len & 3;' % space)
412 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
413 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
414 code_lines.append('%s xcb_block_len = 0;' % space)
415 code_lines.append('%s }' % space)
418 print("unserialize not yet implemented for variable size fields like %s" % field.c_field_name)
420 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s%s;' % (prefix_str, field.c_field_name)
421 if field.type.is_list:
422 # FIXME - list with variable-sized elements
423 if field.type.size is None:
424 errmsg = '%s: warning: list object with variable-sized members not supported for field %s\n'
425 sys.stderr.write(errmsg % (self.c_type, field.c_field_name))
426 length = '%s * sizeof(%s)' % (_c_accessor_get_expr(field.type.expr, prefix), field.type.member.c_wiretype)
427 elif field.type.is_switch:
428 # switch is handled by this function as a special case
429 unserialize_fields(field.type, code_lines, space, prefix="%s%s" % (prefix_str, field.c_field_name))
431 # FIXME - variable sized field that is not a list
432 errmsg = '%s: warning: non-list object of variable size not supported for field %s\n'
433 sys.stderr.write(errmsg % (self.c_type, field.c_field_name))
434 length = '%s * sizeof(%s)' % ('Uh oh', field.type.c_wiretype)
436 # save serialization C code
437 if value is not None:
438 if field.type.fixed_size():
439 # field appears in the request structure
440 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
442 code_lines.append('%s /* %s */' % (space, field.c_field_name))
445 code_lines.append('%s%s' % (space, value))
446 if field.type.fixed_size():
447 code_lines.append('%s xcb_block_len += %s;' % (space, length))
448 code_lines.append('%s xcb_tmp += %s;' % (space, length))
450 # take account of padding
451 code_lines.append('%s xcb_block_len = %s;' % (space, length))
452 code_lines.append('%s xcb_block_len += -xcb_block_len & 3;' % space)
453 code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
454 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
455 code_lines.append('%s xcb_block_len = 0;' % space)
458 code_lines.append('%s xcb_block_len += -xcb_block_len & 3;' % space)
459 #code_lines.append('%s xcb_tmp += xcb_block_len;' % space)
460 code_lines.append('%s xcb_buffer_len += xcb_block_len;' % space)
462 # unserialize_fields()
465 def serialize_fields(complex_type, code_lines=[], temp_vars=set(),
466 space='', prefix='', serialize_fixed_size_fields=False,
469 helper routine to build up iovec arrays that will later be copied into a single buffer
471 complex_type - encapsulating Type/Field
472 code_lines, temp_vars - containers for generated code & variable declarations
473 space - extra space to be inserted before any statement
474 prefix - prefix to be used for struct members, needed for switch/bitcase mapping
475 bitcase - flags whether fields are bitcase members
478 # count -> no. of entries in xcb_parts array
480 # flag to mark wether explicit padding needs to be inserted
486 if hasattr(complex_type, 'type'):
487 self = complex_type.type
488 complex_name = complex_type.name
491 complex_name = '_aux'
493 def end_block(count):
494 "end a block => insert padding"
495 if need_padding and not bitcase:
496 code_lines.append(' /* padding */')
497 code_lines.append(' xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;')
498 code_lines.append(' xcb_pad = -xcb_block_len & 3;')
499 code_lines.append(' xcb_parts[xcb_parts_idx].iov_len = xcb_pad;')
500 code_lines.append(' xcb_parts_idx++;')
501 code_lines.append('')
502 code_lines.append(' xcb_buffer_len += xcb_pad + %s;' % 'xcb_block_len')
503 code_lines.append('')
508 def insert_padding(count):
509 code_lines.append('%s /* implicit padding */' % space)
510 code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space)
511 code_lines.append('%s if (0 != xcb_pad) {' % space)
512 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_base = xcb_pad0;' % space)
513 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = xcb_pad;' % space)
514 code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space)
515 code_lines.append('%s xcb_pad = 0;' % space)
516 code_lines.append('%s xcb_parts_idx++;' % space)
517 code_lines.append('%s }' % space)
521 # special case - if self.is_switch, all fields need to be serialized conditionally
523 switch_expr = _c_accessor_get_expr(self.expr)
526 for b in self.bitcases:
527 bitcase_expr = _c_accessor_get_expr(b.type.expr, prefix)
528 code_lines.append(' if(%s & %s) {' % (switch_expr, bitcase_expr))
530 count += serialize_fields(b.type, code_lines, temp_vars, '%s ' % space,
531 prefix="%s%s" % (prefix_str, complex_name),
532 serialize_fixed_size_fields=True, bitcase=True)
533 code_lines.append(' }')
536 for field in self.fields:
539 # sort out invisible fields
540 if not ((field.wire and not field.auto) or field.visible):
543 length = "sizeof(%s)" % field.c_field_type
545 # 1. fields with fixed size
546 # fixed size fields are not always handled here,
547 # dependent on serialize_fixed_size_fields
548 if field.type.fixed_size() and serialize_fixed_size_fields:
549 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) '
552 if field.type.is_expr:
553 # need to register a temporary variable for the expression
554 if field.type.c_type is None:
555 raise Exception("type for field '%s' (expression '%s') unkown" %
556 (field.field_name, _c_accessor_get_expr(field.type.expr)))
557 temp_vars.add(' %s xcb_expr_%s = %s;' % (field.type.c_type, field.field_name,
558 _c_accessor_get_expr(field.type.expr, prefix)))
559 value += "&xcb_expr_%s;" % field.field_name
561 elif field.type.is_pad:
562 if field.type.nmemb == 1:
563 temp_vars.add(' unsigned int xcb_pad = 0;')
564 temp_vars.add(' char xcb_pad0[3] = {0, 0, 0};')
567 value = ' memset(xcb_parts[xcb_parts_idx].iov_base, 0, %d);' % field.type.nmemb
568 length += "*%d" % field.type.nmemb
571 # non-list type with fixed size
572 if field.type.nmemb == 1:
573 value += "&%s%s;" % (prefix_str, field.c_field_name)
574 # list with nmemb (fixed size) elements
576 value += '%s%s;' % (prefix_str, field.c_field_name)
577 length = '%d' % field.type.nmemb
579 # 2. fields with variable size
580 elif not field.type.fixed_size():
581 # always calculate padding before variable sized fields
582 count = insert_padding(count)
583 code_lines.append('%s xcb_block_len = 0;' % space)
585 value = ' xcb_parts[xcb_parts_idx].iov_base = (char *) %s%s;' % (prefix_str, field.c_field_name)
587 if field.type.is_list:
588 # FIXME - list of variable length with variable size elements
589 if field.type.size is None:
590 errmsg = '%s: warning: list object with variable-sized members not supported for field %s\n'
591 sys.stderr.write(errmsg % (self.c_type, field.c_field_name))
593 # list of variable length with fixed size elements
595 length = '%s * sizeof(%s)' % (_c_accessor_get_expr(field.type.expr, prefix),
596 field.type.member.c_wiretype)
598 elif field.type.is_switch:
599 # switch is handled at the beginning of this function as a special case
600 count += serialize_fields(field.type, code_lines, temp_vars, space,
601 prefix="%s%s" % (prefix_str, field.c_field_name))
604 # FIXME - variable sized field that is not a list
605 errmsg = '%s: warning: non-list object of variable size not supported for field %s\n'
606 sys.stderr.write(errmsg % (self.c_type, field.c_field_name))
607 length = '%s * sizeof(%s)' % ('Uh oh', field.type.c_wiretype)
609 # 3. save serialization C code
610 if value is not None:
611 # insert a comment so one can easily trace back to the XML
612 if field.type.fixed_size():
613 # field belongs to some anchestor structure
614 code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
616 code_lines.append('%s /* %s */' % (space, field.c_field_name))
618 # set xcb_parts[].iov_base and xcb_parts[].iov_len
619 code_lines.append('%s%s' % (space, value))
620 code_lines.append('%s xcb_parts[xcb_parts_idx].iov_len = %s;' % (space, length))
621 # increase xcb_parts index
622 code_lines.append('%s xcb_parts_idx++;' % space)
625 # record required memory
626 if field.type.fixed_size():
627 code_lines.append('%s xcb_block_len += %s;' % (space, length))
630 count = insert_padding(count)
631 # raise Exception("obsolete - should not be reached")
632 # code_lines.append('%s xcb_unpadded = xcb_parts[xcb_parts_idx].iov_len;' % space)
634 count = end_block(count)
636 temp_vars.add(' unsigned int xcb_parts_idx = 0;')
637 temp_vars.add(' unsigned int xcb_block_len = 0;')
639 temp_vars.add(' unsigned int xcb_pad = 0;')
640 temp_vars.add(' char xcb_pad0[3] = {0, 0, 0};')
644 def _c_switch_aux_params(self):
645 # get the fields referenced by the switch expression
646 def get_expr_fields(expr):
648 if expr.lenfield_name is not None:
649 return [expr.lenfield_name]
652 return get_expr_fields(expr.rhs)
653 elif expr.op == 'popcount':
654 return get_expr_fields(expr.rhs)
655 elif expr.op == 'sumof':
656 return [expr.lenfield_name]
657 elif expr.op == 'enumref':
660 return get_expr_fields(expr.lhs) + get_expr_fields(expr.rhs)
663 # resolve the field names with the parent structure(s)
664 unresolved_fields = get_expr_fields(self.expr)
665 expr_fields = dict.fromkeys(unresolved_fields)
666 for p in reversed(self.parent):
667 parent_fields = dict((f.field_name, f) for f in p.fields)
668 if len(unresolved_fields) == 0:
670 for f in parent_fields.keys():
671 if f in unresolved_fields:
672 expr_fields[f] = parent_fields[f]
673 unresolved_fields.remove(f)
675 if None in expr_fields.values():
676 raise Exception("could not resolve all fields for <switch> %s" % self.name)
679 for name, field in expr_fields.iteritems():
680 params.append((field, name))
683 # _c_switch_aux_params()
685 def get_serialize_params(self, buffer_var='_buffer', aux_var='_aux', unserialize=False):
686 param_fields, wire_fields = get_request_fields(self)
688 switch_params = _c_switch_aux_params(self)
689 param_fields += [s[0] for s in switch_params]
691 # _serialize function parameters
692 params = [('void', '**', buffer_var)]
693 # parameter fields if any
695 for p in switch_params:
696 typespec = p[0].c_field_const_type
697 pointerspec = p[0].c_pointer
698 params.append((typespec, pointerspec, p[0].c_field_name))
699 # aux argument - structure to be serialized
701 params.append(('const %s' % self.c_type, '*', aux_var))
703 params.append(('%s' % self.c_type, '*', aux_var))
704 if not self.is_switch:
705 for p in param_fields:
706 if not p.type.fixed_size():
707 params.append((p.c_field_const_type, p.c_pointer, p.c_field_name))
708 return (param_fields, wire_fields, params)
709 # get_serialize_params()
711 def _c_serialize(self):
716 # _serialize() returns the buffer size
719 variable_size_fields = 0
720 # maximum space required for type definition of function arguments
722 param_fields, wire_fields, params = get_serialize_params(self)
724 # determine N(variable_fields)
725 for field in param_fields:
726 # if self.is_switch, treat all fields as if they are variable sized
727 if not field.type.fixed_size() or self.is_switch:
728 variable_size_fields += 1
729 # determine maxtypelen
731 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
734 for p in range(len(params)):
736 typespec, pointerspec, field_name = params[p]
737 indent = ' '*(len(self.c_serialize_name)+2)
738 # p==0: function declaration
740 line = "%s (" % self.c_serialize_name
742 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
743 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
744 if p < len(params)-1:
751 if not self.is_switch:
752 _c(' %s *xcb_out = *_buffer;', self.c_type)
753 _c(' unsigned int xcb_buffer_len = sizeof(%s);', self.c_type)
755 _c(' char *xcb_out = *_buffer;')
756 _c(' unsigned int xcb_buffer_len = 0;')
757 if variable_size_fields > 0:
760 count = serialize_fields(self, code_lines, temp_vars,
761 serialize_fixed_size_fields=False)
762 # update variable size fields
763 variable_size_fields = count
764 _c(' struct iovec xcb_parts[%d];', count)
767 _c(' char *xcb_tmp;')
768 _c(' unsigned int i;')
769 if not self.is_switch:
770 _c(' unsigned int xcb_out_pad = -xcb_buffer_len & 3;')
771 _c(' /* add size of padding */')
772 _c(' xcb_buffer_len += xcb_out_pad;')
776 if variable_size_fields > 0:
780 # variable sized fields have been collected, now
781 # allocate memory and copy everything into a continuous memory area
782 _c(' if (NULL == xcb_out) {')
783 _c(' /* allocate memory */')
784 _c(' *_buffer = malloc(xcb_buffer_len);')
785 _c(' xcb_out = *_buffer;')
789 # fill in struct members
790 if not self.is_switch:
791 if len(wire_fields)>0:
792 _c(' *xcb_out = *_aux;')
794 # copy variable size fields into the buffer
795 if variable_size_fields > 0:
797 if not self.is_switch:
798 _c(' xcb_tmp = (char*)++xcb_out;')
799 _c(' xcb_tmp += xcb_out_pad;')
801 _c(' xcb_tmp = xcb_out;')
803 # variable sized fields
804 _c(' for(i=0; i<xcb_parts_idx; i++) {')
805 # _c(' if (0 != xcb_parts[i].iov_base) {')
806 _c(' memcpy(xcb_tmp, xcb_parts[i].iov_base, xcb_parts[i].iov_len);')
808 _c(' xcb_tmp += xcb_parts[i].iov_len;')
811 _c(' return xcb_buffer_len;')
815 def _c_unserialize(self):
821 # _unserialize() returns the buffer size as well
825 variable_size_fields = 0
826 # maximum space required for type definition of function arguments
828 param_fields, wire_fields, params = get_serialize_params(self, unserialize=True)
830 # determine N(variable_fields)
831 for field in param_fields:
832 # if self.is_switch, treat all fields as if they are variable sized
833 if not field.type.fixed_size() or self.is_switch:
834 variable_size_fields += 1
835 # determine maxtypelen
837 maxtypelen = max(maxtypelen, len(p[0]) + len(p[1]))
840 for p in range(len(params)):
842 typespec, pointerspec, field_name = params[p]
843 indent = ' '*(len(self.c_unserialize_name)+2)
844 # p==0: function declaration
846 line = "%s (" % self.c_unserialize_name
849 spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
850 line += "%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name)
851 if p < len(params)-1:
858 _c(' char *xcb_tmp = _buffer;')
859 _c(' unsigned int xcb_buffer_len = 0;')
860 _c(' unsigned int xcb_block_len = 0;')
863 unserialize_fields(self, code_lines)
867 _c(' return xcb_buffer_len;')
871 def _c_iterator_get_end(field, accum):
873 Figures out what C code is needed to find the end of a variable-length structure field.
874 For nested structures, recurses into its last variable-sized field.
875 For lists, calls the end function
877 if field.type.is_container:
878 accum = field.c_accessor_name + '(' + accum + ')'
879 # XXX there could be fixed-length fields at the end
880 return _c_iterator_get_end(field.type.last_varsized_field, accum)
881 if field.type.is_list:
882 # XXX we can always use the first way
883 if field.type.member.is_simple:
884 return field.c_end_name + '(' + accum + ')'
886 return field.type.member.c_end_name + '(' + field.c_iterator_name + '(' + accum + '))'
888 def _c_iterator(self, name):
890 Declares the iterator structure and next/end functions for a given type.
895 _h(' * @brief %s', self.c_iterator_type)
897 _h('typedef struct %s {', self.c_iterator_type)
898 _h(' %s *data; /**< */', self.c_type)
899 _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
900 _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
901 _h('} %s;', self.c_iterator_type)
907 _h(' * Get the next element of the iterator')
908 _h(' * @param i Pointer to a %s', self.c_iterator_type)
910 _h(' * Get the next element in the iterator. The member rem is')
911 _h(' * decreased by one. The member data points to the next')
912 _h(' * element. The member index is increased by sizeof(%s)', self.c_type)
916 _hc('/*****************************************************************************')
918 _hc(' ** void %s', self.c_next_name)
920 _hc(' ** @param %s *i', self.c_iterator_type)
921 _hc(' ** @returns void')
923 _hc(' *****************************************************************************/')
926 _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
927 _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
930 if not self.fixed_size():
931 _c(' %s *R = i->data;', self.c_type)
932 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(self.last_varsized_field, 'R'))
934 _c(' i->data = (%s *) child.data;', self.c_type)
935 _c(' i->index = child.index;')
939 _c(' i->index += sizeof(%s);', self.c_type)
945 _h(' * Return the iterator pointing to the last element')
946 _h(' * @param i An %s', self.c_iterator_type)
947 _h(' * @return The iterator pointing to the last element')
949 _h(' * Set the current element in the iterator to the last element.')
950 _h(' * The member rem is set to 0. The member data points to the')
951 _h(' * last element.')
955 _hc('/*****************************************************************************')
957 _hc(' ** xcb_generic_iterator_t %s', self.c_end_name)
959 _hc(' ** @param %s i', self.c_iterator_type)
960 _hc(' ** @returns xcb_generic_iterator_t')
962 _hc(' *****************************************************************************/')
964 _hc('xcb_generic_iterator_t')
965 _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
966 _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
968 _c(' xcb_generic_iterator_t ret;')
970 if self.fixed_size():
971 _c(' ret.data = i.data + i.rem;')
972 _c(' ret.index = i.index + ((char *) ret.data - (char *) i.data);')
975 _c(' while(i.rem > 0)')
976 _c(' %s(&i);', self.c_next_name)
977 _c(' ret.data = i.data;')
978 _c(' ret.rem = i.rem;')
979 _c(' ret.index = i.index;')
984 def _c_accessor_get_length(expr, prefix=''):
986 Figures out what C code is needed to get a length field.
987 For fields that follow a variable-length field, use the accessor.
988 Otherwise, just reference the structure field directly.
990 prefarrow = '' if prefix == '' else prefix + '->'
992 if expr.lenfield != None and expr.lenfield.prev_varsized_field != None:
993 return expr.lenfield.c_accessor_name + '(' + prefix + ')'
994 elif expr.lenfield_name != None:
995 return prefarrow + expr.lenfield_name
997 return str(expr.nmemb)
999 def _c_accessor_get_expr(expr, prefix=''):
1001 Figures out what C code is needed to get the length of a list field.
1002 Recurses for math operations.
1003 Returns bitcount for value-mask fields.
1004 Otherwise, uses the value of the length field.
1006 lenexp = _c_accessor_get_length(expr, prefix)
1009 return '(' + '~' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1010 elif expr.op == 'popcount':
1011 return 'xcb_popcount(' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1012 elif expr.op == 'enumref':
1013 enum_name = expr.lenfield_type.name
1014 constant_name = expr.lenfield_name
1015 c_name = _n(enum_name + (constant_name,)).upper()
1017 elif expr.op == 'sumof':
1018 # 1. locate the referenced list object
1019 list_obj = expr.lenfield_type
1021 for f in expr.lenfield_parent.fields:
1022 if f.field_name == expr.lenfield_name:
1026 raise Exception("list field '%s' referenced by sumof not found" % expr.lenfield_name)
1028 prefix = "%s->" % prefix
1029 list_name = "%s%s" % (prefix, field.c_field_name)
1030 c_length_func = "%s(%s%s)" % (field.c_length_name, prefix, field.c_field_name)
1031 return 'xcb_sumof(%s, %s)' % (list_name, c_length_func)
1032 elif expr.op != None:
1033 return '(' + _c_accessor_get_expr(expr.lhs, prefix) + ' ' + expr.op + ' ' + _c_accessor_get_expr(expr.rhs, prefix) + ')'
1035 return 'xcb_popcount(' + lenexp + ')'
1039 def _c_accessors_field(self, field):
1041 Declares the accessor functions for a non-list field that follows a variable-length field.
1043 if field.type.is_simple:
1046 _hc('/*****************************************************************************')
1048 _hc(' ** %s %s', field.c_field_type, field.c_accessor_name)
1050 _hc(' ** @param const %s *R', self.c_type)
1051 _hc(' ** @returns %s', field.c_field_type)
1053 _hc(' *****************************************************************************/')
1055 _hc('%s', field.c_field_type)
1056 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1057 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1059 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1060 _c(' return * (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index) + %d);',
1061 field.c_field_type, field.first_field_after_varsized.type.c_type, field.prev_varsized_offset)
1066 _hc('/*****************************************************************************')
1068 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1070 _hc(' ** @param const %s *R', self.c_type)
1071 _hc(' ** @returns %s *', field.c_field_type)
1073 _hc(' *****************************************************************************/')
1075 _hc('%s *', field.c_field_type)
1076 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1077 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1079 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1080 _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)
1083 def _c_accessors_list(self, field):
1085 Declares the accessor functions for a list field.
1086 Declares a direct-accessor function only if the list members are fixed size.
1087 Declares length and get-iterator functions always.
1093 if list.member.fixed_size():
1096 _hc('/*****************************************************************************')
1098 _hc(' ** %s * %s', field.c_field_type, field.c_accessor_name)
1100 _hc(' ** @param const %s *R', self.c_type)
1101 _hc(' ** @returns %s *', field.c_field_type)
1103 _hc(' *****************************************************************************/')
1105 _hc('%s *', field.c_field_type)
1106 _h('%s (const %s *R /**< */);', field.c_accessor_name, self.c_type)
1107 _c('%s (const %s *R /**< */)', field.c_accessor_name, self.c_type)
1110 if field.prev_varsized_field == None:
1111 _c(' return (%s *) (R + 1);', field.c_field_type)
1113 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1114 _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)
1120 _hc('/*****************************************************************************')
1122 _hc(' ** int %s', field.c_length_name)
1124 _hc(' ** @param const %s *R', self.c_type)
1125 _hc(' ** @returns int')
1127 _hc(' *****************************************************************************/')
1130 _h('%s (const %s *R /**< */);', field.c_length_name, self.c_type)
1131 _c('%s (const %s *R /**< */)', field.c_length_name, self.c_type)
1133 _c(' return %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1136 if field.type.member.is_simple:
1139 _hc('/*****************************************************************************')
1141 _hc(' ** xcb_generic_iterator_t %s', field.c_end_name)
1143 _hc(' ** @param const %s *R', self.c_type)
1144 _hc(' ** @returns xcb_generic_iterator_t')
1146 _hc(' *****************************************************************************/')
1148 _hc('xcb_generic_iterator_t')
1149 _h('%s (const %s *R /**< */);', field.c_end_name, self.c_type)
1150 _c('%s (const %s *R /**< */)', field.c_end_name, self.c_type)
1152 _c(' xcb_generic_iterator_t i;')
1154 if field.prev_varsized_field == None:
1155 _c(' i.data = ((%s *) (R + 1)) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1157 _c(' xcb_generic_iterator_t child = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1158 _c(' i.data = ((%s *) child.data) + (%s);', field.type.c_wiretype, _c_accessor_get_expr(field.type.expr, 'R'))
1161 _c(' i.index = (char *) i.data - (char *) R;')
1168 _hc('/*****************************************************************************')
1170 _hc(' ** %s %s', field.c_iterator_type, field.c_iterator_name)
1172 _hc(' ** @param const %s *R', self.c_type)
1173 _hc(' ** @returns %s', field.c_iterator_type)
1175 _hc(' *****************************************************************************/')
1177 _hc('%s', field.c_iterator_type)
1178 _h('%s (const %s *R /**< */);', field.c_iterator_name, self.c_type)
1179 _c('%s (const %s *R /**< */)', field.c_iterator_name, self.c_type)
1181 _c(' %s i;', field.c_iterator_type)
1183 if field.prev_varsized_field == None:
1184 _c(' i.data = (%s *) (R + 1);', field.c_field_type)
1186 _c(' xcb_generic_iterator_t prev = %s;', _c_iterator_get_end(field.prev_varsized_field, 'R'))
1187 _c(' i.data = (%s *) ((char *) prev.data + XCB_TYPE_PAD(%s, prev.index));', field.c_field_type, field.c_field_type)
1189 _c(' i.rem = %s;', _c_accessor_get_expr(field.type.expr, 'R'))
1190 _c(' i.index = (char *) i.data - (char *) R;')
1194 def _c_accessors(self, name, base):
1196 Declares the accessor functions for the fields of a structure.
1198 for field in self.fields:
1199 if field.type.is_list and not field.type.fixed_size():
1200 _c_accessors_list(self, field)
1201 elif field.prev_varsized_field != None:
1202 _c_accessors_field(self, field)
1204 def c_simple(self, name):
1206 Exported function that handles cardinal type declarations.
1207 These are types which are typedef'd to one of the CARDx's, char, float, etc.
1209 _c_type_setup(self, name, ())
1211 if (self.name != name):
1216 _h('typedef %s %s;', _t(self.name), my_name)
1219 _c_iterator(self, name)
1221 def _c_complex(self):
1223 Helper function for handling all structure types.
1224 Called for all structs, requests, replies, events, errors.
1229 _h(' * @brief %s', self.c_type)
1231 _h('typedef %s %s {', self.c_container, self.c_type)
1237 for field in self.fields:
1238 if not field.type.fixed_size() and not self.is_switch:
1239 varfield = field.c_field_name
1241 if varfield != None and not field.type.is_pad and field.wire:
1242 errmsg = '%s: warning: variable field %s followed by fixed field %s\n' % (self.c_type, varfield, field.c_field_name)
1243 sys.stderr.write(errmsg)
1246 struct_fields.append(field)
1248 for field in struct_fields:
1249 length = len(field.c_field_type)
1250 if field.type.fixed_size():
1252 if length > maxtypelen:
1255 for field in struct_fields:
1256 if field.type.fixed_size():
1257 spacing = ' ' * (maxtypelen - len(field.c_field_type))
1258 _h(' %s%s %s%s; /**< */', field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1260 spacing = ' ' * (maxtypelen - (len(field.c_field_type) - 1))
1261 _h(' %s%s *%s%s; /**< */', field.c_field_type, spacing, field.c_field_name, field.c_subscript)
1263 _h('} %s;', self.c_type)
1265 def c_struct(self, name):
1267 Exported function that handles structure declarations.
1269 _c_type_setup(self, name, ())
1271 _c_accessors(self, name, name)
1272 _c_iterator(self, name)
1274 def c_union(self, name):
1276 Exported function that handles union declarations.
1278 _c_type_setup(self, name, ())
1280 _c_iterator(self, name)
1282 def _c_request_helper(self, name, cookie_type, void, regular, aux=False):
1284 Declares a request function.
1287 # Four stunningly confusing possibilities here:
1290 # ------------------------------
1292 # 0 flag CHECKED flag Normal Mode
1293 # void_cookie req_cookie
1294 # ------------------------------
1295 # "req_checked" "req_unchecked"
1296 # CHECKED flag 0 flag Abnormal Mode
1297 # void_cookie req_cookie
1298 # ------------------------------
1301 # Whether we are _checked or _unchecked
1302 checked = void and not regular
1303 unchecked = not void and not regular
1305 # What kind of cookie we return
1306 func_cookie = 'xcb_void_cookie_t' if void else self.c_cookie_type
1308 # What flag is passed to xcb_request
1309 func_flags = '0' if (void and regular) or (not void and not regular) else 'XCB_REQUEST_CHECKED'
1311 # Global extension id variable or NULL for xproto
1312 func_ext_global = '&' + _ns.c_ext_global_name if _ns.is_ext else '0'
1314 # What our function name is
1315 func_name = self.c_request_name if not aux else self.c_aux_name
1317 func_name = self.c_checked_name if not aux else self.c_aux_checked_name
1319 func_name = self.c_unchecked_name if not aux else self.c_aux_unchecked_name
1323 maxtypelen = len('xcb_connection_t')
1326 for field in self.fields:
1328 # The field should appear as a call parameter
1329 param_fields.append(field)
1330 if field.wire and not field.auto:
1331 # We need to set the field up in the structure
1332 wire_fields.append(field)
1333 if field.type.need_serialize:
1334 serial_fields.append(field)
1336 for field in param_fields:
1337 c_field_const_type = field.c_field_const_type
1338 if field.type.need_serialize and not aux:
1339 c_field_const_type = "const void"
1340 if len(c_field_const_type) > maxtypelen:
1341 maxtypelen = len(c_field_const_type)
1347 _h(' * Delivers a request to the X server')
1348 _h(' * @param c The connection')
1349 _h(' * @return A cookie')
1351 _h(' * Delivers a request to the X server.')
1354 _h(' * This form can be used only if the request will not cause')
1355 _h(' * a reply to be generated. Any returned error will be')
1356 _h(' * saved for handling by xcb_request_check().')
1358 _h(' * This form can be used only if the request will cause')
1359 _h(' * a reply to be generated. Any returned error will be')
1360 _h(' * placed in the event queue.')
1364 _hc('/*****************************************************************************')
1366 _hc(' ** %s %s', cookie_type, func_name)
1369 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1370 _hc(' ** @param xcb_connection_t%s *c', spacing)
1372 for field in param_fields:
1373 c_field_const_type = field.c_field_const_type
1374 if field.type.need_serialize and not aux:
1375 c_field_const_type = "const void"
1376 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1377 _hc(' ** @param %s%s %s%s', c_field_const_type, spacing, field.c_pointer, field.c_field_name)
1379 _hc(' ** @returns %s', cookie_type)
1381 _hc(' *****************************************************************************/')
1383 _hc('%s', cookie_type)
1385 spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
1386 comma = ',' if len(param_fields) else ');'
1387 _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1388 comma = ',' if len(param_fields) else ')'
1389 _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
1391 func_spacing = ' ' * (len(func_name) + 2)
1392 count = len(param_fields)
1393 for field in param_fields:
1395 c_field_const_type = field.c_field_const_type
1396 if field.type.need_serialize and not aux:
1397 c_field_const_type = "const void"
1398 spacing = ' ' * (maxtypelen - len(c_field_const_type))
1399 comma = ',' if count else ');'
1400 _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1401 spacing, field.c_pointer, field.c_field_name, comma)
1402 comma = ',' if count else ')'
1403 _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
1404 spacing, field.c_pointer, field.c_field_name, comma)
1407 for field in param_fields:
1408 if not field.type.fixed_size():
1410 if field.type.need_serialize:
1411 # _serialize() keeps track of padding automatically
1415 _c(' static const xcb_protocol_request_t xcb_req = {')
1416 _c(' /* count */ %d,', count)
1417 _c(' /* ext */ %s,', func_ext_global)
1418 _c(' /* opcode */ %s,', self.c_request_name.upper())
1419 _c(' /* isvoid */ %d', 1 if void else 0)
1423 _c(' struct iovec xcb_parts[%d];', count + 2)
1424 _c(' %s xcb_ret;', func_cookie)
1425 _c(' %s xcb_out;', self.c_type)
1426 for idx, f in enumerate(serial_fields):
1427 _c(' %s xcb_aux%d;', f.type.c_type, idx)
1429 _c(' printf("in function %s\\n");' % func_name)
1432 for field in wire_fields:
1433 if field.type.fixed_size():
1434 if field.type.is_expr:
1435 _c(' xcb_out.%s = %s;', field.c_field_name, _c_accessor_get_expr(field.type.expr))
1436 elif field.type.is_pad:
1437 if field.type.nmemb == 1:
1438 _c(' xcb_out.%s = 0;', field.c_field_name)
1440 _c(' memset(xcb_out.%s, 0, %d);', field.c_field_name, field.type.nmemb)
1442 if field.type.nmemb == 1:
1443 _c(' xcb_out.%s = %s;', field.c_field_name, field.c_field_name)
1445 _c(' memcpy(xcb_out.%s, %s, %d);', field.c_field_name, field.c_field_name, field.type.nmemb)
1448 _c(' xcb_parts[2].iov_base = (char *) &xcb_out;')
1449 _c(' xcb_parts[2].iov_len = sizeof(xcb_out);')
1450 _c(' xcb_parts[3].iov_base = 0;')
1451 _c(' xcb_parts[3].iov_len = -xcb_parts[2].iov_len & 3;')
1453 # calls in order to free dyn. all. memory
1456 for field in param_fields:
1457 if not field.type.fixed_size():
1458 _c(' xcb_parts[%d].iov_base = (char *) %s;', count, field.c_field_name)
1459 if field.type.need_serialize:
1460 idx = serial_fields.index(field)
1461 serialize_args = get_serialize_params(field.type,
1465 serialize_args = reduce(lambda x,y: "%s, %s" % (x,y), [a[2] for a in serialize_args])
1466 _c(' xcb_parts[%d].iov_len = ', count)
1468 _c(' %s (%s);', field.type.c_serialize_name, serialize_args)
1469 free_calls.append(' free(xcb_parts[%d].iov_base);' % count)
1471 _c(' %s (%s);', field.type.c_unserialize_name, serialize_args)
1472 if field.type.is_list:
1473 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);', count,
1474 _c_accessor_get_expr(field.type.expr), field.type.member.c_wiretype)
1475 elif not field.type.need_serialize:
1476 # FIXME - _serialize()
1477 _c(' xcb_parts[%d].iov_len = %s * sizeof(%s);',
1478 count, 'Uh oh', field.type.c_wiretype)
1481 if not field.type.need_serialize:
1482 # the _serialize() function keeps track of padding automatically
1483 _c(' xcb_parts[%d].iov_base = 0;', count)
1484 _c(' xcb_parts[%d].iov_len = -xcb_parts[%d].iov_len & 3;', count, count-1)
1488 _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
1490 # free dyn. all. data, if any
1491 for f in free_calls:
1493 _c(' return xcb_ret;')
1496 def _c_reply(self, name):
1498 Declares the function that returns the reply structure.
1500 spacing1 = ' ' * (len(self.c_cookie_type) - len('xcb_connection_t'))
1501 spacing2 = ' ' * (len(self.c_cookie_type) - len('xcb_generic_error_t'))
1502 spacing3 = ' ' * (len(self.c_reply_name) + 2)
1506 _h(' * Return the reply')
1507 _h(' * @param c The connection')
1508 _h(' * @param cookie The cookie')
1509 _h(' * @param e The xcb_generic_error_t supplied')
1511 _h(' * Returns the reply of the request asked by')
1513 _h(' * The parameter @p e supplied to this function must be NULL if')
1514 _h(' * %s(). is used.', self.c_unchecked_name)
1515 _h(' * Otherwise, it stores the error if any.')
1517 _h(' * The returned value must be freed by the caller using free().')
1521 _hc('/*****************************************************************************')
1523 _hc(' ** %s * %s', self.c_reply_type, self.c_reply_name)
1525 _hc(' ** @param xcb_connection_t%s *c', spacing1)
1526 _hc(' ** @param %s cookie', self.c_cookie_type)
1527 _hc(' ** @param xcb_generic_error_t%s **e', spacing2)
1528 _hc(' ** @returns %s *', self.c_reply_type)
1530 _hc(' *****************************************************************************/')
1532 _hc('%s *', self.c_reply_type)
1533 _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
1534 _hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
1535 _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
1536 _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
1538 _c(' return (%s *) xcb_wait_for_reply(c, cookie.sequence, e);', self.c_reply_type)
1541 def _c_opcode(name, opcode):
1543 Declares the opcode define for requests, events, and errors.
1547 _h('/** Opcode for %s. */', _n(name))
1548 _h('#define %s %s', _n(name).upper(), opcode)
1550 def _c_cookie(self, name):
1552 Declares the cookie type for a non-void request.
1557 _h(' * @brief %s', self.c_cookie_type)
1559 _h('typedef struct %s {', self.c_cookie_type)
1560 _h(' unsigned int sequence; /**< */')
1561 _h('} %s;', self.c_cookie_type)
1563 def c_request(self, name):
1565 Exported function that handles request declarations.
1567 _c_type_setup(self, name, ('request',))
1570 # Cookie type declaration
1571 _c_cookie(self, name)
1574 _c_opcode(name, self.opcode)
1576 # Request structure declaration
1580 _c_type_setup(self.reply, name, ('reply',))
1581 # Reply structure definition
1582 _c_complex(self.reply)
1583 # Request prototypes
1584 _c_request_helper(self, name, self.c_cookie_type, False, True)
1585 _c_request_helper(self, name, self.c_cookie_type, False, False)
1587 _c_request_helper(self, name, self.c_cookie_type, False, True, True)
1588 _c_request_helper(self, name, self.c_cookie_type, False, False, True)
1590 _c_accessors(self.reply, name + ('reply',), name)
1591 _c_reply(self, name)
1593 # Request prototypes
1594 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False)
1595 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True)
1597 _c_request_helper(self, name, 'xcb_void_cookie_t', True, False, True)
1598 _c_request_helper(self, name, 'xcb_void_cookie_t', True, True, True)
1601 def c_event(self, name):
1603 Exported function that handles event declarations.
1605 _c_type_setup(self, name, ('event',))
1608 _c_opcode(name, self.opcodes[name])
1610 if self.name == name:
1611 # Structure definition
1616 _h('typedef %s %s;', _t(self.name + ('event',)), _t(name + ('event',)))
1618 def c_error(self, name):
1620 Exported function that handles error declarations.
1622 _c_type_setup(self, name, ('error',))
1625 _c_opcode(name, self.opcodes[name])
1627 if self.name == name:
1628 # Structure definition
1633 _h('typedef %s %s;', _t(self.name + ('error',)), _t(name + ('error',)))
1636 # Main routine starts here
1638 # Must create an "output" dictionary before any xcbgen imports.
1639 output = {'open' : c_open,
1641 'simple' : c_simple,
1643 'struct' : c_struct,
1645 'request' : c_request,
1650 # Boilerplate below this point
1652 # Check for the argument that specifies path to the xcbgen python package.
1654 opts, args = getopt.getopt(sys.argv[1:], 'p:')
1655 except getopt.GetoptError, err:
1657 print 'Usage: c_client.py [-p path] file.xml'
1660 for (opt, arg) in opts:
1662 sys.path.append(arg)
1664 # Import the module class
1666 from xcbgen.state import Module
1669 print 'Failed to load the xcbgen Python package!'
1670 print 'Make sure that xcb/proto installed it on your Python path.'
1671 print 'If not, you will need to create a .pth file or define $PYTHONPATH'
1672 print 'to extend the path.'
1673 print 'Refer to the README file in xcb/proto for more info.'
1677 # Parse the xml header
1678 module = Module(args[0], output)
1680 # Build type-registry and resolve type dependencies