summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Walters <walters@src.gnome.org>2008-08-28 21:19:22 +0000
committerColin Walters <walters@src.gnome.org>2008-08-28 21:19:22 +0000
commit33ce153ff89ca8511cbb557cc510e9ae08f7999e (patch)
treee9741ac0ceb20be978516f88b8cc4e3318198a65
parent20311dea2f0423f9a7655e648da6a01c62422645 (diff)
downloadgobject-introspection-33ce153ff89ca8511cbb557cc510e9ae08f7999e.tar.gz
Expand aliases when generating typelibs
* gir/Makefile.am: Use --includedir * girepository/girparser.c: Recursively parse includes to pull in aliases and expand them. We need this to avoid putting unknown names in the typelibs. * tools/compiler.c: Add --includedir option. svn path=/trunk/; revision=512
-rw-r--r--gir/Makefile.am4
-rw-r--r--girepository/girparser.c225
-rw-r--r--tools/compiler.c2
3 files changed, 188 insertions, 43 deletions
diff --git a/gir/Makefile.am b/gir/Makefile.am
index 6b306bb5..acd4c9de 100644
--- a/gir/Makefile.am
+++ b/gir/Makefile.am
@@ -85,8 +85,8 @@ CLEANFILES = $(BUILT_SOURCES)
girdir=$(datadir)/gir
dist_gir_DATA = $(BUILT_SOURCES)
-%.typelib: %.gir $(top_builddir)/tools/g-ir-compiler$(EXEEXT)
- $(DEBUG) $(top_builddir)/tools/g-ir-compiler$(EXEEXT) $< -o $@
+%.typelib: %.gir $(top_builddir)/tools/g-ir-compiler$(EXEEXT) Makefile
+ $(DEBUG) $(top_builddir)/tools/g-ir-compiler$(EXEEXT) --includedir=. $(G_IR_COMPILER_OPTS) $< -o $@
typelibsdir = $(datadir)/girepository
typelibs_DATA = GLib.typelib GObject.typelib Gio.typelib
diff --git a/girepository/girparser.c b/girepository/girparser.c
index 247f896c..7f20ce9a 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -68,15 +68,94 @@ struct _ParseContext
ParseState state;
ParseState prev_state;
+ const char **includes;
+
GList *modules;
+ gboolean prefix_aliases;
GHashTable *aliases;
+ const char *namespace;
GIrModule *current_module;
GIrNode *current_node;
GIrNode *current_typed;
int type_depth;
};
+static gboolean
+start_alias (GMarkupParseContext *context,
+ const gchar *element_name,
+ const gchar **attribute_names,
+ const gchar **attribute_values,
+ ParseContext *ctx,
+ GError **error);
+
+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 char *
+locate_gir (const char *name, const char **extra_paths)
+{
+ const gchar *const *datadirs;
+ const gchar *const *dir;
+ char *girname;
+ char *path = NULL;
+ GSList *link;
+ gboolean firstpass = TRUE;
+
+ datadirs = g_get_system_data_dirs ();
+
+ girname = g_strdup_printf ("%s.gir", name);
+
+ for (dir = datadirs; *dir; dir++)
+ {
+ path = g_build_filename (*dir, "gir", girname, NULL);
+ if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
+ return path;
+ g_free (path);
+ path = NULL;
+ if (firstpass && !*dir)
+ {
+ firstpass = FALSE;
+ dir = extra_paths;
+ }
+ }
+ g_free (girname);
+ return path;
+}
+
#define MISSING_ATTRIBUTE(ctx,error,element,attribute) \
do { \
int line_number, char_number; \
@@ -946,6 +1025,8 @@ start_alias (GMarkupParseContext *context,
const gchar *name;
const gchar *target;
const gchar *type;
+ char *key;
+ char *value;
name = find_attribute ("name", attribute_names, attribute_values);
if (name == NULL)
@@ -961,7 +1042,12 @@ start_alias (GMarkupParseContext *context,
return FALSE;
}
- g_hash_table_insert (ctx->aliases, g_strdup (name), g_strdup (target));
+ if (ctx->prefix_aliases)
+ key = g_strdup_printf ("%s.%s", ctx->namespace, name);
+ else
+ key = g_strdup (name);
+
+ g_hash_table_insert (ctx->aliases, key, g_strdup (target));
return TRUE;
}
@@ -1847,6 +1933,63 @@ start_discriminator (GMarkupParseContext *context,
return FALSE;
}
+
+static gboolean
+parse_include (GMarkupParseContext *context,
+ ParseContext *ctx,
+ const char *name,
+ GError **error)
+{
+ ParseContext sub_ctx = { 0 };
+ GMarkupParseContext *sub_context;
+ gchar *buffer;
+ gsize length;
+ char *girpath;
+
+ girpath = locate_gir (name, ctx->includes);
+
+ if (girpath == NULL)
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Could not find GIR file '%s'; check XDG_DATA_DIRS or use --includedir",
+ name);
+ return FALSE;
+ }
+
+ g_debug ("Parsing include %s", girpath);
+
+ if (!g_file_get_contents (girpath, &buffer, &length, error))
+ {
+ g_free (girpath);
+ return FALSE;
+ }
+ g_free (girpath);
+
+ sub_ctx.state = STATE_START;
+ sub_ctx.prefix_aliases = TRUE;
+ sub_ctx.namespace = name;
+ sub_ctx.aliases = ctx->aliases;
+ 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;
+ }
+
+ if (!g_markup_parse_context_end_parse (context, error))
+ {
+ g_free (buffer);
+ return FALSE;
+ }
+
+ g_markup_parse_context_free (context);
+ return TRUE;
+}
extern GLogLevelFlags logged_levels;
@@ -1972,6 +2115,19 @@ start_element_handler (GMarkupParseContext *context,
if (strcmp (element_name, "include") == 0 &&
ctx->state == STATE_REPOSITORY)
{
+ const gchar *name;
+
+ name = find_attribute ("name", attribute_names, attribute_values);
+
+ if (name == NULL)
+ {
+ MISSING_ATTRIBUTE (context, error, element_name, "name");
+ break;
+ }
+
+ if (!parse_include (context, ctx, name, error))
+ break;
+
state_switch (ctx, STATE_INCLUDE);
goto out;
}
@@ -2464,44 +2620,6 @@ 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,
@@ -2512,7 +2630,8 @@ static GMarkupParser parser =
};
GList *
-g_ir_parse_string (const gchar *buffer,
+g_ir_parse_string (const char *namespace,
+ const gchar *buffer,
gssize length,
GError **error)
{
@@ -2520,6 +2639,8 @@ g_ir_parse_string (const gchar *buffer,
GMarkupParseContext *context;
ctx.state = STATE_START;
+ ctx.prefix_aliases = FALSE;
+ ctx.namespace = namespace;
ctx.aliases = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
ctx.type_depth = 0;
@@ -2530,6 +2651,8 @@ g_ir_parse_string (const gchar *buffer,
if (!g_markup_parse_context_end_parse (context, error))
goto out;
+
+ g_markup_parse_context_free (context);
context = g_markup_parse_context_new (&parser, 0, &ctx, NULL);
if (!g_markup_parse_context_parse (context, buffer, length, error))
@@ -2554,13 +2677,33 @@ g_ir_parse_file (const gchar *filename,
gchar *buffer;
gsize length;
GList *modules;
+ const char *slash;
+ char *namespace;
+
+ if (!g_str_has_suffix (filename, ".gir"))
+ {
+ g_set_error (error,
+ G_MARKUP_ERROR,
+ G_MARKUP_ERROR_INVALID_CONTENT,
+ "Expected filename to end with '.gir'");
+ return NULL;
+ }
g_debug ("[parsing] filename %s", filename);
+ slash = g_strrstr (filename, "/");
+ if (!slash)
+ namespace = g_strdup (filename);
+ else
+ namespace = g_strdup (slash+1);
+ namespace[strlen(namespace)-4] = '\0';
+
if (!g_file_get_contents (filename, &buffer, &length, error))
return NULL;
- modules = g_ir_parse_string (buffer, length, error);
+ modules = g_ir_parse_string (namespace, buffer, length, error);
+
+ g_free (namespace);
g_free (buffer);
diff --git a/tools/compiler.c b/tools/compiler.c
index b7112f22..4c47cb6d 100644
--- a/tools/compiler.c
+++ b/tools/compiler.c
@@ -36,6 +36,7 @@
gboolean code = FALSE;
gboolean no_init = FALSE;
+gchar **includedirs = NULL;
gchar **input = NULL;
gchar *output = NULL;
gchar *mname = NULL;
@@ -160,6 +161,7 @@ static GOptionEntry options[] =
{
{ "code", 0, 0, G_OPTION_ARG_NONE, &code, "emit C code", NULL },
{ "no-init", 0, 0, G_OPTION_ARG_NONE, &no_init, "do not create _init() function", NULL },
+ { "includedir", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &includedirs, "include directories in GIR search path", NULL },
{ "output", 'o', 0, G_OPTION_ARG_FILENAME, &output, "output file", "FILE" },
{ "module", 'm', 0, G_OPTION_ARG_STRING, &mname, "module to compile", "NAME" },
{ "shared-library", 'l', 0, G_OPTION_ARG_FILENAME, &shlib, "shared library", "FILE" },