summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@src.gnome.org>2008-11-11 00:48:17 +0000
committerOwen Taylor <otaylor@src.gnome.org>2008-11-11 00:48:17 +0000
commit259eaeb7de6ef454f3f79e68278018ed0787dd68 (patch)
tree7636068e205c231e0c89a527d3dfb067d57b156b
parent1764f6bcf2be6b45b0726694d86c501ce60d1b4e (diff)
downloadgobject-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.c4
-rw-r--r--girepository/girmodule.h1
-rw-r--r--girepository/girnode.c86
-rw-r--r--girepository/girnode.h8
-rw-r--r--girepository/girparser.c100
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)
{