diff options
author | Owen Taylor <otaylor@src.gnome.org> | 2008-11-11 00:48:17 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2008-11-11 00:48:17 +0000 |
commit | 259eaeb7de6ef454f3f79e68278018ed0787dd68 (patch) | |
tree | 7636068e205c231e0c89a527d3dfb067d57b156b | |
parent | 1764f6bcf2be6b45b0726694d86c501ce60d1b4e (diff) | |
download | gobject-introspection-259eaeb7de6ef454f3f79e68278018ed0787dd68.tar.gz |
Bug 560250 - Fully parse included modules
For some things, like computing structure offsets to put into the typelib
we need more than just the aliases from included modules. Do a completel
parse of included modules and store in module->included_modules.
Also add g_ir_find_node() to find node information from within the
active set of modules and their includes.
svn path=/trunk/; revision=874
-rw-r--r-- | girepository/girmodule.c | 4 | ||||
-rw-r--r-- | girepository/girmodule.h | 1 | ||||
-rw-r--r-- | girepository/girnode.c | 86 | ||||
-rw-r--r-- | girepository/girnode.h | 8 | ||||
-rw-r--r-- | girepository/girparser.c | 100 |
5 files changed, 177 insertions, 22 deletions
diff --git a/girepository/girmodule.c b/girepository/girmodule.c index d7ca37bf..91cc02d8 100644 --- a/girepository/girmodule.c +++ b/girepository/girmodule.c @@ -62,6 +62,10 @@ g_ir_module_free (GIrModule *module) g_list_free (module->entries); /* Don't free dependencies, we inherit that from the parser */ + /* FIXME: we leak the included modules themelves; they may be shared + * between multiple modules, so we would need refcounting */ + g_list_free (module->include_modules); + g_free (module); } diff --git a/girepository/girmodule.h b/girepository/girmodule.h index 56c7d468..5008c4e9 100644 --- a/girepository/girmodule.h +++ b/girepository/girmodule.h @@ -36,6 +36,7 @@ struct _GIrModule gchar *shared_library; GList *dependencies; GList *entries; + GList *include_modules; }; GIrModule *g_ir_module_new (const gchar *name, diff --git a/girepository/girnode.c b/girepository/girnode.c index 632d5c34..b7f0cb27 100644 --- a/girepository/girnode.c +++ b/girepository/girnode.c @@ -1070,6 +1070,92 @@ find_entry (GIrModule *module, return idx; } +static GIrNode * +find_name_in_module (GIrModule *module, + const gchar *name) +{ + GList *l; + + for (l = module->entries; l; l = l->next) + { + GIrNode *node = (GIrNode *)l->data; + + if (strcmp (node->name, name) == 0) + return node; + } + + return NULL; +} + +gboolean +g_ir_find_node (GIrModule *module, + GList *modules, + const char *name, + GIrNode **node_out, + GIrModule **module_out) +{ + char **names = g_strsplit (name, ".", 0); + gint n_names = g_strv_length (names); + GIrNode *node = NULL; + GList *l; + + if (n_names == 0) + { + g_warning ("Name can't be empty"); + goto out; + } + + if (n_names > 2) + { + g_warning ("Too many name parts in '%s'", name); + goto out; + } + + if (n_names == 1) + { + *module_out = module; + node = find_name_in_module (module, names[0]); + } + else if (strcmp (names[0], module->name) == 0) + { + *module_out = module; + node = find_name_in_module (module, names[1]); + } + else + { + for (l = module->include_modules; l; l = l->next) + { + GIrModule *m = l->data; + + if (strcmp (names[0], m->name) == 0) + { + *module_out = m; + node = find_name_in_module (m, names[1]); + goto out; + } + } + + for (l = modules; l; l = l->next) + { + GIrModule *m = l->data; + + if (strcmp (names[0], m->name) == 0) + { + *module_out = m; + node = find_name_in_module (m, names[1]); + goto out; + } + } + } + + out: + g_strfreev (names); + + *node_out = node; + + return node != NULL; +} + static void serialize_type (GIrModule *module, GList *modules, diff --git a/girepository/girnode.h b/girepository/girnode.h index a0dd9ee0..bc24a11c 100644 --- a/girepository/girnode.h +++ b/girepository/girnode.h @@ -23,6 +23,8 @@ #include <glib.h> +#include "girmodule.h" + G_BEGIN_DECLS typedef struct _GIrNode GIrNode; @@ -340,6 +342,12 @@ guint32 write_string (const gchar *str, const gchar * g_ir_node_param_direction_string (GIrNodeParam * node); const gchar * g_ir_node_type_to_string (GIrNodeTypeId type); +gboolean g_ir_find_node (GIrModule *module, + GList *modules, + const char *name, + GIrNode **node_out, + GIrModule **module_out); + G_END_DECLS #endif /* __G_IR_NODE_H__ */ diff --git a/girepository/girparser.c b/girepository/girparser.c index 50085c4c..9221bb5d 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -72,6 +72,7 @@ struct _ParseContext const char * const*includes; GList *modules; + GList *include_modules; gboolean prefix_aliases; GList *dependencies; GHashTable *aliases; @@ -87,6 +88,34 @@ struct _ParseContext int type_depth; }; +static void start_element_handler (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error); +static void end_element_handler (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error); +static void text_handler (GMarkupParseContext *context, + const gchar *text, + gsize text_len, + gpointer user_data, + GError **error); +static void cleanup (GMarkupParseContext *context, + GError *error, + gpointer user_data); + +static GMarkupParser parser = +{ + start_element_handler, + end_element_handler, + text_handler, + NULL, + cleanup +}; + static gboolean start_alias (GMarkupParseContext *context, const gchar *element_name, @@ -2116,7 +2145,31 @@ parse_include (GMarkupParseContext *context, gchar *buffer; gsize length; char *girpath; - + gboolean success = FALSE; + GList *l; + + for (l = ctx->include_modules; l; l = l->next) + { + GIrModule *m = l->data; + + if (strcmp (m->name, name) == 0) + { + if (strcmp (m->version, version) == 0) + { + return TRUE; + } + else + { + g_set_error (error, + G_MARKUP_ERROR, + G_MARKUP_ERROR_INVALID_CONTENT, + "Module '%s' imported with conflicting versions '%s' and '%s'", + name, m->version, version); + return FALSE; + } + } + } + girpath = locate_gir (name, version, ctx->includes); if (girpath == NULL) @@ -2147,21 +2200,32 @@ parse_include (GMarkupParseContext *context, sub_ctx.type_depth = 0; context = g_markup_parse_context_new (&firstpass_parser, 0, &sub_ctx, NULL); - + if (!g_markup_parse_context_parse (context, buffer, length, error)) - { - g_free (buffer); - return FALSE; - } - + goto out; + if (!g_markup_parse_context_end_parse (context, error)) - { - g_free (buffer); - return FALSE; - } - + goto out; + g_markup_parse_context_free (context); - return TRUE; + + context = g_markup_parse_context_new (&parser, 0, &sub_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; + + success = TRUE; + + out: + ctx->include_modules = g_list_concat (ctx->include_modules, + sub_ctx.modules); + + g_markup_parse_context_free (context); + g_free (buffer); + + return success; } extern GLogLevelFlags logged_levels; @@ -2358,6 +2422,7 @@ start_element_handler (GMarkupParseContext *context, ctx->current_module = g_ir_module_new (name, version, shared_library); ctx->modules = g_list_append (ctx->modules, ctx->current_module); ctx->current_module->dependencies = ctx->dependencies; + ctx->current_module->include_modules = g_list_copy (ctx->include_modules); state_switch (ctx, STATE_NAMESPACE); goto out; @@ -2819,15 +2884,6 @@ cleanup (GMarkupParseContext *context, ctx->current_module = NULL; } -static GMarkupParser parser = -{ - start_element_handler, - end_element_handler, - text_handler, - NULL, - cleanup -}; - static GList * post_filter_varargs_functions (GList *list) { |