Keep aliases and disguised_structures local to each module (#560419)
authorOwen Taylor <otaylor@src.gnome.org>
Wed, 12 Nov 2008 17:17:01 +0000 (17:17 +0000)
committerOwen Taylor <otaylor@src.gnome.org>
Wed, 12 Nov 2008 17:17:01 +0000 (17:17 +0000)
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

ChangeLog
girepository/girmodule.c
girepository/girmodule.h
girepository/girparser.c

index f930da6..271fde5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2008-11-12  Owen Taylor  <otaylor@redhat.com>
+
+       Keep aliases and disguised_structures local to each module (#560419)
+
+       * girepository/girmodule.[ch]: 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.
+
+       * girepository/girparser.c: Remove 'prefix_aliases' flag and
+       always prefix aliases/disguised structure types when parsing; this
+       simplifies the code considerably.
+
 2008-11-12  Owen Taylor  <otaylor@redhat.com>
 
        Fix mismatches between .gir name and 'name' attribute (#560419)
index 91cc02d..1b7c304 100644 (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)
index 5008c4e..c658e17 100644 (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);
 
index 6601fcc..fcd9dad 100644 (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;
-
-  context = g_markup_parse_context_new (&firstpass_parser, 0, &sub_ctx, NULL);
-
-  if (!g_markup_parse_context_parse (context, buffer, length, error))
-    goto out;
+  modules = g_ir_parser_parse_string (ctx->parser, name, buffer, length, error);
+  success = error != NULL;
 
-  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);