diff options
author | Colin Walters <walters@src.gnome.org> | 2008-08-28 21:19:22 +0000 |
---|---|---|
committer | Colin Walters <walters@src.gnome.org> | 2008-08-28 21:19:22 +0000 |
commit | 33ce153ff89ca8511cbb557cc510e9ae08f7999e (patch) | |
tree | e9741ac0ceb20be978516f88b8cc4e3318198a65 | |
parent | 20311dea2f0423f9a7655e648da6a01c62422645 (diff) | |
download | gobject-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.am | 4 | ||||
-rw-r--r-- | girepository/girparser.c | 225 | ||||
-rw-r--r-- | tools/compiler.c | 2 |
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" }, |