Keep aliases and disguised_structures local to each module (#560419)

When parsing, keep keep a separate hash tables of aliases and
'disguised' flags for each module, and store that on the module.

After parsing an include merge the aliases/disguised flags to the
including module.

Remove 'prefix_aliases' flag and always prefix aliases/disguised
structure types when parsing; this simplifies the code considerably.

svn path=/trunk/; revision=904
This commit is contained in:
Owen Taylor 2008-11-12 17:17:01 +00:00
parent 102e08428b
commit b1c6e64049
3 changed files with 123 additions and 71 deletions

View File

@ -46,6 +46,9 @@ g_ir_module_new (const gchar *name,
module->dependencies = NULL;
module->entries = NULL;
module->include_modules = NULL;
module->aliases = NULL;
return module;
}
@ -62,13 +65,50 @@ 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_hash_table_destroy (module->aliases);
g_hash_table_destroy (module->disguised_structures);
g_free (module);
}
static void
add_alias_foreach (gpointer key,
gpointer value,
gpointer data)
{
GIrModule *module = data;
g_hash_table_replace (module->aliases, g_strdup (key), g_strdup (value));
}
static void
add_disguised_structure_foreach (gpointer key,
gpointer value,
gpointer data)
{
GIrModule *module = data;
g_hash_table_replace (module->disguised_structures, g_strdup (key), value);
}
void
g_ir_module_add_include_module (GIrModule *module,
GIrModule *include_module)
{
module->include_modules = g_list_prepend (module->include_modules,
include_module);
g_hash_table_foreach (include_module->aliases,
add_alias_foreach,
module);
g_hash_table_foreach (include_module->disguised_structures,
add_disguised_structure_foreach,
module);
}
GTypelib *
g_ir_module_build_typelib (GIrModule *module,
GList *modules)

View File

@ -36,7 +36,16 @@ struct _GIrModule
gchar *shared_library;
GList *dependencies;
GList *entries;
/* All modules that are included directly or indirectly */
GList *include_modules;
/* Aliases defined in the module or in included modules */
GHashTable *aliases;
/* Structures with the 'disguised' flag (typedef struct _X *X)
* in the module or in included modules */
GHashTable *disguised_structures;
};
GIrModule *g_ir_module_new (const gchar *name,
@ -44,6 +53,9 @@ GIrModule *g_ir_module_new (const gchar *name,
const gchar *module_filename);
void g_ir_module_free (GIrModule *module);
void g_ir_module_add_include_module (GIrModule *module,
GIrModule *include_module);
GTypelib * g_ir_module_build_typelib (GIrModule *module,
GList *modules);

View File

@ -79,7 +79,6 @@ struct _ParseContext
GList *modules;
GList *include_modules;
gboolean prefix_aliases;
GList *dependencies;
GHashTable *aliases;
GHashTable *disguised_structures;
@ -189,15 +188,7 @@ firstpass_start_element_handler (GMarkupParseContext *context,
{
char *key;
if (ctx->prefix_aliases)
{
key = g_strdup_printf ("%s.%s", ctx->namespace, name);
}
else
{
key = g_strdup (name);
}
key = g_strdup_printf ("%s.%s", ctx->namespace, name);
g_hash_table_replace (ctx->disguised_structures, key, GINT_TO_POINTER (1));
}
}
@ -514,23 +505,22 @@ resolve_aliases (ParseContext *ctx, const gchar *type)
gpointer orig;
gpointer value;
GSList *seen_values = NULL;
const char *lookup;
char *prefixed = NULL;
const gchar *lookup;
gchar *prefixed;
/* If we are in an included module, then we need to qualify the
* names of types before resolving them, since they will have
* been stored in the aliases qualified.
*/
if (ctx->prefix_aliases && strchr (type, '.') == NULL)
if (strchr (type, '.') == NULL)
{
prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
lookup = prefixed;
}
else
lookup = type;
{
lookup = type;
prefixed = NULL;
}
seen_values = g_slist_prepend (seen_values, (char*)lookup);
while (g_hash_table_lookup_extended (ctx->aliases, lookup, &orig, &value))
while (g_hash_table_lookup_extended (ctx->current_module->aliases, lookup, &orig, &value))
{
g_debug ("Resolved: %s => %s\n", lookup, (char*)value);
lookup = value;
@ -543,12 +533,38 @@ resolve_aliases (ParseContext *ctx, const gchar *type)
if (lookup == prefixed)
lookup = type;
g_free (prefixed);
return lookup;
}
static gboolean
is_disguised_structure (ParseContext *ctx, const gchar *type)
{
const gchar *lookup;
gchar *prefixed;
gboolean result;
if (strchr (type, '.') == NULL)
{
prefixed = g_strdup_printf ("%s.%s", ctx->namespace, type);
lookup = prefixed;
}
else
{
lookup = type;
prefixed = NULL;
}
result = g_hash_table_lookup (ctx->current_module->disguised_structures,
lookup) != NULL;
g_free (prefixed);
return result;
}
static GIrNodeType *
parse_type (ParseContext *ctx, const gchar *type)
{
@ -1062,25 +1078,18 @@ start_alias (GMarkupParseContext *context,
}
value = g_strdup (target);
if (ctx->prefix_aliases)
key = g_strdup_printf ("%s.%s", ctx->namespace, name);
if (!strchr (target, '.'))
{
key = g_strdup_printf ("%s.%s", ctx->namespace, name);
if (!strchr (target, '.'))
const BasicTypeInfo *basic = parse_basic (target);
if (!basic)
{
const BasicTypeInfo *basic = parse_basic (target);
if (!basic)
{
g_free (value);
/* For non-basic types, re-qualify the interface */
value = g_strdup_printf ("%s.%s", ctx->namespace, target);
}
g_free (value);
/* For non-basic types, re-qualify the interface */
value = g_strdup_printf ("%s.%s", ctx->namespace, target);
}
}
else
{
key = g_strdup (name);
}
g_hash_table_insert (ctx->aliases, key, value);
g_hash_table_replace (ctx->aliases, key, value);
return TRUE;
}
@ -1660,7 +1669,7 @@ start_type (GMarkupParseContext *context,
* doesn't look like a pointer, but is internally.
*/
if (typenode->tag == GI_TYPE_TAG_INTERFACE &&
g_hash_table_lookup (ctx->disguised_structures, typenode->interface) != NULL)
is_disguised_structure (ctx, typenode->interface))
is_pointer = TRUE;
if (is_pointer)
@ -2190,11 +2199,11 @@ parse_include (GMarkupParseContext *context,
const char *version,
GError **error)
{
ParseContext sub_ctx = { 0 };
gchar *buffer;
gsize length;
char *girpath;
gboolean success = FALSE;
GList *modules;
GList *l;
for (l = ctx->include_modules; l; l = l->next)
@ -2240,38 +2249,12 @@ parse_include (GMarkupParseContext *context,
}
g_free (girpath);
sub_ctx.parser = ctx->parser;
sub_ctx.state = STATE_START;
sub_ctx.prefix_aliases = TRUE;
sub_ctx.namespace = name;
sub_ctx.aliases = ctx->aliases;
sub_ctx.disguised_structures = ctx->disguised_structures;
sub_ctx.type_depth = 0;
modules = g_ir_parser_parse_string (ctx->parser, name, buffer, length, error);
success = error != NULL;
context = g_markup_parse_context_new (&firstpass_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;
g_markup_parse_context_free (context);
context = g_markup_parse_context_new (&markup_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);
modules);
g_markup_parse_context_free (context);
g_free (buffer);
return success;
@ -2477,6 +2460,8 @@ start_element_handler (GMarkupParseContext *context,
MISSING_ATTRIBUTE (context, error, element_name, "version");
else
{
GList *l;
if (strcmp (name, ctx->namespace) != 0)
g_set_error (error,
G_MARKUP_ERROR,
@ -2485,6 +2470,15 @@ start_element_handler (GMarkupParseContext *context,
name, ctx->namespace);
ctx->current_module = g_ir_module_new (name, version, shared_library);
ctx->current_module->aliases = ctx->aliases;
ctx->aliases = NULL;
ctx->current_module->disguised_structures = ctx->disguised_structures;
ctx->disguised_structures = NULL;
for (l = ctx->include_modules; l; l = l->next)
g_ir_module_add_include_module (ctx->current_module, l->data);
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);
@ -3033,7 +3027,6 @@ g_ir_parser_parse_string (GIrParser *parser,
ctx.parser = parser;
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.disguised_structures = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@ -3060,8 +3053,15 @@ g_ir_parser_parse_string (GIrParser *parser,
out:
g_hash_table_destroy (ctx.aliases);
g_hash_table_destroy (ctx.disguised_structures);
if (ctx.modules == NULL)
{
/* If we have a module, then ownership is transferred to the module */
if (ctx.aliases != NULL)
g_hash_table_destroy (ctx.aliases);
if (ctx.disguised_structures != NULL)
g_hash_table_destroy (ctx.disguised_structures);
}
g_markup_parse_context_free (context);