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->dependencies = NULL;
module->entries = NULL; module->entries = NULL;
module->include_modules = NULL;
module->aliases = NULL;
return module; return module;
} }
@ -62,13 +65,50 @@ g_ir_module_free (GIrModule *module)
g_list_free (module->entries); g_list_free (module->entries);
/* Don't free dependencies, we inherit that from the parser */ /* 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_list_free (module->include_modules);
g_hash_table_destroy (module->aliases);
g_hash_table_destroy (module->disguised_structures);
g_free (module); 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 * GTypelib *
g_ir_module_build_typelib (GIrModule *module, g_ir_module_build_typelib (GIrModule *module,
GList *modules) GList *modules)

View File

@ -36,7 +36,16 @@ struct _GIrModule
gchar *shared_library; gchar *shared_library;
GList *dependencies; GList *dependencies;
GList *entries; GList *entries;
/* All modules that are included directly or indirectly */
GList *include_modules; 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, GIrModule *g_ir_module_new (const gchar *name,
@ -44,6 +53,9 @@ GIrModule *g_ir_module_new (const gchar *name,
const gchar *module_filename); const gchar *module_filename);
void g_ir_module_free (GIrModule *module); 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, GTypelib * g_ir_module_build_typelib (GIrModule *module,
GList *modules); GList *modules);

View File

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