diff options
author | Colin Walters <walters@verbum.org> | 2008-08-13 16:10:09 +0000 |
---|---|---|
committer | Colin Walters <walters@src.gnome.org> | 2008-08-13 16:10:09 +0000 |
commit | 5ec7b60569fce361c5f78a042aebc5ad570dfb40 (patch) | |
tree | 0d4aa8846a9ecfd6e0dbedb3e54029739058bd6a | |
parent | 316f0ee0af07331e07624e769edfc11e457cd838 (diff) | |
download | gobject-introspection-5ec7b60569fce361c5f78a042aebc5ad570dfb40.tar.gz |
Record typedefs as <alias> elements. Also attempt to look up types in
2008-08-12 Colin Walters <walters@verbum.org>
* giscanner/transformer.py: Record typedefs as <alias> elements.
Also attempt to look up types in external namespaces.
* giscanner/girwriter.py: Write them.
* giscanner/glibtransformer.py: Rework resolver using real instanceof
checks. Resolve interface methods and properties.
* tests/scanner/foo-object.h: Add a method with typedef.
* tests/scanner/Foo-expected.gir: Update.
* girepository/girnode.c: Debug tweaks.
* girepository/girparser.c: Make a first pass through the XML where we
record all the aliases. This lets us resolve them as we go through the
second pass.
* gir/Makefile.am: Don't install gobject-2.0.gir; we want that to come
from gir-repository.
svn path=/trunk/; revision=355
-rw-r--r-- | ChangeLog | 25 | ||||
-rw-r--r-- | gir/Makefile.am | 4 | ||||
-rw-r--r-- | girepository/girnode.c | 6 | ||||
-rw-r--r-- | girepository/girparser.c | 144 | ||||
-rw-r--r-- | giscanner/ast.py | 11 | ||||
-rw-r--r-- | giscanner/girwriter.py | 10 | ||||
-rw-r--r-- | giscanner/glibtransformer.py | 33 | ||||
-rw-r--r-- | giscanner/transformer.py | 14 | ||||
-rw-r--r-- | tests/scanner/Foo-expected.gir | 23 | ||||
-rw-r--r-- | tests/scanner/foo-object.h | 8 |
10 files changed, 250 insertions, 28 deletions
@@ -1,5 +1,30 @@ 2008-08-12 Colin Walters <walters@verbum.org> + * giscanner/transformer.py: Record typedefs as <alias> elements. + Also attempt to look up types in external namespaces. + * giscanner/girwriter.py: Write them. + * giscanner/glibtransformer.py: Rework resolver using real instanceof + checks. Resolve interface methods and properties. + * tests/scanner/foo-object.h: Add a method with typedef. + * tests/scanner/Foo-expected.gir: Update. + * girepository/girnode.c: Debug tweaks. + * girepository/girparser.c: Make a first pass through the XML where we + record all the aliases. This lets us resolve them as we go through the + second pass. + * gir/Makefile.am: Don't install gobject-2.0.gir; we want that to come + from gir-repository. + +2008-08-12 Colin Walters <walters@verbum.org> + + * giscanner/glibtransformer.py: Resolve typedefs (e.g. AtkAttributeSet -> GSList). + Correctly do subclasseing in 2nd pass resolution. Handle callbacks in structure + fields. + * giscanner/transformer.py: Record typedefs and expose public API for resolving + them. + * tests/scanner/Foo-expected.gir: Fix expected callback types. + +2008-08-12 Colin Walters <walters@verbum.org> + * giscanner/glibtransformer.py: Also transform object properties. 2008-08-12 Colin Walters <walters@verbum.org> diff --git a/gir/Makefile.am b/gir/Makefile.am index dce5152e..97e3c2d6 100644 --- a/gir/Makefile.am +++ b/gir/Makefile.am @@ -1,2 +1,2 @@ -girdir = $(datadir)/gir -dist_gir_DATA = gobject-2.0.gir +#girdir = $(datadir)/gir +#dist_gir_DATA = gobject-2.0.gir diff --git a/girepository/girnode.c b/girepository/girnode.c index 2aeba30e..7961da37 100644 --- a/girepository/girnode.c +++ b/girepository/girnode.c @@ -880,7 +880,7 @@ g_ir_node_get_full_size_internal (GIrNode *parent, GIrNode *node) size = 0; } - g_debug ("node %p type '%s' full size %d", node, + g_debug ("node '%s' %p type '%s' full size %d", node->name, node, g_ir_node_type_to_string (node->type), size); return size; @@ -2173,8 +2173,8 @@ g_ir_node_build_typelib (GIrNode *node, g_assert_not_reached (); } - g_debug ("node %p type '%s', offset %d -> %d, offset2 %d -> %d", - node, g_ir_node_type_to_string (node->type), + g_debug ("node '%s' %p type '%s', offset %d -> %d, offset2 %d -> %d", + node->name, node, g_ir_node_type_to_string (node->type), old_offset, *offset, old_offset2, *offset2); if (*offset2 - old_offset2 + *offset - old_offset > g_ir_node_get_full_size (node)) diff --git a/girepository/girparser.c b/girepository/girparser.c index 0bc8af39..2e875d7f 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -53,7 +53,8 @@ typedef enum STATE_STRUCT_FIELD, STATE_ERRORDOMAIN, STATE_UNION, - STATE_CONSTANT + STATE_CONSTANT, + STATE_ALIAS, /* 25 */ } ParseState; typedef struct _ParseContext ParseContext; @@ -63,6 +64,7 @@ struct _ParseContext ParseState prev_state; GList *modules; + GHashTable *aliases; GIrModule *current_module; GIrNode *current_node; @@ -123,6 +125,18 @@ state_switch (ParseContext *ctx, ParseState newstate) ctx->state = newstate; } +static GIrNodeType * parse_type_internal (gchar *str, gchar **rest); + +static GIrNodeType * +create_pointer () +{ + char *pointer = g_strdup ("any"); + char *pointer_rest; + GIrNodeType *ret = parse_type_internal (pointer, &pointer_rest); + g_free (pointer); + return ret; +} + static GIrNodeType * parse_type_internal (gchar *str, gchar **rest) { @@ -258,6 +272,10 @@ parse_type_internal (gchar *str, gchar **rest) goto error; (*rest)++; } + else + { + type->parameter_type1 = create_pointer (); + } } else if (g_str_has_prefix (*rest, "GHashTable")) { @@ -290,6 +308,12 @@ parse_type_internal (gchar *str, gchar **rest) goto error; (*rest)++; } + else + { + type->parameter_type1 = create_pointer (); + type->parameter_type2 = create_pointer (); + } + } else if (g_str_has_prefix (*rest, "GError")) { @@ -396,13 +420,28 @@ parse_type_internal (gchar *str, gchar **rest) return NULL; } +static const char * +resolve_aliases (ParseContext *ctx, const gchar *type) +{ + gpointer orig; + gpointer value; + + while (g_hash_table_lookup_extended (ctx->aliases, type, &orig, &value)) + { + g_debug ("Resolved: %s => %s", type, value); + type = value; + } + return type; +} + static GIrNodeType * -parse_type (const gchar *type) +parse_type (ParseContext *ctx, const gchar *type) { gchar *str; gchar *rest; GIrNodeType *node; + type = resolve_aliases (ctx, type); str = g_strdup (type); node = parse_type_internal (str, &rest); g_free (str); @@ -849,6 +888,34 @@ start_field (GMarkupParseContext *context, } static gboolean +start_alias (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + ParseContext *ctx, + GError **error) +{ + const gchar *name; + const gchar *target; + const gchar *type; + + name = find_attribute ("name", attribute_names, attribute_values); + if (name == NULL) { + MISSING_ATTRIBUTE (context, error, element_name, "name"); + return FALSE; + } + + target = find_attribute ("target", attribute_names, attribute_values); + if (name == NULL) { + MISSING_ATTRIBUTE (context, error, element_name, "target"); + return FALSE; + } + + g_hash_table_insert (ctx->aliases, g_strdup (name), g_strdup (target)); + return TRUE; +} + +static gboolean start_enum (GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names, @@ -1075,7 +1142,7 @@ start_constant (GMarkupParseContext *context, ((GIrNode *)constant)->name = g_strdup (name); constant->value = g_strdup (value); - constant->type = parse_type (type); + constant->type = parse_type (ctx, type); if (deprecated && strcmp (deprecated, "1") == 0) constant->deprecated = TRUE; @@ -1310,19 +1377,19 @@ start_type (GMarkupParseContext *context, { GIrNodeParam *param; param = (GIrNodeParam *)ctx->current_typed; - param->type = parse_type (name); + param->type = parse_type (ctx, name); } break; case G_IR_NODE_FIELD: { GIrNodeField *field = (GIrNodeField *)ctx->current_typed; - field->type = parse_type (name); + field->type = parse_type (ctx, name); } break; case G_IR_NODE_PROPERTY: { GIrNodeProperty *property = (GIrNodeProperty *) ctx->current_typed; - property->type = parse_type (name); + property->type = parse_type (ctx, name); } break; default: @@ -1661,7 +1728,7 @@ start_discriminator (GMarkupParseContext *context, MISSING_ATTRIBUTE (context, error, element_name, "offset"); { ((GIrNodeUnion *)ctx->current_node)->discriminator_type - = parse_type (type); + = parse_type (ctx, type); ((GIrNodeUnion *)ctx->current_node)->discriminator_offset = atoi (offset); } @@ -1705,6 +1772,13 @@ start_element_handler (GMarkupParseContext *context, switch (element_name[0]) { + case 'a': + if (ctx->state == STATE_NAMESPACE && strcmp (element_name, "alias") == 0) + { + state_switch (ctx, STATE_ALIAS); + goto out; + } + break; case 'b': if (start_enum (context, element_name, attribute_names, attribute_values, @@ -2047,6 +2121,13 @@ end_element_handler (GMarkupParseContext *context, } break; + case STATE_ALIAS: + if (require_end_element (context, "alias", element_name, error)) + { + state_switch (ctx, STATE_NAMESPACE); + } + break; + case STATE_FUNCTION_RETURN: if (strcmp ("type", element_name) == 0) break; @@ -2262,6 +2343,44 @@ cleanup (GMarkupParseContext *context, ctx->current_module = NULL; } +static void +firstpass_start_element_handler (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + ParseContext *ctx = user_data; + + if (strcmp (element_name, "alias") == 0) + { + start_alias (context, element_name, attribute_names, attribute_values, + ctx, error); + } +} + +static void +firstpass_end_element_handler (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + ParseContext *ctx = user_data; + +} + + +static GMarkupParser firstpass_parser = +{ + firstpass_start_element_handler, + firstpass_end_element_handler, + NULL, + NULL, + NULL, +}; + + static GMarkupParser parser = { start_element_handler, @@ -2280,6 +2399,15 @@ g_ir_parse_string (const gchar *buffer, GMarkupParseContext *context; ctx.state = STATE_START; + ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); + + context = g_markup_parse_context_new (&firstpass_parser, 0, &ctx, NULL); + + if (!g_markup_parse_context_parse (context, buffer, length, error)) + goto out; + + if (!g_markup_parse_context_end_parse (context, error)) + goto out; context = g_markup_parse_context_new (&parser, 0, &ctx, NULL); if (!g_markup_parse_context_parse (context, buffer, length, error)) @@ -2289,6 +2417,8 @@ g_ir_parse_string (const gchar *buffer, goto out; out: + + g_hash_table_destroy (ctx.aliases); g_markup_parse_context_free (context); diff --git a/giscanner/ast.py b/giscanner/ast.py index a0955c10..93736f30 100644 --- a/giscanner/ast.py +++ b/giscanner/ast.py @@ -141,6 +141,17 @@ class Type(Node): self.ctype = ctype +class Alias(Node): + + def __init__(self, name, target,ctype=None): + Node.__init__(self, name) + self.target = target + self.ctype = ctype + + def __repr__(self): + return 'Alias(%r, %r)' % (self.name, self.target) + + class Parameter(Node): def __init__(self, name, typenode): diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py index 45d2b23c..427c04f5 100644 --- a/giscanner/girwriter.py +++ b/giscanner/girwriter.py @@ -21,7 +21,7 @@ from __future__ import with_statement from .ast import (Callback, Class, Enum, Function, Interface, Member, - Sequence, Struct) + Sequence, Struct, Alias) from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags, GLibObject, GLibInterface) from .xmlwriter import XMLWriter @@ -65,9 +65,17 @@ class GIRWriter(XMLWriter): elif isinstance(node, Member): # FIXME: atk_misc_instance singleton pass + elif isinstance(node, Alias): + self._write_alias(node) else: print 'WRITER: Unhandled node', node + def _write_alias(self, alias): + attrs = [('name', alias.name), ('target', alias.target)] + if alias.ctype is not None: + attrs.append(('c:type', ntype.ctype)) + self.write_tag('alias', attrs) + def _write_function(self, func, tag_name='function'): attrs = [('name', func.name), ('c:identifier', func.symbol)] diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py index 43c1dea6..ceb98907 100644 --- a/giscanner/glibtransformer.py +++ b/giscanner/glibtransformer.py @@ -25,7 +25,7 @@ import sys from . import cgobject from .odict import odict from .ast import (Callback, Enum, Function, Member, Namespace, Parameter, - Property, Return, Sequence, Struct, Field, Type, + Property, Return, Sequence, Struct, Field, Type, Alias, type_name_from_ctype) from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags, GLibInterface, GLibObject, GLibSignal) @@ -95,6 +95,7 @@ class GLibTransformer(object): def _resolve_param_type(self, ptype): type_name = ptype.name.replace('*', '') + type_name = self._transformer.resolve_possible_typedef(type_name) ptype.name = self._resolve_type_name(type_name) return ptype @@ -107,6 +108,8 @@ class GLibTransformer(object): self._parse_struct(node) elif isinstance(node, Callback): self._parse_callback(node) + elif isinstance(node, Alias): + self._parse_alias(node) elif isinstance(node, Member): # FIXME: atk_misc_instance singletons pass @@ -114,21 +117,35 @@ class GLibTransformer(object): print 'GOBJECT BUILDER: Unhandled node:', node def _resolve_node(self, node): - ntype = type(node) - if ntype in (Callback, Function): + + def isany(*klasses): + for klass in klasses: + if isinstance(node, klass): + return True + return False + + if isany(Callback, Function): self._resolve_function(node) - if ntype in (GLibObject, GLibBoxed): + if isany(GLibObject, GLibBoxed, GLibInterface): for meth in node.methods: self._resolve_function(meth) + if isany(GLibObject, GLibBoxed): for ctor in node.constructors: self._resolve_function(ctor) - if ntype in (Struct, ): + if isany(GLibObject, GLibInterface): + for prop in node.properties: + self._resolve_property(prop) + for sig in node.signals: + self._resolve_function(sig) + if isany(Struct, ): for field in node.fields: if isinstance(field, Field): self._resolve_field(field) - if ntype in (GLibObject, ): - for prop in node.properties: - self._resolve_property(prop) + elif isinstance(field, Callback): + self._resolve_function(field) + + def _parse_alias(self, alias): + self._add_attribute(alias) def _parse_enum(self, enum): self._add_attribute(enum) diff --git a/giscanner/transformer.py b/giscanner/transformer.py index a843c3ea..f2fe6fc4 100644 --- a/giscanner/transformer.py +++ b/giscanner/transformer.py @@ -18,9 +18,12 @@ # 02110-1301, USA. # +import os +import sys + from giscanner.ast import (Callback, Enum, Function, Namespace, Member, Parameter, Return, Sequence, Struct, Field, - Type, type_name_from_ctype) + Type, Alias, type_name_from_ctype) from giscanner.sourcescanner import ( SourceSymbol, ctype_name, symbol_type_name, CTYPE_POINTER, CTYPE_BASIC_TYPE, CTYPE_UNION, CTYPE_ARRAY, @@ -40,6 +43,7 @@ class Transformer(object): self._type_names = {} self._typedefs_ns = {} self._strip_prefix = '' + self._typedefs = {} def get_type_names(self): return self._type_names @@ -47,6 +51,9 @@ class Transformer(object): def set_strip_prefix(self, strip_prefix): self._strip_prefix = strip_prefix + def resolve_possible_typedef(self, tname): + return self._typedefs.get(tname, tname) + def parse(self): nodes = [] for symbol in self.generator.get_symbols(): @@ -200,7 +207,7 @@ class Transformer(object): CTYPE_BASIC_TYPE, CTYPE_UNION, CTYPE_VOID): - return + return Alias(symbol.ident, symbol.base_type.name) else: raise NotImplementedError( "symbol %r of type %s" % (symbol.ident, ctype_name(ctype))) @@ -209,7 +216,8 @@ class Transformer(object): def _create_type(self, source_type): ctype = self._create_source_type(source_type) type_name = type_name_from_ctype(ctype) - return Type(type_name, ctype) + resolved_type_name = self._resolve_type_name(type_name) + return Type(resolved_type_name, ctype) def _create_parameter(self, symbol, options): ptype = self._create_type(symbol.base_type) diff --git a/tests/scanner/Foo-expected.gir b/tests/scanner/Foo-expected.gir index d1b45a7f..b0cfd897 100644 --- a/tests/scanner/Foo-expected.gir +++ b/tests/scanner/Foo-expected.gir @@ -184,7 +184,7 @@ </parameter> </parameters> </method> - <method name="with_voidp" c:identifier="foo_object_with_voidp"> + <method name="various" c:identifier="foo_object_various"> <return-value> <type name="none" c:type="void"/> </return-value> @@ -195,6 +195,22 @@ <parameter name="data"> <type name="any" c:type="void*"/> </parameter> + <parameter name="some_type"> + <type name="GType" c:type="GType"/> + </parameter> + </parameters> + </method> + <method name="with_tdef" c:identifier="foo_object_with_tdef"> + <return-value> + <type name="none" c:type="void"/> + </return-value> + <parameters> + <parameter name="object"> + <type name="Object" c:type="FooObject*"/> + </parameter> + <parameter name="blah"> + <type name="FooList" c:type="FooList*"/> + </parameter> </parameters> </method> <property name="string"> @@ -206,7 +222,7 @@ </return-value> <parameters> <parameter name="object"> - <type name="FooObject*" c:type="FooObject*"/> + <type name="Object" c:type="FooObject*"/> </parameter> <parameter name="first_param"> <type name="int32" c:type="int"/> @@ -219,7 +235,7 @@ </return-value> <parameters> <parameter name="object"> - <type name="GObject" c:type="GObject"/> + <type name="GLib.Object" c:type="GObject"/> </parameter> <parameter name="p0"> <type name="any" c:type="gpointer"/> @@ -227,6 +243,7 @@ </parameters> </glib:signal> </class> + <alias name="FooList" target="GSList"/> <class name="Subobject" c:type="FooSubobject" parent="Object" diff --git a/tests/scanner/foo-object.h b/tests/scanner/foo-object.h index aefa2cd1..2ac76465 100644 --- a/tests/scanner/foo-object.h +++ b/tests/scanner/foo-object.h @@ -61,7 +61,13 @@ gint foo_object_calleesowns (FooObject *object, GObject * GList* foo_object_get_strings (FooObject *object); GSList* foo_object_get_objects (FooObject *object); -void foo_object_with_voidp (FooObject *object, void *data); +void foo_object_various (FooObject *object, void *data, GType some_type); + +/* A random typedef */ +typedef GSList FooList; + +void foo_object_with_tdef (FooObject *object, FooList *blah); + struct _FooSubobject { |