OPT_TYPE = 'type'
OPT_CLOSURE = 'closure'
OPT_DESTROY = 'destroy'
+OPT_SKIP = 'skip'
# Specific option values
OPT_VAL_BITFIELD = 'bitfield'
OPT_ARRAY_LENGTH = 'length'
OPT_ARRAY_ZERO_TERMINATED = 'zero-terminated'
+OPT_SCOPE_ASYNC = 'async'
+OPT_SCOPE_CALL = 'call'
+OPT_SCOPE_NOTIFIED = 'notified'
class InvalidAnnotationError(Exception):
pass
tag_name, value = self._split_tag_namevalue(line)
canon_name = tag_name.lower()
if canon_name in block.tags:
- print >>sys.stderr, "Multiple definition of tag %r" \
- % (canon_name, )
+ print >> sys.stderr, (
+ "Symbol %s has multiple definition of tag %r" % (
+ block_name, canon_name, ))
block.tags[canon_name] = self._create_tag(canon_name, value)
block.comment = '\n'.join(comment_lines)
self._blocks[block.name] = block
if len(parts) == 1:
tag_name = parts[0]
value = ''
+ if tag_name.endswith(':'):
+ tag_name = tag_name[:-1]
else:
tag_name, value = parts
return (tag_name, value)
def _parse_callable(self, callable, block):
self._parse_node_common(callable, block)
+ for i, param in enumerate(callable.parameters):
+ if (param.type.ctype != 'GDestroyNotify' and
+ param.type.name != 'GLib.DestroyNotify'):
+ continue
+ if i < 2:
+ break
+ callback_param = callable.parameters[i-2]
+ if callback_param.closure_index != -1:
+ callback_param.scope = OPT_SCOPE_NOTIFIED
+ callback_param.transfer = PARAM_TRANSFER_NONE
+
self._parse_params(callable, callable.parameters, block)
self._parse_return(callable, callable.retval, block)
if block:
if scope:
param.scope = scope.one()
param.transfer = PARAM_TRANSFER_NONE
+ elif (param.type.ctype == 'GAsyncReadyCallback' or
+ param.type.name == 'Gio.AsyncReadyCallback'):
+ param.scope = OPT_SCOPE_ASYNC
+ param.transfer = PARAM_TRANSFER_NONE
+
destroy = options.get(OPT_DESTROY)
if destroy:
param.destroy_index = parent.get_parameter_index(destroy.one())
if node.direction is None:
node.direction = self._guess_direction(node)
node.transfer = self._extract_transfer(parent, node, options)
- if OPT_ALLOW_NONE in options:
- node.allow_none = True
param_type = options.get(OPT_TYPE)
if param_type:
node.type = self._resolve(param_type.one(), node.type)
+ if (OPT_ALLOW_NONE in options or
+ node.type.ctype == 'GCancellable*'):
+ node.allow_none = True
+
assert node.transfer is not None
if tag is not None and tag.comment is not None:
node.doc = tag.comment
def combiner(base, *rest):
if not rest:
return base
- if base.name in ['GLib.List', 'GLib.SList'] and len(rest)==1:
+ if (base.name in ['GLib.List', 'GLib.SList'] or
+ base.ctype in ['GList*', 'GSList*']) and len(rest)==1:
return List(base.name, base.ctype, *rest)
- if base.name in ['GLib.HashTable'] and len(rest)==2:
+ if (base.name in ['GLib.HashTable'] or
+ base.ctype in ['GHashTable*']) and len(rest)==2:
return Map(base.name, base.ctype, *rest)
print "WARNING: throwing away type parameters:", type_str
return base
def _parse_element_type(self, parent, node, options):
element_type_opt = options.get(OPT_ELEMENT_TYPE)
element_type = element_type_opt.flat()
- if node.type.name in ['GLib.List', 'GLib.SList']:
+ if (node.type.name in ['GLib.List', 'GLib.SList'] or
+ node.type.ctype in ['GList*', 'GSList*']):
assert len(element_type) == 1
container_type = List(
node.type.name,
node.type.ctype,
self._resolve(element_type[0]))
- elif node.type.name in ['GLib.HashTable']:
+ elif (node.type.name in ['GLib.HashTable'] or
+ node.type.ctype in ['GHashTable*']):
assert len(element_type) == 2
container_type = Map(
node.type.name,
self._parse_version(node, block)
self._parse_deprecated(node, block)
self._parse_attributes(node, block)
+ self._parse_skip(node, block)
def _parse_version(self, node, block):
since_tag = self._get_tag(block, TAG_SINCE)
if annos_tag is None:
return
for key, value in annos_tag.options.iteritems():
- node.attributes.append((key, value.one()))
+ if value:
+ node.attributes.append((key, value.one()))
+
+ def _parse_skip(self, node, block):
+ if block is not None:
+ if OPT_SKIP in block.options:
+ node.skip = True
def _parse_rename_to_func(self, node, block):
rename_to_tag = self._get_tag(block, TAG_RENAME_TO)