[ALIAS_POINTER] Support for alias to pointers
[gnome.gobject-introspection] / girepository / girparser.c
index 1347945..c8a13aa 100644 (file)
@@ -524,6 +524,17 @@ parse_type_internal (const gchar *str, char **next, gboolean in_glib,
        (str)++;
 
       type->interface = g_strndup (start, str - start);
+      /* 
+         The alias code can return pointers for typedefs.
+        since the type reader code does not catch this,
+         it has to be set here.
+      */
+      if (strchr(start, '*')) 
+        {
+          g_debug("Adding type as interface (pointer) %s ", type->interface); 
+          type->is_pointer = TRUE;
+        }
     }
 
   if (next)
@@ -539,13 +550,15 @@ parse_type_internal (const gchar *str, char **next, gboolean in_glib,
 }
 
 static const char *
-resolve_aliases (ParseContext *ctx, const gchar *type)
+resolve_aliases (ParseContext *ctx, const gchar *type, gboolean *is_pointer)
 {
   gpointer orig;
   gpointer value;
   GSList *seen_values = NULL;
   const gchar *lookup;
-  gchar *prefixed;
+  gchar *prefixed, *lookup_copy;
+  char *star_pos;
+    
 
   if (strchr (type, '.') == NULL)
     {
@@ -557,17 +570,36 @@ resolve_aliases (ParseContext *ctx, const gchar *type)
       lookup = type;
       prefixed = NULL;
     }
-
+   /*
+    Since target could be a name + '*'
+    we need to duplicate the lookup value always
+    and free it later..
+  */
+  star_pos = strchr(lookup, '*');
+  if (star_pos) 
+    *is_pointer = TRUE;
+    
+  lookup_copy = g_strndup(lookup, star_pos ? (gsize) (star_pos - lookup) : strlen(lookup));
+  
   seen_values = g_slist_prepend (seen_values, (char*)lookup);
-  while (g_hash_table_lookup_extended (ctx->current_module->aliases, lookup, &orig, &value))
+  while (g_hash_table_lookup_extended (ctx->current_module->aliases, lookup_copy, &orig, &value))
     {
       g_debug ("Resolved: %s => %s\n", lookup, (char*)value);
       lookup = value;
+      /* prevent looping forever.. */
       if (g_slist_find_custom (seen_values, lookup,
                               (GCompareFunc)strcmp) != NULL)
        break;
       seen_values = g_slist_prepend (seen_values, (gchar*)lookup);
-    }
+        
+      g_free(lookup_copy);
+      star_pos = strchr(lookup, '*');
+      if (star_pos)
+        *is_pointer = TRUE;
+      lookup_copy = g_strndup(lookup, star_pos ? (gsize) (star_pos - lookup) : strlen(lookup));
+    }
+  g_free(lookup_copy);  
   g_slist_free (seen_values);
 
   if (lookup == prefixed)
@@ -610,18 +642,23 @@ parse_type (ParseContext *ctx, const gchar *type)
   GIrNodeType *node;
   const BasicTypeInfo *basic;
   gboolean in_glib, in_gobject;
-
+  gboolean is_pointer = FALSE;
+    
   in_glib = strcmp (ctx->namespace, "GLib") == 0;
   in_gobject = strcmp (ctx->namespace, "GObject") == 0;
 
   /* Do not search aliases for basic types */
   basic = parse_basic (type);
   if (basic == NULL)
-    type = resolve_aliases (ctx, type);
+    type = resolve_aliases (ctx, type, &is_pointer);
 
   node = parse_type_internal (type, NULL, in_glib, in_gobject);
-  if (node)
-    g_debug ("Parsed type: %s => %d", type, node->tag);
+  if (node) 
+    {
+      g_debug ("Parsed type: %s => %d", type, node->tag);
+      /* Overlay is_pointer if it get's set */
+      node->is_pointer = node->is_pointer || is_pointer;
+    } 
   else
     g_critical ("Failed to parse type: '%s'", type);
 
@@ -3195,6 +3232,28 @@ post_filter_toplevel_varargs_functions (GList *list,
   return list;
 }
 
+
+/* 
+  quick look up of node in the list..
+  return null, or a pointer to the list item..
+ */
+static GList *
+node_find_in_list(GList *list, const char *name)
+{
+  GList *link;
+  for (link = list;
+       link;
+       link = link->next)
+    {
+      if (!strcmp (name, ((GIrNode *)link->data)->name))
+       return link;
+    }
+  return NULL;
+}
+
+
+
 static GList *
 post_filter_varargs_functions (GList *list, GList ** varargs_callbacks_out)
 {
@@ -3229,22 +3288,59 @@ post_filter_varargs_functions (GList *list, GList ** varargs_callbacks_out)
 
              if (node->type->is_interface)
                {
-                 GList *callback;
-                 for (callback = varargs_callbacks;
-                      callback;
-                      callback = callback->next)
-                   {
-                     if (!strcmp (node->type->interface,
-                                  ((GIrNode *)callback->data)->name))
-                       {
-                         list = g_list_delete_link (list, link);
-                         function_done = TRUE;
-                         break;
-                       }
-                   }
+       
+                 GList *callback = node_find_in_list(
+                                       varargs_callbacks, 
+                                       node->type->interface);
+                 if (callback)
+                    {
+                      list = g_list_delete_link (list, link);
+                      function_done = TRUE;
+                    }
+                    
                }
            }
        }
+
+       if (node->type == G_IR_NODE_FIELD)
+          {
+           /*
+               this is a field, if the member is a blacklisted callback, 
+               then we need to flag it as to be generated as a void*
+            */
+           GIrNodeField *fnode = (GIrNodeField *)node;
+           GIrNodeType * tnode;
+           GList *match;
+
+           if (!fnode->type)
+              continue;
+           
+           tnode = (GIrNodeType *)fnode->type;
+            /* field is not an interface. */
+           if (!tnode->is_interface)
+             continue;
+             
+           match = node_find_in_list(
+                       varargs_callbacks, tnode->interface);
+
+            if (!match)
+             continue;
+
+           /*
+               we now have a field which is pointing to an blacklisted callback.
+              so need modify the type so it points to void* and
+               is not read/or writable.
+            */
+           fnode->readable = FALSE;
+           fnode->writable = FALSE;
+           
+           tnode->tag          = GI_TYPE_TAG_VOID;
+           tnode->is_interface = FALSE;
+           tnode->is_pointer   = TRUE;
+           tnode->is_basic     = TRUE;
+         }
+
+        
     }
 
   *varargs_callbacks_out = varargs_callbacks;