vala r829 - in trunk: . gobject-introspection vapigen/vala-gen-introspect



Author: juergbi
Date: Fri Jan 11 21:44:01 2008
New Revision: 829
URL: http://svn.gnome.org/viewvc/vala?rev=829&view=rev

Log:
2008-01-11  Juerg Billeter  <j bitron ch>

	* gobject-introspection/: update from gobject-introspection SVN,
	  fixes bug 505920

	* vapigen/vala-gen-introspect/vala-gen-introspect.in: fix to work
	  with updated gobject-introspection


Added:
   trunk/gobject-introspection/gidlwriter.c
   trunk/gobject-introspection/gidlwriter.h
   trunk/gobject-introspection/girepository.h
   trunk/gobject-introspection/gmetadata.c
   trunk/gobject-introspection/scanner.c
      - copied, changed from r809, /trunk/gobject-introspection/gen-introspect.c
   trunk/gobject-introspection/scanner.h
      - copied, changed from r809, /trunk/gobject-introspection/gen-introspect.h
   trunk/gobject-introspection/scannerlexer.l
      - copied, changed from r809, /trunk/gobject-introspection/clexer.l
   trunk/gobject-introspection/scannerparser.y
      - copied, changed from r809, /trunk/gobject-introspection/cparser.y
Removed:
   trunk/gobject-introspection/clexer.l
   trunk/gobject-introspection/cparser.y
   trunk/gobject-introspection/gen-introspect.c
   trunk/gobject-introspection/gen-introspect.h
Modified:
   trunk/ChangeLog
   trunk/gobject-introspection/   (props changed)
   trunk/gobject-introspection/Makefile.am
   trunk/gobject-introspection/gidlmodule.c
   trunk/gobject-introspection/gidlmodule.h
   trunk/gobject-introspection/gidlparser.c
   trunk/gobject-introspection/gmetadata.h
   trunk/vapigen/vala-gen-introspect/vala-gen-introspect.in

Modified: trunk/gobject-introspection/Makefile.am
==============================================================================
--- trunk/gobject-introspection/Makefile.am	(original)
+++ trunk/gobject-introspection/Makefile.am	Fri Jan 11 21:44:01 2008
@@ -15,24 +15,29 @@
 	gidlnode.h \
 	gidlparser.c \
 	gidlparser.h \
+	girepository.h \
+	gmetadata.c \
 	gmetadata.h \
 	$(NULL)
 
 libgidl_la_LIBADD = \
 	$(GLIB_LIBS) \
+	$(GMODULE_LIBS) \
 	$(NULL)
 
 pkglibexecdir = $(libdir)/vala
 pkglibexec_PROGRAMS = gen-introspect
 
-BUILT_SOURCES = cparser.h
+BUILT_SOURCES = scannerparser.h
 AM_YFLAGS = -d
 
 gen_introspect_SOURCES = \
-	clexer.l \
-	cparser.y \
-	gen-introspect.c \
-	gen-introspect.h \
+	gidlwriter.c \
+	gidlwriter.h \
+	scanner.c \
+	scanner.h \
+	scannerlexer.l \
+	scannerparser.y \
 	$(NULL)
 
 gen_introspect_LDADD = \

Modified: trunk/gobject-introspection/gidlmodule.c
==============================================================================
--- trunk/gobject-introspection/gidlmodule.c	(original)
+++ trunk/gobject-introspection/gidlmodule.c	Fri Jan 11 21:44:01 2008
@@ -23,20 +23,23 @@
 
 #include "gidlmodule.h"
 #include "gidlnode.h"
-#include "gmetadata.h"
 
 #define ALIGN_VALUE(this, boundary) \
   (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
 
 
 GIdlModule *
-g_idl_module_new (const gchar *name)
+g_idl_module_new (const gchar *name, const gchar *shared_library)
 {
   GIdlModule *module;
   
   module = g_new (GIdlModule, 1);
 
   module->name = g_strdup (name);
+  if (shared_library)
+      module->shared_library = g_strdup (shared_library);
+  else
+      module->shared_library = NULL;
   module->entries = NULL;
 
   return module;
@@ -57,12 +60,12 @@
   g_free (module);
 }
 
-void  
+GMetadata *
 g_idl_module_build_metadata (GIdlModule  *module,
-			     GList       *modules,
-			     guchar     **metadata,
-			     gsize       *length)
+			     GList       *modules)
 {
+  guchar *metadata;
+  gsize length;
   gint i;
   GList *e;
   Header *header;
@@ -116,6 +119,9 @@
   header->annotations = 0; /* filled in later */
   header->size = 0; /* filled in later */
   header->namespace = write_string (module->name, strings, data, &header_size);
+  header->shared_library = (module->shared_library?
+                             write_string (module->shared_library, strings, data, &header_size)
+                             : 0);
   header->directory = ALIGN_VALUE (header_size, 4);
   header->entry_blob_size = 12;
   header->function_blob_size = 16;
@@ -202,7 +208,8 @@
   
   g_message ("reallocating to %d bytes", offset2);
 
-  *metadata = g_realloc (data, offset2);
-  *length = header->size = offset2;
+  metadata = g_realloc (data, offset2);
+  length = header->size = offset2;
+  return g_metadata_new_from_memory (metadata, length);
 }
 

Modified: trunk/gobject-introspection/gidlmodule.h
==============================================================================
--- trunk/gobject-introspection/gidlmodule.h	(original)
+++ trunk/gobject-introspection/gidlmodule.h	Fri Jan 11 21:44:01 2008
@@ -22,6 +22,7 @@
 #define __G_IDL_MODULE_H__
 
 #include <glib.h>
+#include "gmetadata.h"
 
 G_BEGIN_DECLS
 
@@ -31,16 +32,16 @@
 struct _GIdlModule
 { 
   gchar *name;
+  gchar *shared_library;
   GList *entries;
 };
 
-GIdlModule *g_idl_module_new            (const gchar *name);
+GIdlModule *g_idl_module_new            (const gchar *name,
+                                         const gchar *module_filename);
 void        g_idl_module_free           (GIdlModule  *module);
 
-void        g_idl_module_build_metadata (GIdlModule  *module,
-					 GList       *modules,
-					 guchar     **metadata,
-					 gsize       *length);
+GMetadata * g_idl_module_build_metadata (GIdlModule  *module,
+					 GList       *modules);
 
 G_END_DECLS
 

Modified: trunk/gobject-introspection/gidlparser.c
==============================================================================
--- trunk/gobject-introspection/gidlparser.c	(original)
+++ trunk/gobject-introspection/gidlparser.c	Fri Jan 11 21:44:01 2008
@@ -20,6 +20,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include <glib.h>
 #include "gidlmodule.h"
@@ -92,6 +93,11 @@
     { "void",     TYPE_TAG_VOID,    0 },
     { "gpointer", TYPE_TAG_VOID,    1 },
     { "gboolean", TYPE_TAG_BOOLEAN, 0 },
+#if 0
+    { "char",     TYPE_TAG_INT8,    0 },
+    { "gchar",    TYPE_TAG_INT8,    0 },
+    { "guchar",   TYPE_TAG_UINT8,   0 },
+#endif
     { "int8_t",   TYPE_TAG_INT8,    0 },
     { "int8",     TYPE_TAG_INT8,    0 },
     { "gint8",    TYPE_TAG_INT8,    0 },
@@ -1724,15 +1730,16 @@
     case 'n':
       if (strcmp (element_name, "namespace") == 0 && ctx->state == STATE_ROOT)
 	{
-	  const gchar *name;
+	  const gchar *name, *shared_library;
 	  
 	  name = find_attribute ("name", attribute_names, attribute_values);
+	  shared_library = find_attribute ("shared-library", attribute_names, attribute_values);
 
 	  if (name == NULL)
 	    MISSING_ATTRIBUTE (error, element_name, "name");
 	  else
 	    {
-	      ctx->current_module = g_idl_module_new (name);
+	      ctx->current_module = g_idl_module_new (name, shared_library);
 	      ctx->modules = g_list_append (ctx->modules, ctx->current_module);
 
 	      ctx->state = STATE_NAMESPACE;
@@ -1863,7 +1870,7 @@
 
     case STATE_NAMESPACE:
       if (strcmp (element_name, "namespace") == 0)
-        {
+	{
           ctx->current_module = NULL;
           ctx->state = STATE_ROOT;
         }

Added: trunk/gobject-introspection/gidlwriter.c
==============================================================================
--- (empty file)
+++ trunk/gobject-introspection/gidlwriter.c	Fri Jan 11 21:44:01 2008
@@ -0,0 +1,483 @@
+/* GObject introspection: gen-introspect
+ *
+ * Copyright (C) 2007  JÃrg Billeter
+ * Copyright (C) 2007  Johan Dahlin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author:
+ * 	JÃrg Billeter <j bitron ch>
+ */
+
+#include <stdio.h>
+#include <glib.h>
+#include "scanner.h"
+#include "gidlnode.h"
+
+typedef struct {
+  int indent;
+  FILE *output;
+} GIdlWriter;
+
+static void node_generate (GIdlWriter * writer, GIdlNode * node);
+
+static void
+g_writer_write_inline (GIdlWriter * writer, const char *s)
+{
+  fprintf (writer->output, "%s", s);
+}
+
+static void
+g_writer_write (GIdlWriter * writer, const char *s)
+{
+  int i;
+  for (i = 0; i < writer->indent; i++)
+    {
+      fprintf (writer->output, "\t");
+    }
+
+  g_writer_write_inline (writer, s);
+}
+
+static void
+g_writer_write_indent (GIdlWriter * writer, const char *s)
+{
+  g_writer_write (writer, s);
+  writer->indent++;
+}
+
+static void
+g_writer_write_unindent (GIdlWriter * writer, const char *s)
+{
+  writer->indent--;
+  g_writer_write (writer, s);
+}
+
+static void
+field_generate (GIdlWriter * writer, GIdlNodeField * node)
+{
+  char *markup =
+    g_markup_printf_escaped ("<field name=\"%s\" type=\"%s\"/>\n",
+			     node->node.name, node->type->unparsed);
+  g_writer_write (writer, markup);
+  g_free (markup);
+}
+
+static void
+value_generate (GIdlWriter * writer, GIdlNodeValue * node)
+{
+  char *markup =
+    g_markup_printf_escaped ("<member name=\"%s\" value=\"%d\"/>\n",
+			     node->node.name, node->value);
+  g_writer_write (writer, markup);
+  g_free (markup);
+}
+
+static void
+constant_generate (GIdlWriter * writer, GIdlNodeConstant * node)
+{
+  char *markup =
+    g_markup_printf_escaped
+    ("<constant name=\"%s\" type=\"%s\" value=\"%s\"/>\n", node->node.name,
+     node->type->unparsed, node->value);
+  g_writer_write (writer, markup);
+  g_free (markup);
+}
+
+static void
+property_generate (GIdlWriter * writer, GIdlNodeProperty * node)
+{
+  char *markup =
+    g_markup_printf_escaped ("<property name=\"%s\" "
+			     "type=\"%s\" "
+			     "readable=\"%s\" "
+			     "writable=\"%s\" "
+			     "construct=\"%s\" "
+			     "construct-only=\"%s\"/>\n",
+			     node->node.name,
+			     node->type->unparsed,
+			     node->readable ? "1" : "0",
+			     node->writable ? "1" : "0",
+			     node->construct ? "1" : "0",
+			     node->construct_only ? "1" : "0");
+  g_writer_write (writer, markup);
+  g_free (markup);
+}
+
+static void
+function_generate (GIdlWriter * writer, GIdlNodeFunction * node)
+{
+  const char *tag_name;
+  GString *markup_s;
+  gchar *markup;
+  
+  if (node->node.type == G_IDL_NODE_CALLBACK)
+    tag_name = "callback";
+  else if (node->is_constructor)
+    tag_name = "constructor";
+  else if (node->is_method)
+    tag_name = "method";
+  else
+    tag_name = "function";
+
+  markup_s = g_string_new ("<");
+  g_string_append_printf (markup_s,
+			  "%s name=\"%s\"",
+			  tag_name, node->node.name);
+
+  if (node->node.type != G_IDL_NODE_CALLBACK)
+    g_string_append_printf (markup_s,
+			    g_markup_printf_escaped (" symbol=\"%s\"", node->symbol));
+
+  if (node->deprecated)
+    g_string_append_printf (markup_s, " deprecated=\"1\"");
+
+  g_string_append (markup_s, ">\n");
+  
+  g_writer_write_indent (writer, markup_s->str);
+  g_string_free (markup_s, TRUE);
+
+  markup =
+    g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
+			     node->result->type->unparsed);
+  g_writer_write (writer, markup);
+  g_free (markup);
+
+  if (node->parameters != NULL)
+    {
+      GList *l;
+      g_writer_write_indent (writer, "<parameters>\n");
+      for (l = node->parameters; l != NULL; l = l->next)
+	{
+	  GIdlNodeParam *param = l->data;
+	  markup =
+	    g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
+				     param->node.name, param->type->unparsed);
+	  g_writer_write (writer, markup);
+	  g_free (markup);
+	}
+      g_writer_write_unindent (writer, "</parameters>\n");
+    }
+  markup = g_strdup_printf ("</%s>\n", tag_name);
+  g_writer_write_unindent (writer, markup);
+  g_free (markup);
+}
+
+static void
+vfunc_generate (GIdlWriter * writer, GIdlNodeVFunc * node)
+{
+  char *markup =
+    g_markup_printf_escaped ("<vfunc name=\"%s\">\n", node->node.name);
+  g_writer_write_indent (writer, markup);
+  g_free (markup);
+  markup =
+    g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
+			     node->result->type->unparsed);
+  g_writer_write (writer, markup);
+  g_free (markup);
+  if (node->parameters != NULL)
+    {
+      GList *l;
+      g_writer_write_indent (writer, "<parameters>\n");
+      for (l = node->parameters; l != NULL; l = l->next)
+	{
+	  GIdlNodeParam *param = l->data;
+	  markup =
+	    g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
+				     param->node.name, param->type->unparsed);
+	  g_writer_write (writer, markup);
+	  g_free (markup);
+	}
+      g_writer_write_unindent (writer, "</parameters>\n");
+    }
+  g_writer_write_unindent (writer, "</vfunc>\n");
+}
+
+static void
+signal_generate (GIdlWriter * writer, GIdlNodeSignal * node)
+{
+  char *markup;
+  const char *when = "LAST";
+  if (node->run_first)
+    {
+      when = "FIRST";
+    }
+  else if (node->run_cleanup)
+    {
+      when = "CLEANUP";
+    }
+  markup =
+    g_markup_printf_escaped ("<signal name=\"%s\" when=\"%s\">\n",
+			     node->node.name, when);
+  g_writer_write_indent (writer, markup);
+  g_free (markup);
+  markup =
+    g_markup_printf_escaped ("<return-type type=\"%s\"/>\n",
+			     node->result->type->unparsed);
+  g_writer_write (writer, markup);
+  g_free (markup);
+  if (node->parameters != NULL)
+    {
+      GList *l;
+      g_writer_write_indent (writer, "<parameters>\n");
+      for (l = node->parameters; l != NULL; l = l->next)
+	{
+	  GIdlNodeParam *param = l->data;
+	  markup =
+	    g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n",
+				     param->node.name, param->type->unparsed);
+	  g_writer_write (writer, markup);
+	  g_free (markup);
+	}
+      g_writer_write_unindent (writer, "</parameters>\n");
+    }
+  g_writer_write_unindent (writer, "</signal>\n");
+}
+
+static void
+interface_generate (GIdlWriter * writer, GIdlNodeInterface * node)
+{
+  GList *l;
+  char *markup;
+  if (node->node.type == G_IDL_NODE_OBJECT)
+    {
+      markup =
+	g_markup_printf_escaped ("<object name=\"%s\" "
+				 "parent=\"%s\" "
+				 "type-name=\"%s\" "
+				 "get-type=\"%s\">\n",
+				 node->node.name,
+				 node->parent,
+				 node->gtype_name,
+				 node->gtype_init);
+    }
+  else if (node->node.type == G_IDL_NODE_INTERFACE)
+    {
+      markup =
+	g_markup_printf_escaped
+	("<interface name=\"%s\" type-name=\"%s\" get-type=\"%s\">\n",
+	 node->node.name, node->gtype_name, node->gtype_init);
+    }
+
+  g_writer_write_indent (writer, markup);
+  g_free (markup);
+  if (node->node.type == G_IDL_NODE_OBJECT && node->interfaces != NULL)
+    {
+      GList *l;
+      g_writer_write_indent (writer, "<implements>\n");
+      for (l = node->interfaces; l != NULL; l = l->next)
+	{
+	  markup =
+	    g_markup_printf_escaped ("<interface name=\"%s\"/>\n",
+				     (char *) l->data);
+	  g_writer_write (writer, markup);
+	  g_free (markup);
+	}
+      g_writer_write_unindent (writer, "</implements>\n");
+    }
+  else if (node->node.type == G_IDL_NODE_INTERFACE
+	   && node->prerequisites != NULL)
+    {
+      GList *l;
+      g_writer_write_indent (writer, "<requires>\n");
+      for (l = node->prerequisites; l != NULL; l = l->next)
+	{
+	  markup =
+	    g_markup_printf_escaped ("<interface name=\"%s\"/>\n",
+				     (char *) l->data);
+	  g_writer_write (writer, markup);
+	  g_free (markup);
+	}
+      g_writer_write_unindent (writer, "</requires>\n");
+    }
+
+  for (l = node->members; l != NULL; l = l->next)
+    {
+      node_generate (writer, l->data);
+    }
+
+  if (node->node.type == G_IDL_NODE_OBJECT)
+    {
+      g_writer_write_unindent (writer, "</object>\n");
+    }
+  else if (node->node.type == G_IDL_NODE_INTERFACE)
+    {
+      g_writer_write_unindent (writer, "</interface>\n");
+    }
+}
+
+static void
+struct_generate (GIdlWriter * writer, GIdlNodeStruct * node)
+{
+  GList *l;
+  char *markup =
+    g_markup_printf_escaped ("<struct name=\"%s\">\n", node->node.name);
+  g_writer_write_indent (writer, markup);
+  g_free (markup);
+  for (l = node->members; l != NULL; l = l->next)
+    {
+      node_generate (writer, l->data);
+    }
+  g_writer_write_unindent (writer, "</struct>\n");
+}
+
+static void
+union_generate (GIdlWriter * writer, GIdlNodeUnion * node)
+{
+  GList *l;
+  char *markup =
+    g_markup_printf_escaped ("<union name=\"%s\">\n", node->node.name);
+  g_writer_write_indent (writer, markup);
+  g_free (markup);
+  for (l = node->members; l != NULL; l = l->next)
+    {
+      node_generate (writer, l->data);
+    }
+  g_writer_write_unindent (writer, "</union>\n");
+}
+
+static void
+boxed_generate (GIdlWriter * writer, GIdlNodeBoxed * node)
+{
+  GList *l;
+  char *markup =
+    g_markup_printf_escaped
+    ("<boxed name=\"%s\" type-name=\"%s\" get-type=\"%s\">\n",
+     node->node.name, node->gtype_name, node->gtype_init);
+  g_writer_write_indent (writer, markup);
+  g_free (markup);
+  for (l = node->members; l != NULL; l = l->next)
+    {
+      node_generate (writer, l->data);
+    }
+  g_writer_write_unindent (writer, "</boxed>\n");
+}
+
+static void
+enum_generate (GIdlWriter * writer, GIdlNodeEnum * node)
+{
+  GList *l;
+  char *markup;
+  const char *tag_name = NULL;
+
+  if (node->node.type == G_IDL_NODE_ENUM)
+    {
+      tag_name = "enum";
+    }
+  else if (node->node.type == G_IDL_NODE_FLAGS)
+    {
+      tag_name = "flags";
+    }
+  markup =
+    g_markup_printf_escaped ("<%s name=\"%s\">\n", tag_name, node->node.name);
+  g_writer_write_indent (writer, markup);
+  g_free (markup);
+
+  for (l = node->values; l != NULL; l = l->next)
+    {
+      node_generate (writer, l->data);
+    }
+
+  markup = g_strdup_printf ("</%s>\n", tag_name);
+  g_writer_write_unindent (writer, markup);
+  g_free (markup);
+}
+
+static void
+node_generate (GIdlWriter * writer, GIdlNode * node)
+{
+  switch (node->type)
+    {
+    case G_IDL_NODE_FUNCTION:
+    case G_IDL_NODE_CALLBACK:
+      function_generate (writer, (GIdlNodeFunction *) node);
+      break;
+    case G_IDL_NODE_VFUNC:
+      vfunc_generate (writer, (GIdlNodeVFunc *) node);
+      break;
+    case G_IDL_NODE_OBJECT:
+    case G_IDL_NODE_INTERFACE:
+      interface_generate (writer, (GIdlNodeInterface *) node);
+      break;
+    case G_IDL_NODE_STRUCT:
+      struct_generate (writer, (GIdlNodeStruct *) node);
+      break;
+    case G_IDL_NODE_UNION:
+      union_generate (writer, (GIdlNodeUnion *) node);
+      break;
+    case G_IDL_NODE_BOXED:
+      boxed_generate (writer, (GIdlNodeBoxed *) node);
+      break;
+    case G_IDL_NODE_ENUM:
+    case G_IDL_NODE_FLAGS:
+      enum_generate (writer, (GIdlNodeEnum *) node);
+      break;
+    case G_IDL_NODE_PROPERTY:
+      property_generate (writer, (GIdlNodeProperty *) node);
+      break;
+    case G_IDL_NODE_FIELD:
+      field_generate (writer, (GIdlNodeField *) node);
+      break;
+    case G_IDL_NODE_SIGNAL:
+      signal_generate (writer, (GIdlNodeSignal *) node);
+      break;
+    case G_IDL_NODE_VALUE:
+      value_generate (writer, (GIdlNodeValue *) node);
+      break;
+    case G_IDL_NODE_CONSTANT:
+      constant_generate (writer, (GIdlNodeConstant *) node);
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+g_writer_write_module (GIdlWriter * writer, GIdlModule * module)
+{
+  GList *l;
+  char *markup =
+    g_markup_printf_escaped ("<namespace name=\"%s\">\n", module->name);
+  g_writer_write_indent (writer, markup);
+  g_free (markup);
+  for (l = module->entries; l != NULL; l = l->next)
+    {
+      node_generate (writer, l->data);
+    }
+  g_writer_write_unindent (writer, "</namespace>\n");
+}
+
+void
+g_idl_writer_save_file (GIdlModule *module,
+			const gchar *filename)
+{
+  GIdlWriter *writer;
+
+  writer = g_new0 (GIdlWriter, 1);
+  
+  if (!filename)
+    writer->output = stdout;
+  else
+    writer->output = fopen (filename, "w");
+  
+  g_writer_write (writer, "<?xml version=\"1.0\"?>\n");
+  g_writer_write_indent (writer, "<api version=\"1.0\">\n");
+  g_writer_write_module (writer, module);
+  g_writer_write_unindent (writer, "</api>\n");
+
+  if (filename)
+    fclose (writer->output);
+}

Added: trunk/gobject-introspection/gidlwriter.h
==============================================================================
--- (empty file)
+++ trunk/gobject-introspection/gidlwriter.h	Fri Jan 11 21:44:01 2008
@@ -0,0 +1,26 @@
+/* GObject introspection: IDL writer
+ *
+ * Copyright (C) 2007 Johan Dahlin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __G_IDL_WRITER_H__
+#define __G_IDL_WRITER_H__
+
+void g_idl_writer_save_file (GIdlModule *module, const gchar *filename);
+
+#endif  /* __G_IDL_WRITER_H__ */

Added: trunk/gobject-introspection/girepository.h
==============================================================================
--- (empty file)
+++ trunk/gobject-introspection/girepository.h	Fri Jan 11 21:44:01 2008
@@ -0,0 +1,452 @@
+/* GObject introspection: Repository
+ *
+ * Copyright (C) 2005 Matthias Clasen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __G_IREPOSITORY_H__
+#define __G_IREPOSITORY_H__
+
+#include <glib-object.h>
+#include <gmodule.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_IREPOSITORY      (g_irepository_get_type ())
+#define G_IREPOSITORY(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj), G_TYPE_IREPOSITORY, GIRepository))
+
+typedef struct _GIRepository         GIRepository; 
+typedef struct _GIRepositoryClass    GIRepositoryClass; 
+typedef struct _GIRepositoryPrivate  GIRepositoryPrivate; 
+typedef struct _GIBaseInfo           GIBaseInfo;
+typedef struct _GICallableInfo       GICallableInfo;
+typedef struct _GIFunctionInfo       GIFunctionInfo;
+typedef struct _GICallbackInfo       GICallbackInfo;
+typedef struct _GIRegisteredTypeInfo GIRegisteredTypeInfo;
+typedef struct _GIStructInfo         GIStructInfo;
+typedef struct _GIUnionInfo          GIUnionInfo;
+typedef struct _GIEnumInfo           GIEnumInfo;
+typedef struct _GIObjectInfo         GIObjectInfo;
+typedef struct _GIInterfaceInfo      GIInterfaceInfo;
+typedef struct _GIConstantInfo       GIConstantInfo;
+typedef struct _GIValueInfo          GIValueInfo;
+typedef struct _GISignalInfo         GISignalInfo;
+typedef struct _GIVFuncInfo          GIVFuncInfo;
+typedef struct _GIPropertyInfo       GIPropertyInfo;
+typedef struct _GIFieldInfo          GIFieldInfo;
+typedef struct _GIArgInfo            GIArgInfo;
+typedef struct _GITypeInfo           GITypeInfo;
+typedef struct _GIErrorDomainInfo    GIErrorDomainInfo;
+typedef struct _GIUnresolvedInfo     GIUnresolvedInfo;
+typedef struct _GMetadata            GMetadata;
+
+struct _GIRepository 
+{ 
+  GObject parent; 
+
+  /*< private >*/
+  GIRepositoryPrivate *priv;
+};
+
+struct _GIRepositoryClass
+{ 
+  GObjectClass parent; 
+};
+
+
+/* Repository */
+
+GType         g_irepository_get_type      (void) G_GNUC_CONST;
+GIRepository *g_irepository_get_default   (void);
+const gchar * g_irepository_register      (GIRepository *repository,
+					   GMetadata    *metadata);
+void          g_irepository_unregister    (GIRepository *repository,
+					   const gchar  *namespace);
+const gchar * g_irepository_register_file (GIRepository *repository,
+					   const gchar  *filename,
+					   GError      **error);
+gboolean      g_irepository_is_registered (GIRepository *repository, 
+					   const gchar  *namespace);
+GIBaseInfo *  g_irepository_find_by_name  (GIRepository *repository,
+					   const gchar  *namespace,
+					   const gchar  *name);
+gchar      ** g_irepository_get_namespaces (GIRepository *repository);
+GIBaseInfo *  g_irepository_find_by_gtype (GIRepository *repository,
+					   GType         gtype);
+gint          g_irepository_get_n_infos   (GIRepository *repository,
+					   const gchar  *namespace);
+GIBaseInfo *  g_irepository_get_info      (GIRepository *repository,
+					   const gchar  *namespace,
+					   gint          index);
+const gchar * g_irepository_get_shared_library (GIRepository *repository,
+						const gchar  *namespace);
+/* Metadata */
+
+GMetadata *   g_metadata_new_from_memory       (guchar       *memory,
+                                                gsize         len);
+GMetadata *   g_metadata_new_from_const_memory (const guchar *memory,
+                                                gsize         len);
+GMetadata *   g_metadata_new_from_mapped_file  (GMappedFile  *mfile);
+void          g_metadata_free                  (GMetadata    *metadata);
+void          g_metadata_set_module            (GMetadata    *metadata,
+                                                GModule      *module);
+const gchar * g_metadata_get_namespace         (GMetadata    *metadata);
+
+typedef enum
+{
+  G_IREPOSITORY_ERROR_METADATA_NOT_FOUND,
+  G_IREPOSITORY_ERROR_NAMESPACE_MISMATCH,
+  G_IREPOSITORY_ERROR_LIBRARY_NOT_FOUND
+} GIRepositoryError;
+
+#define G_IREPOSITORY_ERROR (g_irepository_error_quark ())
+
+GQuark g_irepository_error_quark (void);
+
+
+/* Types of objects registered in the repository */
+
+typedef enum 
+{
+  GI_INFO_TYPE_INVALID,
+  GI_INFO_TYPE_FUNCTION,
+  GI_INFO_TYPE_CALLBACK,
+  GI_INFO_TYPE_STRUCT,
+  GI_INFO_TYPE_BOXED,
+  GI_INFO_TYPE_ENUM,
+  GI_INFO_TYPE_FLAGS,
+  GI_INFO_TYPE_OBJECT,
+  GI_INFO_TYPE_INTERFACE,
+  GI_INFO_TYPE_CONSTANT,
+  GI_INFO_TYPE_ERROR_DOMAIN,
+  GI_INFO_TYPE_UNION,
+  GI_INFO_TYPE_VALUE,
+  GI_INFO_TYPE_SIGNAL,
+  GI_INFO_TYPE_VFUNC,
+  GI_INFO_TYPE_PROPERTY,
+  GI_INFO_TYPE_FIELD,
+  GI_INFO_TYPE_ARG,
+  GI_INFO_TYPE_TYPE,
+  GI_INFO_TYPE_UNRESOLVED
+} GIInfoType;
+
+
+/* GIBaseInfo */
+
+GIBaseInfo *           g_base_info_ref              (GIBaseInfo   *info);
+void                   g_base_info_unref            (GIBaseInfo   *info);
+GIInfoType             g_base_info_get_type         (GIBaseInfo   *info);
+const gchar *          g_base_info_get_name         (GIBaseInfo   *info);
+const gchar *          g_base_info_get_namespace    (GIBaseInfo   *info);
+gboolean               g_base_info_is_deprecated    (GIBaseInfo   *info);
+const gchar *          g_base_info_get_annotation   (GIBaseInfo   *info,
+                                                     const gchar  *name);
+GIBaseInfo *           g_base_info_get_container    (GIBaseInfo   *info);
+GMetadata *            g_base_info_get_metadata     (GIBaseInfo   *info);
+
+GIBaseInfo *           g_info_new                   (GIInfoType     type,
+						     GIBaseInfo    *container,
+						     GMetadata     *metadata, 
+						     guint32       offset);
+
+
+/* GIFunctionInfo */
+
+typedef enum
+{
+  GI_FUNCTION_IS_METHOD      = 1 << 0,
+  GI_FUNCTION_IS_CONSTRUCTOR = 1 << 1,
+  GI_FUNCTION_IS_GETTER      = 1 << 2,
+  GI_FUNCTION_IS_SETTER      = 1 << 3,
+  GI_FUNCTION_WRAPS_VFUNC    = 1 << 4
+} GIFunctionInfoFlags;
+
+const gchar *           g_function_info_get_symbol     (GIFunctionInfo *info);
+GIFunctionInfoFlags     g_function_info_get_flags      (GIFunctionInfo *info);
+GIPropertyInfo *        g_function_info_get_property   (GIFunctionInfo *info);
+GIVFuncInfo *           g_function_info_get_vfunc      (GIFunctionInfo *info);
+
+typedef union 
+{
+  gboolean v_boolean;
+  gint8    v_int8;
+  guint8   v_uint8;
+  gint16   v_int16;
+  guint16  v_uint16;
+  gint32   v_int32;
+  guint32  v_uint32;
+  gint64   v_int64;
+  guint64  v_uint64;
+  gfloat   v_float;
+  gdouble  v_double;
+  gint     v_int;
+  guint    v_uint;
+  glong    v_long;
+  gulong   v_ulong;
+  gssize   v_ssize;
+  gsize    v_size;
+  gchar *  v_string;
+  gpointer v_pointer;
+} GArgument;
+
+#define G_INVOKE_ERROR (g_invoke_error_quark ())
+GQuark g_invoke_error_quark (void);
+
+typedef enum
+{
+  G_INVOKE_ERROR_FAILED,
+  G_INVOKE_ERROR_SYMBOL_NOT_FOUND,
+  G_INVOKE_ERROR_ARGUMENT_MISMATCH
+} GInvokeError;
+
+gboolean              g_function_info_invoke         (GIFunctionInfo *info, 
+						      const GArgument  *in_args,
+						      int               n_in_args,
+						      const GArgument  *out_args,
+						      int               n_out_args,
+						      GArgument        *return_value,
+						      GError          **error);
+
+
+/* GICallableInfo */
+
+typedef enum {
+  GI_TRANSFER_NOTHING,
+  GI_TRANSFER_CONTAINER,
+  GI_TRANSFER_EVERYTHING
+} GITransfer;
+
+GITypeInfo *           g_callable_info_get_return_type (GICallableInfo *info);
+GITransfer             g_callable_info_get_caller_owns (GICallableInfo *info);
+gboolean               g_callable_info_may_return_null (GICallableInfo *info);
+gint                   g_callable_info_get_n_args      (GICallableInfo *info);
+GIArgInfo *            g_callable_info_get_arg         (GICallableInfo *info,
+							gint           n);
+
+/* GIArgInfo */
+
+typedef enum  {
+  GI_DIRECTION_IN,
+  GI_DIRECTION_OUT,
+  GI_DIRECTION_INOUT
+} GIDirection;
+
+GIDirection            g_arg_info_get_direction          (GIArgInfo *info);
+gboolean               g_arg_info_is_dipper              (GIArgInfo *info);
+gboolean               g_arg_info_is_return_value        (GIArgInfo *info);
+gboolean               g_arg_info_is_optional            (GIArgInfo *info);
+gboolean               g_arg_info_may_be_null            (GIArgInfo *info);
+GITransfer             g_arg_info_get_ownership_transfer (GIArgInfo *info);
+GITypeInfo *           g_arg_info_get_type               (GIArgInfo *info);
+
+
+/* GITypeInfo */
+
+typedef enum {
+  GI_TYPE_TAG_VOID      =  0,
+  GI_TYPE_TAG_BOOLEAN   =  1,
+  GI_TYPE_TAG_INT8      =  2,
+  GI_TYPE_TAG_UINT8     =  3,
+  GI_TYPE_TAG_INT16     =  4,
+  GI_TYPE_TAG_UINT16    =  5,  
+  GI_TYPE_TAG_INT32     =  6,
+  GI_TYPE_TAG_UINT32    =  7,
+  GI_TYPE_TAG_INT64     =  8,
+  GI_TYPE_TAG_UINT64    =  9,
+  GI_TYPE_TAG_INT       = 10,
+  GI_TYPE_TAG_UINT      = 11,
+  GI_TYPE_TAG_LONG      = 12,
+  GI_TYPE_TAG_ULONG     = 13,
+  GI_TYPE_TAG_SSIZE     = 14,
+  GI_TYPE_TAG_SIZE      = 15,
+  GI_TYPE_TAG_FLOAT     = 16,
+  GI_TYPE_TAG_DOUBLE    = 17,
+  GI_TYPE_TAG_UTF8      = 18,
+  GI_TYPE_TAG_FILENAME  = 19,
+  GI_TYPE_TAG_ARRAY     = 20,
+  GI_TYPE_TAG_INTERFACE = 21,
+  GI_TYPE_TAG_GLIST     = 22,
+  GI_TYPE_TAG_GSLIST    = 23,
+  GI_TYPE_TAG_GHASH     = 24,
+  GI_TYPE_TAG_ERROR     = 25
+} GITypeTag;
+
+gboolean               g_type_info_is_pointer          (GITypeInfo *info);
+GITypeTag              g_type_info_get_tag             (GITypeInfo *info);
+GITypeInfo *           g_type_info_get_param_type      (GITypeInfo *info,
+						        gint       n);
+GIBaseInfo *           g_type_info_get_interface       (GITypeInfo *info);
+gint                   g_type_info_get_array_length    (GITypeInfo *info);
+gboolean               g_type_info_is_zero_terminated  (GITypeInfo *info);
+
+gint                   g_type_info_get_n_error_domains (GITypeInfo *info);
+GIErrorDomainInfo     *g_type_info_get_error_domain    (GITypeInfo *info,
+							gint       n);
+
+/* GIErrorDomainInfo */
+
+const gchar *          g_error_domain_info_get_quark   (GIErrorDomainInfo *info);
+GIInterfaceInfo *           g_error_domain_info_get_codes (GIErrorDomainInfo *info);
+
+
+/* GIValueInfo */
+ 
+glong                  g_value_info_get_value      (GIValueInfo *info);
+
+
+/* GIFieldInfo */
+
+typedef enum
+{
+  GI_FIELD_IS_READABLE = 1 << 0,
+  GI_FIELD_IS_WRITABLE = 1 << 1
+} GIFieldInfoFlags;
+
+GIFieldInfoFlags       g_field_info_get_flags      (GIFieldInfo *info);
+gint                   g_field_info_get_size       (GIFieldInfo *info);
+gint                   g_field_info_get_offset     (GIFieldInfo *info);
+GITypeInfo *           g_field_info_get_type       (GIFieldInfo *info);
+
+
+/* GIUnionInfo */
+gint                   g_union_info_get_n_fields  (GIUnionInfo *info);
+GIFieldInfo *          g_union_info_get_field     (GIUnionInfo *info,
+					           gint         n);
+gint                   g_union_info_get_n_methods (GIUnionInfo *info);
+GIFunctionInfo *       g_union_info_get_method    (GIUnionInfo *info,
+						   gint         n);
+gboolean               g_union_info_is_discriminated (GIUnionInfo *info);
+gint                   g_union_info_get_discriminator_offset (GIUnionInfo *info);
+GITypeInfo *           g_union_info_get_discriminator_type (GIUnionInfo *info);
+GIConstantInfo *       g_union_info_get_discriminator      (GIUnionInfo *info,
+					                    gint         n);
+
+
+/* GIStructInfo */
+gint                   g_struct_info_get_n_fields  (GIStructInfo *info);
+GIFieldInfo *          g_struct_info_get_field     (GIStructInfo *info,
+						    gint         n);
+gint                   g_struct_info_get_n_methods (GIStructInfo *info);
+GIFunctionInfo *       g_struct_info_get_method    (GIStructInfo *info,
+						    gint         n);
+GIFunctionInfo *       g_struct_info_find_method   (GIStructInfo *info,
+						    const gchar *name);
+
+/* GIRegisteredTypeInfo */
+
+const gchar *          g_registered_type_info_get_type_name (GIRegisteredTypeInfo *info);
+const gchar *          g_registered_type_info_get_type_init (GIRegisteredTypeInfo *info);
+
+
+/* GIEnumInfo */
+
+gint                   g_enum_info_get_n_values             (GIEnumInfo      *info);
+GIValueInfo  *         g_enum_info_get_value                (GIEnumInfo      *info,
+							     gint            n);
+
+/* GIObjectInfo */
+
+const gchar *          g_object_info_get_type_name 	    (GIObjectInfo    *info);
+const gchar *          g_object_info_get_type_init 	    (GIObjectInfo    *info);
+GIObjectInfo *         g_object_info_get_parent             (GIObjectInfo    *info);
+gint                   g_object_info_get_n_interfaces       (GIObjectInfo    *info);
+GIInterfaceInfo *      g_object_info_get_interface          (GIObjectInfo    *info,
+							     gint            n);
+gint                   g_object_info_get_n_fields           (GIObjectInfo    *info);
+GIFieldInfo *          g_object_info_get_field              (GIObjectInfo    *info,
+							     gint            n);
+gint                   g_object_info_get_n_properties       (GIObjectInfo    *info);
+GIPropertyInfo *       g_object_info_get_property           (GIObjectInfo    *info,
+							     gint            n);
+gint                   g_object_info_get_n_methods          (GIObjectInfo    *info);
+GIFunctionInfo *       g_object_info_get_method             (GIObjectInfo    *info,
+							     gint            n);
+GIFunctionInfo *       g_object_info_find_method            (GIObjectInfo *info,
+							     const gchar *name);
+gint                   g_object_info_get_n_signals          (GIObjectInfo    *info);
+GISignalInfo *         g_object_info_get_signal             (GIObjectInfo    *info,
+							     gint            n);
+gint                   g_object_info_get_n_vfuncs           (GIObjectInfo    *info);
+GIVFuncInfo *          g_object_info_get_vfunc              (GIObjectInfo    *info,
+							     gint            n);
+gint                   g_object_info_get_n_constants        (GIObjectInfo    *info);
+GIConstantInfo *       g_object_info_get_constant           (GIObjectInfo    *info,
+							     gint            n);
+
+							     
+/* GIInterfaceInfo */
+
+gint                   g_interface_info_get_n_prerequisites (GIInterfaceInfo *info);
+GIBaseInfo *           g_interface_info_get_prerequisite    (GIInterfaceInfo *info,
+							     gint        n);
+gint                   g_interface_info_get_n_properties    (GIInterfaceInfo *info);
+GIPropertyInfo *       g_interface_info_get_property        (GIInterfaceInfo *info,
+							     gint        n);
+gint                   g_interface_info_get_n_methods       (GIInterfaceInfo *info);
+GIFunctionInfo *       g_interface_info_get_method          (GIInterfaceInfo *info,
+							     gint        n);
+GIFunctionInfo *       g_interface_info_find_method         (GIInterfaceInfo *info,
+		       				             const gchar *name);
+gint                   g_interface_info_get_n_signals       (GIInterfaceInfo *info);
+GISignalInfo *         g_interface_info_get_signal          (GIInterfaceInfo *info,
+							     gint        n);
+gint                   g_interface_info_get_n_vfuncs        (GIInterfaceInfo *info);
+GIVFuncInfo *          g_interface_info_get_vfunc           (GIInterfaceInfo *info,
+							     gint        n);
+gint                   g_interface_info_get_n_constants     (GIInterfaceInfo *info);
+GIConstantInfo *       g_interface_info_get_constant        (GIInterfaceInfo *info,
+							     gint        n);
+
+
+/* GIPropertyInfo  */
+
+GParamFlags             g_property_info_get_flags                (GIPropertyInfo         *info);
+GITypeInfo *            g_property_info_get_type                 (GIPropertyInfo         *info);
+
+
+/* GISignalInfo */
+
+GSignalFlags            g_signal_info_get_flags                  (GISignalInfo           *info);
+GIVFuncInfo *           g_signal_info_get_class_closure          (GISignalInfo           *info);
+gboolean                g_signal_info_true_stops_emit            (GISignalInfo           *info);
+
+
+/* GIVFuncInfo */
+
+typedef enum
+{
+  GI_VFUNC_MUST_CHAIN_UP     = 1 << 0,
+  GI_VFUNC_MUST_OVERRIDE     = 1 << 1,
+  GI_VFUNC_MUST_NOT_OVERRIDE = 1 << 2
+} GIVFuncInfoFlags;
+
+GIVFuncInfoFlags        g_vfunc_info_get_flags                   (GIVFuncInfo            *info);
+gint                    g_vfunc_info_get_offset                  (GIVFuncInfo            *info);
+GISignalInfo *          g_vfunc_info_get_signal                  (GIVFuncInfo            *info);
+
+
+/* GIConstantInfo */
+
+GITypeInfo *            g_constant_info_get_type                 (GIConstantInfo         *info);
+gint                    g_constant_info_get_value                (GIConstantInfo         *info,
+								  GArgument             *value);
+
+
+G_END_DECLS
+
+#endif  /* __G_IREPOSITORY_H__ */
+

Added: trunk/gobject-introspection/gmetadata.c
==============================================================================
--- (empty file)
+++ trunk/gobject-introspection/gmetadata.c	Fri Jan 11 21:44:01 2008
@@ -0,0 +1,1876 @@
+/* GObject introspection: metadata validation, auxiliary functions 
+ * related to the binary metadata format
+ *
+ * Copyright (C) 2005 Matthias Clasen
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <glib.h>
+
+#include "gmetadata.h"
+
+
+#define ALIGN_VALUE(this, boundary) \
+  (( ((unsigned long)(this)) + (((unsigned long)(boundary)) -1)) & (~(((unsigned long)(boundary))-1)))
+
+
+DirEntry *
+g_metadata_get_dir_entry (GMetadata *metadata,
+			  guint16    index)
+{
+  Header *header = (Header *)metadata->data;
+
+  return (DirEntry *)&metadata->data[header->directory + (index - 1) * header->entry_blob_size];
+}
+
+void    
+g_metadata_check_sanity (void)
+{
+  /* Check that struct layout is as we expect */
+  g_assert (sizeof (Header) == 100);
+  g_assert (sizeof (DirEntry) == 12);
+  g_assert (sizeof (SimpleTypeBlob) == 4);
+  g_assert (sizeof (ArgBlob) == 12);
+  g_assert (sizeof (SignatureBlob) == 8);
+  g_assert (sizeof (CommonBlob) == 8);
+  g_assert (sizeof (FunctionBlob) == 16);
+  g_assert (sizeof (InterfaceTypeBlob) == 4);
+  g_assert (sizeof (ArrayTypeBlob) == 8);
+  g_assert (sizeof (ParamTypeBlob) == 4);
+  g_assert (sizeof (ErrorTypeBlob) == 4);
+  g_assert (sizeof (ErrorDomainBlob) == 16);
+  g_assert (sizeof (ValueBlob) == 12);
+  g_assert (sizeof (FieldBlob) == 12);
+  g_assert (sizeof (RegisteredTypeBlob) == 16);
+  g_assert (sizeof (StructBlob) == 20);
+  g_assert (sizeof (EnumBlob) == 20);
+  g_assert (sizeof (PropertyBlob) == 12);
+  g_assert (sizeof (SignalBlob) == 12);
+  g_assert (sizeof (VFuncBlob) == 16);
+  g_assert (sizeof (ObjectBlob) == 32);
+  g_assert (sizeof (InterfaceBlob) == 28);
+  g_assert (sizeof (ConstantBlob) == 20);
+  g_assert (sizeof (AnnotationBlob) == 12);
+  g_assert (sizeof (UnionBlob) == 28);
+}
+
+
+static gboolean
+is_aligned (guint32 offset)
+{
+  return offset == ALIGN_VALUE (offset, 4);
+}
+
+#define MAX_NAME_LEN 200
+
+static gboolean
+is_name (const guchar *data, guint32 offset)
+{
+  gchar *name;
+
+  name = (gchar*)&data[offset];
+  
+  if (!memchr (name, '\0', MAX_NAME_LEN))
+    return FALSE;
+  
+  if (strspn (name, G_CSET_a_2_z G_CSET_A_2_Z G_CSET_DIGITS "-_") < strlen (name))
+    return FALSE;
+  
+  return TRUE;
+}
+
+static gboolean 
+validate_header (GMetadata  *metadata,
+		 GError    **error)
+{
+  Header *header;
+
+  if (metadata->len < sizeof (Header))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  header = (Header *)metadata->data;
+
+  if (strncmp (header->magic, G_IDL_MAGIC, 16) != 0)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_HEADER,
+		   "Magic string not found");
+      return FALSE;
+      
+    }
+
+  if (header->major_version != 1 || header->minor_version != 0)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_HEADER,
+		   "Version mismatch");
+      return FALSE;
+      
+    }
+
+  if (header->n_entries < header->n_local_entries)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_HEADER,
+		   "Inconsistent entry counts");
+      return FALSE; 
+    }
+
+  if (header->size != metadata->len)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_HEADER,
+		   "Metadata size mismatch");
+      return FALSE; 
+    }
+
+  if (header->entry_blob_size != 12 ||
+      header->function_blob_size != 16 ||
+      header->callback_blob_size != 12 ||
+      header->signal_blob_size != 12 ||
+      header->vfunc_blob_size != 16 ||
+      header->arg_blob_size != 12 ||
+      header->property_blob_size != 12 ||
+      header->field_blob_size != 12 ||
+      header->value_blob_size != 12 ||
+      header->constant_blob_size != 20 ||
+      header->error_domain_blob_size != 16 ||
+      header->annotation_blob_size != 12 ||
+      header->signature_blob_size != 8 ||
+      header->enum_blob_size != 20 ||
+      header->struct_blob_size != 20 ||
+      header->object_blob_size != 32 ||
+      header->interface_blob_size != 28 ||
+      header->union_blob_size != 28)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_HEADER,
+		   "Blob size mismatch");
+      return FALSE; 
+    }
+
+  if (!is_aligned (header->directory))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_HEADER,
+		   "Misaligned directory");
+      return FALSE; 
+    }
+
+  if (!is_aligned (header->annotations))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_HEADER,
+		   "Misaligned annotations");
+      return FALSE; 
+    }
+
+  if (header->annotations == 0 && header->n_annotations > 0)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_HEADER,
+		   "Wrong number of annotations");
+      return FALSE; 
+    }
+
+  if (!is_name (metadata->data, header->namespace))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_HEADER,
+		   "Invalid namespace name");
+      return FALSE; 
+    }
+
+  return TRUE;
+}
+
+static gboolean validate_type_blob (GMetadata     *metadata,
+				    guint32        offset,
+				    guint32        signature_offset,
+				    gboolean       return_type,
+				    GError       **error);
+
+static gboolean
+validate_array_type_blob (GMetadata     *metadata,
+			  guint32        offset,
+			  guint32        signature_offset,
+			  gboolean       return_type,
+			  GError       **error)
+{
+  ArrayTypeBlob *blob;
+
+  blob = (ArrayTypeBlob*)&metadata->data[offset];
+
+  if (!blob->pointer)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Pointer type exected for tag %d", blob->tag);
+      return FALSE;	  
+    }
+
+  /* FIXME validate length */
+
+  if (!validate_type_blob (metadata,
+			   offset + G_STRUCT_OFFSET (ArrayTypeBlob, type),
+			   0, FALSE, error))
+    return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+validate_iface_type_blob (GMetadata     *metadata,
+			  guint32        offset,
+			  guint32        signature_offset,
+			  gboolean       return_type,
+			  GError       **error)
+{
+  InterfaceTypeBlob *blob;
+  Header *header;
+
+  header = (Header *)metadata->data;
+
+  blob = (InterfaceTypeBlob*)&metadata->data[offset];
+
+  if (blob->interface == 0 || blob->interface > header->n_entries)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid directory index %d", blob->interface);
+      return FALSE;	        
+    }
+
+  return TRUE;
+}
+
+static gboolean
+validate_param_type_blob (GMetadata     *metadata,
+			  guint32        offset,
+			  guint32        signature_offset,
+			  gboolean       return_type,
+			  gint           n_params,
+			  GError       **error)
+{
+  ParamTypeBlob *blob;
+  gint i;
+
+  blob = (ParamTypeBlob*)&metadata->data[offset];
+
+  if (!blob->pointer)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Pointer type exected for tag %d", blob->tag);
+      return FALSE;	  
+    }
+  
+  if (blob->n_types != n_params)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Parameter type number mismatch");
+      return FALSE;	        
+    }
+  
+  for (i = 0; i < n_params; i++)
+    {
+      if (!validate_type_blob (metadata,
+			       offset + sizeof (ParamTypeBlob) +
+			       i * sizeof (SimpleTypeBlob),
+			       0, FALSE, error))
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean
+validate_error_type_blob (GMetadata     *metadata,
+			  guint32        offset,
+			  guint32        signature_offset,
+			  gboolean       return_type,
+			  GError       **error)
+{
+  ErrorTypeBlob *blob;
+  Header *header;
+  gint i;
+  DirEntry *entry;
+
+  blob = (ErrorTypeBlob*)&metadata->data[offset];
+
+  header = (Header *)metadata->data;
+
+  if (!blob->pointer)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Pointer type exected for tag %d", blob->tag);
+      return FALSE;	  
+    }
+  
+  for (i = 0; i < blob->n_domains; i++)
+    {
+      if (blob->domains[i] == 0 || blob->domains[i] > header->n_entries)
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Invalid directory index %d", blob->domains[i]);
+	  return FALSE;	        
+	}
+
+      entry = g_metadata_get_dir_entry (metadata, blob->domains[i]);
+
+      if (entry->blob_type != BLOB_TYPE_ERROR_DOMAIN &&
+	  (entry->local || entry->blob_type != BLOB_TYPE_INVALID))
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Wrong blob type");
+	  return FALSE;	        
+	}
+    }
+
+  return TRUE;
+}
+
+static gboolean
+validate_type_blob (GMetadata     *metadata,
+		    guint32        offset,
+		    guint32        signature_offset,
+		    gboolean       return_type,
+		    GError       **error)
+{
+  SimpleTypeBlob *simple;
+  InterfaceTypeBlob *iface;
+  
+  simple = (SimpleTypeBlob *)&metadata->data[offset];
+
+  if (simple->reserved == 0 && 
+      simple->reserved2 == 0)
+    {
+      if (simple->tag >= TYPE_TAG_ARRAY)
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Wrong tag in simple type");
+	  return FALSE;
+	}
+      
+      if (simple->tag >= TYPE_TAG_UTF8 &&
+	  !simple->pointer)
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Pointer type exected for tag %d", simple->tag);
+	  return FALSE;	  
+	}
+
+      return TRUE;
+    }
+
+  iface = (InterfaceTypeBlob*)&metadata->data[simple->offset];
+
+  switch (iface->tag)
+    {
+    case TYPE_TAG_ARRAY:
+      if (!validate_array_type_blob (metadata, simple->offset, 
+				     signature_offset, return_type, error))
+	return FALSE;
+      break;
+    case TYPE_TAG_INTERFACE:
+      if (!validate_iface_type_blob (metadata, simple->offset, 
+				     signature_offset, return_type, error))
+	return FALSE;
+      break;
+    case TYPE_TAG_LIST:
+    case TYPE_TAG_SLIST:
+      if (!validate_param_type_blob (metadata, simple->offset, 
+				     signature_offset, return_type, 1, error))
+	return FALSE;
+      break;
+    case TYPE_TAG_HASH:
+      if (!validate_param_type_blob (metadata, simple->offset, 
+				     signature_offset, return_type, 2, error))
+	return FALSE;
+      break;
+    case TYPE_TAG_ERROR:
+      if (!validate_error_type_blob (metadata, simple->offset, 
+				     signature_offset, return_type, error))
+	return FALSE;
+      break;
+    default:
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Wrong tag in complex type");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean
+validate_arg_blob (GMetadata     *metadata,
+		   guint32        offset,
+		   guint32        signature_offset,
+		   GError       **error)
+{
+  ArgBlob *blob;
+
+  if (metadata->len < offset + sizeof (ArgBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (ArgBlob*) &metadata->data[offset];
+
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid argument name");
+      return FALSE; 
+    }
+ 
+  if (!validate_type_blob (metadata, 
+			   offset + G_STRUCT_OFFSET (ArgBlob, arg_type), 
+			   signature_offset, FALSE, error))
+    return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+validate_signature_blob (GMetadata     *metadata,
+			 guint32        offset,
+			 GError       **error)
+{
+  SignatureBlob *blob;
+  gint i;
+
+  if (metadata->len < offset + sizeof (SignatureBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (SignatureBlob*) &metadata->data[offset];
+
+  if (blob->return_type.offset != 0)
+    {
+      if (!validate_type_blob (metadata, 
+			       offset + G_STRUCT_OFFSET (SignatureBlob, return_type), 
+			       offset, TRUE, error))
+	return FALSE;
+    }
+
+  for (i = 0; i < blob->n_arguments; i++)
+    {
+      if (!validate_arg_blob (metadata, 
+			      offset + sizeof (SignatureBlob) + 
+			      i * sizeof (ArgBlob), 
+			      offset, 
+			      error))
+	return FALSE;
+    }
+
+  /* FIXME check constraints on return_value */
+  /* FIXME check array-length pairs */
+  return TRUE;
+}
+
+static gboolean
+validate_function_blob (GMetadata     *metadata,
+			guint32        offset,
+			guint16        container_type,
+			GError       **error)
+{
+  FunctionBlob *blob;
+
+  if (metadata->len < offset + sizeof (FunctionBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (FunctionBlob*) &metadata->data[offset];
+
+  if (blob->blob_type != BLOB_TYPE_FUNCTION)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Wrong blob type");
+      return FALSE;
+    }
+
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid function name");
+      return FALSE; 
+    }
+  
+  if (!is_name (metadata->data, blob->symbol))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid function symbol");
+      return FALSE; 
+    }
+  
+  if (blob->constructor)
+    {
+      switch (container_type)
+	{
+	case BLOB_TYPE_BOXED:
+	case BLOB_TYPE_OBJECT:
+	case BLOB_TYPE_INTERFACE:
+	  break;
+	default:
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Constructor not allowed");
+	  return FALSE;
+	}
+    }
+
+  if (blob->setter || blob->getter || blob->wraps_vfunc)
+    {
+      switch (container_type)
+	{
+	case BLOB_TYPE_OBJECT:
+	case BLOB_TYPE_INTERFACE:
+	  break;
+	default:
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Setter, getter or wrapper not allowed");
+	  return FALSE;
+	}
+    }
+
+  if (blob->index)
+    {
+      if (!(blob->setter || blob->getter || blob->wraps_vfunc))
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Must be setter, getter or wrapper");
+	  return FALSE;
+	}
+    }
+
+  /* FIXME: validate index range */
+  /* FIXME: validate "this" argument for methods */
+  /* FIXME: validate return type for constructors */
+
+  if (!validate_signature_blob (metadata, blob->signature, error))
+    return FALSE;
+	
+  return TRUE;
+}
+
+static gboolean
+validate_callback_blob (GMetadata     *metadata,
+			guint32        offset,
+			GError       **error)
+{
+  CallbackBlob *blob;
+
+  if (metadata->len < offset + sizeof (CallbackBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (CallbackBlob*) &metadata->data[offset];
+
+  if (blob->blob_type != BLOB_TYPE_CALLBACK)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Wrong blob type");
+      return FALSE;
+    }
+
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid callback name");
+      return FALSE; 
+    }
+  
+  if (!validate_signature_blob (metadata, blob->signature, error))
+    return FALSE;
+	
+  return TRUE;
+}
+
+static gboolean
+validate_constant_blob (GMetadata     *metadata,
+			guint32        offset,
+			GError       **error)
+{
+  gint value_size[] = {
+    0, 4, 1, 1, 2, 2, 4, 4, 8, 8, 
+    sizeof (gint), sizeof (guint), 
+    sizeof (glong), sizeof (gulong),
+    sizeof (gssize), sizeof (gsize),
+    sizeof (gfloat), sizeof (gdouble), 
+    0, 0
+  }; 
+  ConstantBlob *blob;
+  SimpleTypeBlob *type;
+
+  if (metadata->len < offset + sizeof (ConstantBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (ConstantBlob*) &metadata->data[offset];
+
+  if (blob->blob_type != BLOB_TYPE_CONSTANT)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Wrong blob type");
+      return FALSE;
+    }
+
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid constant name");
+      return FALSE; 
+    }
+  
+  if (!validate_type_blob (metadata, offset + G_STRUCT_OFFSET (ConstantBlob, type), 
+			   0, FALSE, error))
+    return FALSE;
+
+  if (!is_aligned (blob->offset))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Misaligned constant value");
+      return FALSE;
+    }
+  
+  type = (SimpleTypeBlob *)&metadata->data[offset + G_STRUCT_OFFSET (ConstantBlob, type)];
+  if (type->reserved == 0)
+    {
+      if (type->tag == 0)
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Constant value type void");
+	  return FALSE;
+	}
+
+      if (value_size[type->tag] != 0 &&
+	  blob->size != value_size[type->tag])
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Constant value size mismatch");
+	  return FALSE;
+	}
+      /* FIXME check string values */
+    }
+
+  return TRUE;
+}
+
+static gboolean
+validate_value_blob (GMetadata     *metadata,
+		     guint32        offset,
+		     GError       **error)
+{
+  ValueBlob *blob;
+
+  if (metadata->len < offset + sizeof (ValueBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (ValueBlob*) &metadata->data[offset];
+
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid value name");
+      return FALSE; 
+    }
+  
+  return TRUE;
+}
+
+static gboolean
+validate_field_blob (GMetadata     *metadata,
+		     guint32        offset,
+		     GError       **error)
+{
+  FieldBlob *blob;
+
+  if (metadata->len < offset + sizeof (FieldBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (FieldBlob*) &metadata->data[offset];
+  
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid field name");
+      return FALSE; 
+    }
+    
+  if (!validate_type_blob (metadata,
+			   offset + G_STRUCT_OFFSET (FieldBlob, type), 
+			   0, FALSE, error))
+    return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+validate_property_blob (GMetadata     *metadata,
+			guint32        offset,
+			GError       **error)
+{
+  PropertyBlob *blob;
+
+  if (metadata->len < offset + sizeof (PropertyBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (PropertyBlob*) &metadata->data[offset];
+  
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid property name");
+      return FALSE; 
+    }
+    
+  if (!validate_type_blob (metadata,
+			   offset + G_STRUCT_OFFSET (PropertyBlob, type), 
+			   0, FALSE, error))
+    return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+validate_signal_blob (GMetadata     *metadata,
+		      guint32        offset,
+		      guint32        container_offset,
+		      GError       **error)
+{
+  SignalBlob *blob;
+  gint n_signals;
+
+  if (metadata->len < offset + sizeof (SignalBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (SignalBlob*) &metadata->data[offset];
+
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid signal name");
+      return FALSE; 
+    }
+  
+  if ((blob->run_first != 0) + 
+      (blob->run_last != 0) + 
+      (blob->run_cleanup != 0) != 1)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid signal run flags");
+      return FALSE; 
+    }
+
+  if (blob->has_class_closure)
+    {
+      if (((CommonBlob*)&metadata->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
+	{
+	  ObjectBlob *object;
+
+	  object = (ObjectBlob*)&metadata->data[container_offset];
+	  
+	  n_signals = object->n_signals;
+	}
+      else
+	{
+	  InterfaceBlob *iface;
+	  
+	  iface = (InterfaceBlob*)&metadata->data[container_offset];
+	  
+	  n_signals = iface->n_signals;
+	}
+
+      if (blob->class_closure >= n_signals)
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Invalid class closure index");
+	  return FALSE; 
+	}
+    }
+
+  if (!validate_signature_blob (metadata, blob->signature, error))
+    return FALSE;
+  
+  return TRUE;
+}
+
+static gboolean
+validate_vfunc_blob (GMetadata     *metadata,
+		     guint32        offset,
+		     guint32        container_offset,
+		     GError       **error)
+{
+  VFuncBlob *blob;
+  gint n_vfuncs;
+
+  if (metadata->len < offset + sizeof (VFuncBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (VFuncBlob*) &metadata->data[offset];
+
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid vfunc name");
+      return FALSE; 
+    }
+  
+  if (blob->class_closure)
+    {
+      if (((CommonBlob*)&metadata->data[container_offset])->blob_type == BLOB_TYPE_OBJECT)
+	{
+	  ObjectBlob *object;
+
+	  object = (ObjectBlob*)&metadata->data[container_offset];
+	  
+	  n_vfuncs = object->n_vfuncs;
+	}
+      else
+	{
+	  InterfaceBlob *iface;
+	  
+	  iface = (InterfaceBlob*)&metadata->data[container_offset];
+	  
+	  n_vfuncs = iface->n_vfuncs;
+	}
+
+      if (blob->class_closure >= n_vfuncs)
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Invalid class closure index");
+	  return FALSE; 
+	}
+    }
+
+  if (!validate_signature_blob (metadata, blob->signature, error))
+    return FALSE;
+  
+  return TRUE;
+}
+
+static gboolean
+validate_struct_blob (GMetadata     *metadata,
+		      guint32        offset,
+		      guint16        blob_type,
+		      GError       **error)
+{
+  StructBlob *blob;
+  gint i;
+
+  if (metadata->len < offset + sizeof (StructBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (StructBlob*) &metadata->data[offset];
+
+  if (blob->blob_type != blob_type)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Wrong blob type");
+      return FALSE;
+    }
+  
+  if ((blob->blob_type == BLOB_TYPE_BOXED && blob->unregistered) ||
+      (blob->blob_type == BLOB_TYPE_STRUCT && !blob->unregistered))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Registration/blob type mismatch");
+      return FALSE;
+    }
+
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid struct name");
+      return FALSE; 
+    }
+  
+  if (blob_type == BLOB_TYPE_BOXED)
+    {
+      if (!is_name (metadata->data, blob->gtype_name))
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Invalid boxed type name");
+	  return FALSE; 
+	}
+
+      if (!is_name (metadata->data, blob->gtype_init))
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Invalid boxed type init");
+	  return FALSE; 
+	}
+    }
+  else
+    {
+      if (blob->gtype_name || blob->gtype_init)
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Gtype data in struct");
+	  return FALSE; 
+	}
+    }
+
+  if (metadata->len < offset + sizeof (StructBlob) + 
+            blob->n_fields * sizeof (FieldBlob) +
+            blob->n_methods * sizeof (FunctionBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  for (i = 0; i < blob->n_fields; i++)
+    {
+      if (!validate_field_blob (metadata, 
+				offset + sizeof (StructBlob) + 
+				i * sizeof (FieldBlob), 
+				error))
+	return FALSE;
+    }
+
+  for (i = 0; i < blob->n_methods; i++)
+    {
+      if (!validate_function_blob (metadata, 
+				   offset + sizeof (StructBlob) + 
+				   blob->n_fields * sizeof (FieldBlob) + 
+				   i * sizeof (FunctionBlob), 
+				   blob_type,
+				   error))
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean
+validate_enum_blob (GMetadata     *metadata,
+		    guint32        offset,
+		    guint16        blob_type,
+		    GError       **error)
+{
+  EnumBlob *blob;
+  ValueBlob *v1, *v2;
+  gint i, j; 
+
+  if (metadata->len < offset + sizeof (EnumBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (EnumBlob*) &metadata->data[offset];
+
+  if (blob->blob_type != blob_type)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Wrong blob type");
+      return FALSE;
+    }
+  
+  if (!blob->unregistered)
+    {
+      if (!is_name (metadata->data, blob->gtype_name))
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Invalid enum type name");
+	  return FALSE; 
+	}
+
+      if (!is_name (metadata->data, blob->gtype_init))
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Invalid enum type init");
+	  return FALSE; 
+	}
+    }
+  else
+    {
+      if (blob->gtype_name || blob->gtype_init)
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Gtype data in unregistered enum");
+	  return FALSE; 
+	}
+    }
+
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid enum name");
+      return FALSE; 
+    }
+  
+  if (metadata->len < offset + sizeof (EnumBlob) + 
+      blob->n_values * sizeof (ValueBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+  
+  for (i = 0; i < blob->n_values; i++)
+    {
+      if (!validate_value_blob (metadata, 
+				offset + sizeof (EnumBlob) + 
+				i * sizeof (ValueBlob), 
+				error))
+	return FALSE;
+
+      v1 = (ValueBlob *)&metadata->data[offset + sizeof (EnumBlob) + 
+                                        i * sizeof (ValueBlob)];
+      for (j = 0; j < i; j++) 
+	{
+	  v2 = (ValueBlob *)&metadata->data[offset + sizeof (EnumBlob) + 
+                                            j * sizeof (ValueBlob)];
+
+	  if (v1->value == v2->value)
+	    {
+	      /* FIXME should this be an error ? */
+	      g_set_error (error,
+			   G_METADATA_ERROR,
+			   G_METADATA_ERROR_INVALID_BLOB,
+			   "Duplicate enum value");
+	      return FALSE;
+	    }
+	}
+    }
+  
+  return TRUE;
+}
+
+static gboolean
+validate_object_blob (GMetadata     *metadata,
+		      guint32        offset,
+		      GError       **error)
+{
+  Header *header;
+  ObjectBlob *blob;
+  gint i;
+  guint32 offset2;
+
+  header = (Header *)metadata->data;
+
+  if (metadata->len < offset + sizeof (ObjectBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (ObjectBlob*) &metadata->data[offset];
+
+  if (blob->blob_type != BLOB_TYPE_OBJECT)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Wrong blob type");
+      return FALSE;
+    }
+  
+  if (!is_name (metadata->data, blob->gtype_name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid object type name");
+      return FALSE; 
+    }
+  
+  if (!is_name (metadata->data, blob->gtype_init))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid object type init");
+      return FALSE; 
+    }
+  
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid object name");
+      return FALSE; 
+    }
+  
+  if (blob->parent > header->n_entries)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid parent index");
+      return FALSE; 
+    }
+
+  if (blob->parent != 0)
+    {
+      DirEntry *entry;
+
+      entry = g_metadata_get_dir_entry (metadata, blob->parent);
+      if (entry->blob_type != BLOB_TYPE_OBJECT &&
+	  (entry->local || entry->blob_type != 0))
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Parent not object");
+	  return FALSE; 
+	}
+    }
+  
+  if (metadata->len < offset + sizeof (ObjectBlob) + 
+            (blob->n_interfaces + blob->n_interfaces % 2) * 2 +
+            blob->n_fields * sizeof (FieldBlob) +
+            blob->n_properties * sizeof (PropertyBlob) +
+            blob->n_methods * sizeof (FunctionBlob) +
+            blob->n_signals * sizeof (SignalBlob) +
+            blob->n_vfuncs * sizeof (VFuncBlob) +
+            blob->n_constants * sizeof (ConstantBlob))
+     
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  offset2 = offset + sizeof (ObjectBlob);
+
+  for (i = 0; i < blob->n_interfaces; i++, offset2 += 2)
+    {
+      guint16 iface;
+      DirEntry *entry;
+
+      iface = *(guint16*)&metadata->data[offset2];
+      if (iface == 0 || iface > header->n_entries)
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Invalid interface index");
+	  return FALSE; 
+	}
+      
+      entry = g_metadata_get_dir_entry (metadata, iface);
+
+      if (entry->blob_type != BLOB_TYPE_INTERFACE &&
+	  (entry->local || entry->blob_type != 0))
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Not an interface");
+	  return FALSE; 
+	}
+    }
+
+  offset2 += 2 * (blob->n_interfaces %2);
+
+  for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
+    {
+      if (!validate_field_blob (metadata, offset2, error))
+	return FALSE;
+    }
+
+  for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
+    {
+      if (!validate_property_blob (metadata, offset2, error))
+	return FALSE;
+    }
+
+  for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
+    {
+      if (!validate_function_blob (metadata, offset2, BLOB_TYPE_OBJECT, error))
+	return FALSE;
+    }
+
+  for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
+    {
+      if (!validate_signal_blob (metadata, offset2, offset, error))
+	return FALSE;
+    }
+
+  for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
+    {
+      if (!validate_vfunc_blob (metadata, offset2, offset, error))
+	return FALSE;
+    }
+
+  for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
+    {
+      if (!validate_constant_blob (metadata, offset2, error))
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean
+validate_interface_blob (GMetadata     *metadata,
+			 guint32        offset,
+			 GError       **error)
+{
+  Header *header;
+  InterfaceBlob *blob;
+  gint i;
+  guint32 offset2;
+  
+  header = (Header *)metadata->data;
+
+  if (metadata->len < offset + sizeof (InterfaceBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  blob = (InterfaceBlob*) &metadata->data[offset];
+
+  if (blob->blob_type != BLOB_TYPE_INTERFACE)
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Wrong blob type");
+      return FALSE;
+    }
+  
+  if (!is_name (metadata->data, blob->gtype_name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid interface type name");
+      return FALSE; 
+    }
+  
+  if (!is_name (metadata->data, blob->gtype_init))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid interface type init");
+      return FALSE; 
+    }
+  
+  if (!is_name (metadata->data, blob->name))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_BLOB,
+		   "Invalid interface name");
+      return FALSE; 
+    }
+  
+  if (metadata->len < offset + sizeof (InterfaceBlob) + 
+            (blob->n_prerequisites + blob->n_prerequisites % 2) * 2 +
+            blob->n_properties * sizeof (PropertyBlob) +
+            blob->n_methods * sizeof (FunctionBlob) +
+            blob->n_signals * sizeof (SignalBlob) +
+            blob->n_vfuncs * sizeof (VFuncBlob) +
+            blob->n_constants * sizeof (ConstantBlob))
+     
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  offset2 = offset + sizeof (InterfaceBlob);
+
+  for (i = 0; i < blob->n_prerequisites; i++, offset2 += 2)
+    {
+      DirEntry *entry;
+      guint16 req;
+
+      req = *(guint16*)&metadata->data[offset2];
+      if (req == 0 || req > header->n_entries)
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Invalid prerequisite index");
+	  return FALSE; 
+	}
+
+      entry = g_metadata_get_dir_entry (metadata, req);
+      if (entry->blob_type != BLOB_TYPE_INTERFACE &&
+	  entry->blob_type != BLOB_TYPE_OBJECT &&
+	  (entry->local || entry->blob_type != 0))
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_BLOB,
+		       "Not an interface or object");
+	  return FALSE; 
+	}
+    }
+
+  offset2 += 2 * (blob->n_prerequisites % 2);
+
+  for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))
+    {
+      if (!validate_property_blob (metadata, offset2, error))
+	return FALSE;
+    }
+
+  for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
+    {
+      if (!validate_function_blob (metadata, offset2, BLOB_TYPE_INTERFACE, error))
+	return FALSE;
+    }
+  
+  for (i = 0; i < blob->n_signals; i++, offset2 += sizeof (SignalBlob))
+    {
+      if (!validate_signal_blob (metadata, offset2, offset, error))
+	return FALSE;
+    }
+  
+  for (i = 0; i < blob->n_vfuncs; i++, offset2 += sizeof (VFuncBlob))
+    {
+      if (!validate_vfunc_blob (metadata, offset2, offset, error))
+	return FALSE;
+    }
+
+  for (i = 0; i < blob->n_constants; i++, offset2 += sizeof (ConstantBlob))
+    {
+      if (!validate_constant_blob (metadata, offset2, error))
+	return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean
+validate_errordomain_blob (GMetadata     *metadata,
+			   guint32        offset,
+			   GError       **error)
+{
+  return TRUE;
+}
+
+static gboolean
+validate_union_blob (GMetadata     *metadata,
+		     guint32        offset,
+		     GError       **error)
+{
+  return TRUE;
+}
+
+static gboolean
+validate_blob (GMetadata     *metadata,
+	       guint32        offset,
+	       GError       **error)
+{
+  CommonBlob *common;
+
+  if (metadata->len < offset + sizeof (CommonBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  common = (CommonBlob*)&metadata->data[offset];
+  
+  switch (common->blob_type)
+    {
+    case BLOB_TYPE_FUNCTION:
+      if (!validate_function_blob (metadata, offset, 0, error))
+	return FALSE;
+      break;
+    case BLOB_TYPE_CALLBACK:
+      if (!validate_callback_blob (metadata, offset, error))
+	return FALSE;
+      break;
+    case BLOB_TYPE_STRUCT:
+    case BLOB_TYPE_BOXED:
+      if (!validate_struct_blob (metadata, offset, common->blob_type, error))
+	return FALSE;
+      break;
+    case BLOB_TYPE_ENUM:
+    case BLOB_TYPE_FLAGS:
+      if (!validate_enum_blob (metadata, offset, common->blob_type, error))
+	return FALSE;
+      break;
+    case BLOB_TYPE_OBJECT:
+      if (!validate_object_blob (metadata, offset, error))
+	return FALSE;
+      break;
+    case BLOB_TYPE_INTERFACE:
+      if (!validate_interface_blob (metadata, offset, error))
+	return FALSE;
+      break;
+    case BLOB_TYPE_CONSTANT:
+      if (!validate_constant_blob (metadata, offset, error))
+	return FALSE;
+      break;
+    case BLOB_TYPE_ERROR_DOMAIN:
+      if (!validate_errordomain_blob (metadata, offset, error))
+	return FALSE;
+      break;
+    case BLOB_TYPE_UNION:
+      if (!validate_union_blob (metadata, offset, error))
+	return FALSE;
+      break;
+    default:
+      g_set_error (error, 
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID_ENTRY,
+		   "Invalid blob type");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean 
+validate_directory (GMetadata     *metadata,
+		    GError       **error)
+{
+  Header *header = (Header *)metadata->data;
+  DirEntry *entry;
+  gint i;
+  
+  if (metadata->len < header->directory + header->n_entries * sizeof (DirEntry))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;
+    }
+
+  for (i = 0; i < header->n_entries; i++)
+    {
+      entry = g_metadata_get_dir_entry (metadata, i + 1);
+
+      if (!is_name (metadata->data, entry->name))
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_DIRECTORY,
+		       "Invalid entry name");
+	  return FALSE; 
+	}
+      
+      if ((entry->local && entry->blob_type == BLOB_TYPE_INVALID) ||
+	  entry->blob_type > BLOB_TYPE_UNION)
+	{
+	  g_set_error (error,
+		       G_METADATA_ERROR,
+		       G_METADATA_ERROR_INVALID_DIRECTORY,
+		       "Invalid entry type");
+	  return FALSE; 
+	}
+
+      if (i < header->n_local_entries)
+	{
+	  if (!entry->local)
+	    {
+	      g_set_error (error,
+			   G_METADATA_ERROR,
+			   G_METADATA_ERROR_INVALID_DIRECTORY,
+			   "Too few local directory entries");
+	      return FALSE;
+	    }
+
+	  if (!is_aligned (entry->offset))
+	    {
+	      g_set_error (error,
+			   G_METADATA_ERROR,
+			   G_METADATA_ERROR_INVALID_DIRECTORY,
+			   "Misaligned entry");
+	      return FALSE;
+	    }
+
+	  if (!validate_blob (metadata, entry->offset, error))
+	    return FALSE;
+	}
+      else
+	{
+	  if (entry->local)
+	    {
+	      g_set_error (error,
+			   G_METADATA_ERROR,
+			   G_METADATA_ERROR_INVALID_DIRECTORY,
+			   "Too many local directory entries");
+	      return FALSE;
+	    }
+
+	  if (!is_name (metadata->data, entry->offset))
+	    {
+	      g_set_error (error,
+			   G_METADATA_ERROR,
+			   G_METADATA_ERROR_INVALID_DIRECTORY,
+			   "Invalid namespace name");
+	      return FALSE; 
+	    }
+	}
+    }
+
+  return TRUE;
+}
+
+static gboolean
+validate_annotations (GMetadata     *metadata, 
+		      GError       **error)
+{
+  Header *header = (Header *)metadata->data;
+
+  if (header->size < header->annotations + header->n_annotations * sizeof (AnnotationBlob))
+    {
+      g_set_error (error,
+		   G_METADATA_ERROR,
+		   G_METADATA_ERROR_INVALID,
+		   "The buffer is too short");
+      return FALSE;      
+    }
+  
+  return TRUE;
+}
+
+gboolean 
+g_metadata_validate (GMetadata     *metadata,
+		     GError       **error)
+{
+  if (!validate_header (metadata, error))
+    return FALSE;
+
+  if (!validate_directory (metadata, error))
+    return FALSE;
+
+  if (!validate_annotations (metadata, error))
+    return FALSE;
+
+  return TRUE;
+}
+
+GQuark
+g_metadata_error_quark (void)
+{
+  static GQuark quark = 0;
+  if (quark == 0)
+    quark = g_quark_from_static_string ("g-metadata-error-quark");
+  return quark;
+}
+
+
+static inline void
+_g_metadata_init (GMetadata *metadata)
+{
+  Header *header;
+
+  header = (Header *) metadata->data;
+  if (header->shared_library)
+    {
+      const gchar *shlib;
+      shlib = g_metadata_get_string (metadata, header->shared_library);
+      metadata->module = g_module_open (shlib, G_MODULE_BIND_LAZY|G_MODULE_BIND_LOCAL);
+      if (metadata->module == NULL)
+        g_warning ("Failed to load shared library referenced by the metadata: %s",
+                   g_module_error ());
+    }
+}
+
+/**
+ * g_metadata_new_from_memory:
+ * @memory: address of memory chunk containing the metadata
+ * @len: length of memory chunk containing the metadata
+ * 
+ * Creates a new #GMetadata from a memory location.  The memory block
+ * pointed to by @metadata will be automatically g_free()d when the
+ * repository is destroyed.
+ * 
+ * Return value: the new #GMetadata
+ **/
+GMetadata *
+g_metadata_new_from_memory (guchar *memory, gsize len)
+{
+  GMetadata *meta;
+
+  meta = g_new0 (GMetadata, 1);
+  meta->data = memory;
+  meta->len = len;
+  meta->owns_memory = TRUE;
+  _g_metadata_init (meta);
+  return meta;
+}
+
+/**
+ * g_metadata_new_from_const_memory:
+ * @memory: address of memory chunk containing the metadata
+ * @len: length of memory chunk containing the metadata
+ * 
+ * Creates a new #GMetadata from a memory location.
+ * 
+ * Return value: the new #GMetadata
+ **/
+GMetadata *
+g_metadata_new_from_const_memory (const guchar *memory, gsize len)
+{
+  GMetadata *meta;
+
+  meta = g_new0 (GMetadata, 1);
+  meta->data = (guchar *) memory;
+  meta->len = len;
+  meta->owns_memory = FALSE;
+  _g_metadata_init (meta);
+  return meta;
+}
+
+/**
+ * g_metadata_new_from_mapped_file:
+ * @mfile: a #GMappedFile, that will be free'd when the repository is destroyed
+ * 
+ * Creates a new #GMetadata from a #GMappedFile.
+ * 
+ * Return value: the new #GMetadata
+ **/
+GMetadata *
+g_metadata_new_from_mapped_file (GMappedFile *mfile)
+{
+  GMetadata *meta;
+
+  meta = g_new0 (GMetadata, 1);
+  meta->mfile = mfile;
+  meta->owns_memory = FALSE;
+  meta->data = (guchar *) g_mapped_file_get_contents (mfile);
+  meta->len = g_mapped_file_get_length (mfile);
+  _g_metadata_init (meta);
+  return meta;
+}
+
+/**
+ * g_metadata_free:
+ * @metadata: a #GMetadata
+ * 
+ * Free a #GMetadata.
+ **/
+void
+g_metadata_free (GMetadata *metadata)
+{
+  if (metadata->mfile)
+    g_mapped_file_free (metadata->mfile);
+  else
+    if (metadata->owns_memory)
+      g_free (metadata->data);
+  if (metadata->module)
+    g_module_close (metadata->module);
+  g_free (metadata);
+}
+
+/**
+ * g_metadata_set_module:
+ * @metadata: a #GMetadata instance
+ * @module: a #GModule; takes ownership of this module
+ * 
+ * Sets the target module for all symbols referenced by the metadata.
+ **/
+void
+g_metadata_set_module (GMetadata *metadata, GModule *module)
+{
+  if (metadata->module)
+    g_module_close (metadata->module);
+  metadata->module = module;
+}
+
+const gchar *
+g_metadata_get_namespace(GMetadata *metadata)
+{
+  return g_metadata_get_string (metadata, ((Header *) metadata->data)->namespace);
+}

Modified: trunk/gobject-introspection/gmetadata.h
==============================================================================
--- trunk/gobject-introspection/gmetadata.h	(original)
+++ trunk/gobject-introspection/gmetadata.h	Fri Jan 11 21:44:01 2008
@@ -22,6 +22,9 @@
 #ifndef __G_METADATA_H__
 #define __G_METADATA_H__
 
+#include <gmodule.h>
+#include "girepository.h"
+
 G_BEGIN_DECLS
 
 #define G_IDL_MAGIC "GOBJ\nMETADATA\r\n\032"
@@ -56,6 +59,7 @@
 
   guint32 size;
   guint32 namespace;
+  guint32 shared_library;
 
   guint16 entry_blob_size;
   guint16 function_blob_size;
@@ -77,7 +81,7 @@
   guint16 interface_blob_size;
   guint16 union_blob_size;
   
-  guint16 padding;
+  guint16 padding[7];
 } Header;
 
 typedef struct
@@ -506,13 +510,20 @@
 } AnnotationBlob;
 
 
+struct _GMetadata {
+  guchar *data;
+  gsize len;
+  gboolean owns_memory;
+  GMappedFile *mfile;
+  GModule *module;
+};
 
-DirEntry *g_metadata_get_dir_entry (const guchar *metadata,
-				    guint16       index);
+DirEntry *g_metadata_get_dir_entry (GMetadata *metadata,
+				    guint16            index);
 
 void      g_metadata_check_sanity (void);
 
-#define   g_metadata_get_string(metadata,offset) ((const gchar*)&(metadata)[(offset)])
+#define   g_metadata_get_string(metadata,offset) ((const gchar*)&(metadata->data)[(offset)])
 
 
 typedef enum
@@ -528,9 +539,8 @@
 
 GQuark g_metadata_error_quark (void);
 
-gboolean g_metadata_validate (const guchar  *data,
-			      guint          len,
-			      GError       **error);
+gboolean g_metadata_validate (GMetadata  *metadata,
+			      GError    **error);
 
 
 G_END_DECLS

Copied: trunk/gobject-introspection/scanner.c (from r809, /trunk/gobject-introspection/gen-introspect.c)
==============================================================================
--- /trunk/gobject-introspection/gen-introspect.c	(original)
+++ trunk/gobject-introspection/scanner.c	Fri Jan 11 21:44:01 2008
@@ -1,6 +1,7 @@
-/* GObject introspection: gen-introspect
+/* GObject introspection: scanner
  *
- * Copyright (C) 2007  JÃrg Billeter
+ * Copyright (C) 2007-2008  JÃrg Billeter
+ * Copyright (C) 2007  Johan Dahlin
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,1352 +22,1803 @@
  * 	JÃrg Billeter <j bitron ch>
  */
 
-#include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include <errno.h>
 #include <glib.h>
 #include <glib/gstdio.h>
 #include <glib-object.h>
+#include <sys/wait.h> /* waitpid */
 #include <gmodule.h>
-#include "gen-introspect.h"
+#include "scanner.h"
+#include "gidlparser.h"
 #include "gidlmodule.h"
 #include "gidlnode.h"
+#include "gidlwriter.h"
 
 typedef GType (*TypeFunction) (void);
 
-static void node_generate (GIGenerator *igenerator, GIdlNode *node);
-static void g_igenerator_parse_macros (GIGenerator *igenerator);
+static void g_igenerator_parse_macros (GIGenerator * igenerator);
 
-static int g_idl_node_cmp (GIdlNode *a, GIdlNode *b)
+static int
+g_idl_node_cmp (GIdlNode * a, GIdlNode * b)
 {
-	if (a->type < b->type) {
-		return -1;
-	} else if (a->type > b->type) {
-		return 1;
-	} else {
-		return strcmp (a->name, b->name);
-	}
-}
-
-GIGenerator *g_igenerator_new (void)
-{
-	GIGenerator *igenerator = g_new0 (GIGenerator, 1);
-	igenerator->namespace = "";
-	igenerator->lower_case_namespace = g_strdup ("");
-	igenerator->typedef_table = g_hash_table_new (g_str_hash, g_str_equal);
-	igenerator->struct_or_union_or_enum_table = g_hash_table_new (g_str_hash, g_str_equal);
-
-	igenerator->type_map = g_hash_table_new (g_str_hash, g_str_equal);
-	igenerator->type_by_lower_case_prefix = g_hash_table_new (g_str_hash, g_str_equal);
-
-	the_igenerator = igenerator;
-
-	return igenerator;
-}
-
-static void g_igenerator_write_inline (GIGenerator *igenerator, const char *s)
-{
-	fprintf (stdout, "%s", s);
-}
-
-static void g_igenerator_write (GIGenerator *igenerator, const char *s)
-{
-	int i;
-	for (i = 0; i < igenerator->indent; i++) {
-		fprintf (stdout, "\t");
-	}
-
-	g_igenerator_write_inline (igenerator, s);
-}
-
-static void g_igenerator_write_indent (GIGenerator *igenerator, const char *s)
-{
-	g_igenerator_write (igenerator, s);
-	igenerator->indent++;
-}
-
-static void g_igenerator_write_unindent (GIGenerator *igenerator, const char *s)
-{
-	igenerator->indent--;
-	g_igenerator_write (igenerator, s);
-}
-
-static void field_generate (GIGenerator *igenerator, GIdlNodeField *node)
-{
-	char *markup = g_markup_printf_escaped ("<field name=\"%s\" type=\"%s\"/>\n", node->node.name, node->type->unparsed);
-	g_igenerator_write (igenerator, markup);
-	g_free (markup);
-}
-
-static void value_generate (GIGenerator *igenerator, GIdlNodeValue *node)
-{
-	char *markup = g_markup_printf_escaped ("<member name=\"%s\" value=\"%d\"/>\n", node->node.name, node->value);
-	g_igenerator_write (igenerator, markup);
-	g_free (markup);
-}
-
-static void constant_generate (GIGenerator *igenerator, GIdlNodeConstant *node)
-{
-	char *markup = g_markup_printf_escaped ("<constant name=\"%s\" type=\"%s\" value=\"%s\"/>\n", node->node.name, node->type->unparsed, node->value);
-	g_igenerator_write (igenerator, markup);
-	g_free (markup);
-}
-
-static void property_generate (GIGenerator *igenerator, GIdlNodeProperty *node)
-{
-	char *markup = g_markup_printf_escaped ("<property name=\"%s\" type=\"%s\" readable=\"%s\" writable=\"%s\" construct=\"%s\" construct-only=\"%s\"/>\n", node->node.name, node->type->unparsed, node->readable ? "1" : "0", node->writable ? "1" : "0", node->construct ? "1" : "0", node->construct_only ? "1" : "0");
-	g_igenerator_write (igenerator, markup);
-	g_free (markup);
-}
-
-static void function_generate (GIGenerator *igenerator, GIdlNodeFunction *node)
-{
-	char *markup;
-	const char *tag_name;
-	if (node->node.type == G_IDL_NODE_CALLBACK) {
-		tag_name = "callback";
-		markup = g_markup_printf_escaped ("<callback name=\"%s\">\n", node->node.name);
-	} else if (node->is_constructor) {
-		tag_name = "constructor";
-		markup = g_markup_printf_escaped ("<constructor name=\"%s\" symbol=\"%s\">\n", node->node.name, node->symbol);
-	} else if (node->is_method) {
-		tag_name = "method";
-		markup = g_markup_printf_escaped ("<method name=\"%s\" symbol=\"%s\">\n", node->node.name, node->symbol);
-	} else {
-		tag_name = "function";
-		markup = g_markup_printf_escaped ("<function name=\"%s\" symbol=\"%s\">\n", node->node.name, node->symbol);
-	}
-
-	g_igenerator_write_indent (igenerator, markup);
-	g_free (markup);
-	markup = g_markup_printf_escaped ("<return-type type=\"%s\"/>\n", node->result->type->unparsed);
-	g_igenerator_write (igenerator, markup);
-	g_free (markup);
-	if (node->parameters != NULL) {
-		GList *l;
-		g_igenerator_write_indent (igenerator, "<parameters>\n");
-		for (l = node->parameters; l != NULL; l = l->next) {
-			GIdlNodeParam *param = l->data;
-			markup = g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n", param->node.name, param->type->unparsed);
-			g_igenerator_write (igenerator, markup);
-			g_free (markup);
-		}
-		g_igenerator_write_unindent (igenerator, "</parameters>\n");
-	}
-	markup = g_strdup_printf ("</%s>\n", tag_name);
-	g_igenerator_write_unindent (igenerator, markup);
-	g_free (markup);
-}
-
-static void vfunc_generate (GIGenerator *igenerator, GIdlNodeVFunc *node)
-{
-	char *markup = g_markup_printf_escaped ("<vfunc name=\"%s\">\n", node->node.name);
-	g_igenerator_write_indent (igenerator, markup);
-	g_free (markup);
-	markup = g_markup_printf_escaped ("<return-type type=\"%s\"/>\n", node->result->type->unparsed);
-	g_igenerator_write (igenerator, markup);
-	g_free (markup);
-	if (node->parameters != NULL) {
-		GList *l;
-		g_igenerator_write_indent (igenerator, "<parameters>\n");
-		for (l = node->parameters; l != NULL; l = l->next) {
-			GIdlNodeParam *param = l->data;
-			markup = g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n", param->node.name, param->type->unparsed);
-			g_igenerator_write (igenerator, markup);
-			g_free (markup);
-		}
-		g_igenerator_write_unindent (igenerator, "</parameters>\n");
-	}
-	g_igenerator_write_unindent (igenerator, "</vfunc>\n");
-}
-
-static void signal_generate (GIGenerator *igenerator, GIdlNodeSignal *node)
-{
-	char *markup;
-	const char *when = "LAST";
-	if (node->run_first) {
-		when = "FIRST";
-	} else if (node->run_cleanup) {
-		when = "CLEANUP";
-	}
-	markup = g_markup_printf_escaped ("<signal name=\"%s\" when=\"%s\">\n", node->node.name, when);
-	g_igenerator_write_indent (igenerator, markup);
-	g_free (markup);
-	markup = g_markup_printf_escaped ("<return-type type=\"%s\"/>\n", node->result->type->unparsed);
-	g_igenerator_write (igenerator, markup);
-	g_free (markup);
-	if (node->parameters != NULL) {
-		GList *l;
-		g_igenerator_write_indent (igenerator, "<parameters>\n");
-		for (l = node->parameters; l != NULL; l = l->next) {
-			GIdlNodeParam *param = l->data;
-			markup = g_markup_printf_escaped ("<parameter name=\"%s\" type=\"%s\"/>\n", param->node.name, param->type->unparsed);
-			g_igenerator_write (igenerator, markup);
-			g_free (markup);
-		}
-		g_igenerator_write_unindent (igenerator, "</parameters>\n");
-	}
-	g_igenerator_write_unindent (igenerator, "</signal>\n");
-}
-
-static void interface_generate (GIGenerator *igenerator, GIdlNodeInterface *node)
-{
-	GList *l;
-	char *markup;
-	if (node->node.type == G_IDL_NODE_OBJECT) {
-		markup = g_markup_printf_escaped ("<object name=\"%s\" parent=\"%s\" type-name=\"%s\" get-type=\"%s\">\n", node->node.name, node->parent, node->gtype_name, node->gtype_init);
-	} else if (node->node.type == G_IDL_NODE_INTERFACE) {
-		markup = g_markup_printf_escaped ("<interface name=\"%s\" type-name=\"%s\" get-type=\"%s\">\n", node->node.name, node->gtype_name, node->gtype_init);
-	}
-
-	g_igenerator_write_indent (igenerator, markup);
-	g_free (markup);
-	if (node->node.type == G_IDL_NODE_OBJECT && node->interfaces != NULL) {
-		GList *l;
-		g_igenerator_write_indent (igenerator, "<implements>\n");
-		for (l = node->interfaces; l != NULL; l = l->next) {
-			markup = g_markup_printf_escaped ("<interface name=\"%s\"/>\n", (char *) l->data);
-			g_igenerator_write (igenerator, markup);
-			g_free (markup);
-		}
-		g_igenerator_write_unindent (igenerator, "</implements>\n");
-	} else if (node->node.type == G_IDL_NODE_INTERFACE && node->prerequisites != NULL) {
-		GList *l;
-		g_igenerator_write_indent (igenerator, "<requires>\n");
-		for (l = node->prerequisites; l != NULL; l = l->next) {
-			markup = g_markup_printf_escaped ("<interface name=\"%s\"/>\n", (char *) l->data);
-			g_igenerator_write (igenerator, markup);
-			g_free (markup);
-		}
-		g_igenerator_write_unindent (igenerator, "</requires>\n");
-	}
-
-	for (l = node->members; l != NULL; l = l->next) {
-		node_generate (igenerator, l->data);
-	}
-
-	if (node->node.type == G_IDL_NODE_OBJECT) {
-		g_igenerator_write_unindent (igenerator, "</object>\n");
-	} else if (node->node.type == G_IDL_NODE_INTERFACE) {
-		g_igenerator_write_unindent (igenerator, "</interface>\n");
-	}
-}
-
-static void struct_generate (GIGenerator *igenerator, GIdlNodeStruct *node)
-{
-	GList *l;
-	char *markup = g_markup_printf_escaped ("<struct name=\"%s\">\n", node->node.name);
-	g_igenerator_write_indent (igenerator, markup);
-	g_free (markup);
-	for (l = node->members; l != NULL; l = l->next) {
-		node_generate (igenerator, l->data);
-	}
-	g_igenerator_write_unindent (igenerator, "</struct>\n");
-}
-
-static void union_generate (GIGenerator *igenerator, GIdlNodeUnion *node)
-{
-	GList *l;
-	char *markup = g_markup_printf_escaped ("<union name=\"%s\">\n", node->node.name);
-	g_igenerator_write_indent (igenerator, markup);
-	g_free (markup);
-	for (l = node->members; l != NULL; l = l->next) {
-		node_generate (igenerator, l->data);
-	}
-	g_igenerator_write_unindent (igenerator, "</union>\n");
-}
-
-static void boxed_generate (GIGenerator *igenerator, GIdlNodeBoxed *node)
-{
-	GList *l;
-	char *markup = g_markup_printf_escaped ("<boxed name=\"%s\" type-name=\"%s\" get-type=\"%s\">\n", node->node.name, node->gtype_name, node->gtype_init);
-	g_igenerator_write_indent (igenerator, markup);
-	g_free (markup);
-	for (l = node->members; l != NULL; l = l->next) {
-		node_generate (igenerator, l->data);
-	}
-	g_igenerator_write_unindent (igenerator, "</boxed>\n");
-}
-
-static void enum_generate (GIGenerator *igenerator, GIdlNodeEnum *node)
-{
-	GList *l;
-	char *markup;
-	const char *tag_name = NULL;
-
-	if (node->node.type == G_IDL_NODE_ENUM) {
-		tag_name = "enum";
-	} else if (node->node.type == G_IDL_NODE_FLAGS) {
-		tag_name = "flags";
-	}
-	markup = g_markup_printf_escaped ("<%s name=\"%s\">\n", tag_name, node->node.name);
-	g_igenerator_write_indent (igenerator, markup);
-	g_free (markup);
-
-	for (l = node->values; l != NULL; l = l->next) {
-		node_generate (igenerator, l->data);
-	}
-
-	markup = g_strdup_printf ("</%s>\n", tag_name);
-	g_igenerator_write_unindent (igenerator, markup);
-	g_free (markup);
-}
-
-static void node_generate (GIGenerator *igenerator, GIdlNode *node)
-{
-	switch (node->type) {
-	case G_IDL_NODE_FUNCTION:
-	case G_IDL_NODE_CALLBACK:
-		function_generate (igenerator, (GIdlNodeFunction *) node);
-		break;
-	case G_IDL_NODE_VFUNC:
-		vfunc_generate (igenerator, (GIdlNodeVFunc *) node);
-		break;
-	case G_IDL_NODE_OBJECT:
-	case G_IDL_NODE_INTERFACE:
-		interface_generate (igenerator, (GIdlNodeInterface *) node);
-		break;
-	case G_IDL_NODE_STRUCT:
-		struct_generate (igenerator, (GIdlNodeStruct *) node);
-		break;
-	case G_IDL_NODE_UNION:
-		union_generate (igenerator, (GIdlNodeUnion *) node);
-		break;
-	case G_IDL_NODE_BOXED:
-		boxed_generate (igenerator, (GIdlNodeBoxed *) node);
-		break;
-	case G_IDL_NODE_ENUM:
-	case G_IDL_NODE_FLAGS:
-		enum_generate (igenerator, (GIdlNodeEnum *) node);
-		break;
-	case G_IDL_NODE_PROPERTY:
-		property_generate (igenerator, (GIdlNodeProperty *) node);
-		break;
-	case G_IDL_NODE_FIELD:
-		field_generate (igenerator, (GIdlNodeField *) node);
-		break;
-	case G_IDL_NODE_SIGNAL:
-		signal_generate (igenerator, (GIdlNodeSignal *) node);
-		break;
-	case G_IDL_NODE_VALUE:
-		value_generate (igenerator, (GIdlNodeValue *) node);
-		break;
-	case G_IDL_NODE_CONSTANT:
-		constant_generate (igenerator, (GIdlNodeConstant *) node);
-		break;
-	default:
-		g_assert_not_reached ();
-	}
-}
-
-static void module_generate (GIGenerator *igenerator, GIdlModule *module)
-{
-	GList *l;
-	char *markup = g_markup_printf_escaped ("<namespace name=\"%s\">\n", module->name);
-	g_igenerator_write_indent (igenerator, markup);
-	g_free (markup);
-	for (l = module->entries; l != NULL; l = l->next) {
-		node_generate (igenerator, l->data);
-	}
-	g_igenerator_write_unindent (igenerator, "</namespace>\n");
-}
-
-static GIdlNodeType *get_type_from_type_id (GType type_id)
-{
-	GIdlNodeType *gitype = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
-
-	GType type_fundamental = g_type_fundamental (type_id);
-
-	if (type_fundamental == G_TYPE_STRING) {
-		gitype->unparsed = g_strdup ("char*");
-	} else if (type_id == G_TYPE_STRV) {
-		gitype->unparsed = g_strdup ("char*[]");
-	} else if (type_fundamental == G_TYPE_INTERFACE || type_fundamental == G_TYPE_BOXED || type_fundamental == G_TYPE_OBJECT) {
-		gitype->unparsed = g_strdup_printf ("%s*", g_type_name (type_id));
-	} else if (type_fundamental == G_TYPE_PARAM) {
-		gitype->unparsed = g_strdup ("GParamSpec*");
-	} else {
-		gitype->unparsed = g_strdup (g_type_name (type_id));
-	}
-
-	return gitype;
-}
-
-static char *str_replace (const char *str, const char *needle, const char *replacement)
-{
-	char **strings = g_strsplit (str, needle, 0);
-	char *result = g_strjoinv (replacement, strings);
-	g_strfreev (strings);
-	return result;
-}
-
-static void g_igenerator_process_properties (GIGenerator *igenerator, GIdlNodeInterface *ginode, GType type_id)
-{
-	int i;
-	guint n_properties;
-	GParamSpec **properties;
-
-	if (ginode->node.type == G_IDL_NODE_OBJECT) {
-		GObjectClass *type_class = g_type_class_ref (type_id);
-		properties = g_object_class_list_properties (type_class, &n_properties);
-	} else if (ginode->node.type == G_IDL_NODE_INTERFACE) {
-		GTypeInterface *iface = g_type_default_interface_ref (type_id);
-		properties = g_object_interface_list_properties (iface, &n_properties);
-	} else {
-		g_assert_not_reached ();
-	}
-
-	for (i = 0; i < n_properties; i++) {
-		/* ignore inherited properties */
-		if (properties[i]->owner_type != type_id) {
-			continue;
-		}
-		GIdlNodeProperty *giprop = (GIdlNodeProperty *) g_idl_node_new (G_IDL_NODE_PROPERTY);
-		giprop->node.name = properties[i]->name;
-		ginode->members = g_list_insert_sorted (ginode->members, giprop, (GCompareFunc) g_idl_node_cmp);
-		giprop->type = get_type_from_type_id (properties[i]->value_type);
-		giprop->readable = (properties[i]->flags & G_PARAM_READABLE) != 0;
-		giprop->writable = (properties[i]->flags & G_PARAM_WRITABLE) != 0;
-		giprop->construct = (properties[i]->flags & G_PARAM_CONSTRUCT) != 0;
-		giprop->construct_only = (properties[i]->flags & G_PARAM_CONSTRUCT_ONLY) != 0;
-	}
-}
-
-static void g_igenerator_process_signals (GIGenerator *igenerator, GIdlNodeInterface *ginode, GType type_id)
-{
-	int i, j;
-	guint n_signal_ids;
-	guint *signal_ids = g_signal_list_ids (type_id, &n_signal_ids);
-
-	for (i = 0; i < n_signal_ids; i++) {
-		GSignalQuery signal_query;
-		g_signal_query (signal_ids[i], &signal_query);
-		GIdlNodeSignal *gisig = (GIdlNodeSignal *) g_idl_node_new (G_IDL_NODE_SIGNAL);
-		gisig->node.name = g_strdup (signal_query.signal_name);
-		ginode->members = g_list_insert_sorted (ginode->members, gisig, (GCompareFunc) g_idl_node_cmp);
-
-		gisig->run_first = (signal_query.signal_flags & G_SIGNAL_RUN_FIRST) != 0;
-		gisig->run_last = (signal_query.signal_flags & G_SIGNAL_RUN_LAST) != 0;
-		gisig->run_cleanup = (signal_query.signal_flags & G_SIGNAL_RUN_CLEANUP) != 0;
-
-		/* add sender parameter */
-		GIdlNodeParam *giparam = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
-		gisig->parameters = g_list_append (gisig->parameters, giparam);
-		giparam->node.name = g_strdup ("object");
-		giparam->type = get_type_from_type_id (type_id);
-		
-		for (j = 0; j < signal_query.n_params; j++) {
-			giparam = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
-			gisig->parameters = g_list_append (gisig->parameters, giparam);
-			giparam->node.name = g_strdup_printf ("p%d", j);
-			giparam->type = get_type_from_type_id (signal_query.param_types[j]);
-		}
-		gisig->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
-		gisig->result->type = get_type_from_type_id (signal_query.return_type);
-	}
-}
-
-static void g_igenerator_process_types (GIGenerator *igenerator)
-{
-	int i;
-	GList *lib_l;
-
-	/* ensure to initialize GObject */
-	g_type_class_ref (G_TYPE_OBJECT);
-
-	for (lib_l = igenerator->libraries; lib_l != NULL; lib_l = lib_l->next) {
-		GList *l;
-		GModule *module = g_module_open (lib_l->data, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
-		if (module == NULL) {
-			g_critical ("Couldn't open module: %s", (char *) lib_l->data);
-			continue;
-		}
-		for (l = igenerator->get_type_symbols; l != NULL; l = l->next) {
-			char *get_type_symbol = l->data;
-
-			if (get_type_symbol == NULL) {
-				/* ignore already processed functions */
-				continue;
-			}
-
-			TypeFunction type_fun;
-			if (!g_module_symbol (module, get_type_symbol, (gpointer*) &type_fun)) {
-				continue;
-			}
-
-			/* symbol found, ignore in future iterations */
-			l->data = NULL;
-
-			GType type_id = type_fun ();
-			GType type_fundamental = g_type_fundamental (type_id);
-			char *lower_case_prefix = str_replace (g_strndup (get_type_symbol, strlen (get_type_symbol) - strlen ("_get_type")), "_", "");
-			if (type_fundamental == G_TYPE_OBJECT) {
-				char *alt_lower_case_prefix;
-				GIdlNodeInterface *ginode = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_OBJECT);
-				ginode->node.name = g_strdup (g_type_name (type_id));
-				igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
-				g_hash_table_insert (igenerator->type_map, ginode->node.name, ginode);
-				g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
-				alt_lower_case_prefix = g_ascii_strdown (ginode->node.name, -1);
-				if (strcmp (alt_lower_case_prefix, lower_case_prefix) != 0) {
-					/* alternative prefix sometimes necessary, for example for GdkWindow  */
-					g_hash_table_insert (igenerator->type_by_lower_case_prefix, alt_lower_case_prefix, ginode);
-				} else {
-					g_free (alt_lower_case_prefix);
-				}
-				ginode->gtype_name = ginode->node.name;
-				ginode->gtype_init = get_type_symbol;
-				ginode->parent = g_strdup (g_type_name (g_type_parent (type_id)));
-			
-				guint n_type_interfaces;
-				GType *type_interfaces = g_type_interfaces (type_id, &n_type_interfaces);
-				for (i = 0; i < n_type_interfaces; i++) {
-					char *iface_name = g_strdup (g_type_name (type_interfaces[i]));
-					/* workaround for AtkImplementorIface */
-					if (g_str_has_suffix (iface_name, "Iface")) {
-						iface_name[strlen (iface_name) - strlen ("Iface")] = '\0';
-					}
-					ginode->interfaces = g_list_append (ginode->interfaces, iface_name);
-				}
-
-				g_igenerator_process_properties (igenerator, ginode, type_id);
-				g_igenerator_process_signals (igenerator, ginode, type_id);
-			} else if (type_fundamental == G_TYPE_INTERFACE) {
-				GIdlNodeInterface *ginode = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_INTERFACE);
-				ginode->node.name = g_strdup (g_type_name (type_id));
-				/* workaround for AtkImplementorIface */
-				if (g_str_has_suffix (ginode->node.name, "Iface")) {
-					ginode->node.name[strlen (ginode->node.name) - strlen ("Iface")] = '\0';
-				}
-				igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
-				g_hash_table_insert (igenerator->type_map, ginode->node.name, ginode);
-				g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
-				ginode->gtype_name = ginode->node.name;
-				ginode->gtype_init = get_type_symbol;
-			
-				gboolean is_gobject = FALSE;
-				guint n_iface_prereqs;
-				GType *iface_prereqs = g_type_interface_prerequisites (type_id, &n_iface_prereqs);
-				for (i = 0; i < n_iface_prereqs; i++) {
-					if (g_type_fundamental (iface_prereqs[i]) == G_TYPE_OBJECT) {
-						is_gobject = TRUE;
-					}
-					ginode->prerequisites = g_list_append (ginode->prerequisites, g_strdup (g_type_name (iface_prereqs[i])));
-				}
-
-				if (is_gobject) {
-					g_igenerator_process_properties (igenerator, ginode, type_id);
-				} else {
-					g_type_default_interface_ref (type_id);
-				}
-				g_igenerator_process_signals (igenerator, ginode, type_id);
-			} else if (type_fundamental == G_TYPE_BOXED) {
-				GIdlNodeBoxed *ginode = (GIdlNodeBoxed *) g_idl_node_new (G_IDL_NODE_BOXED);
-				ginode->node.name = g_strdup (g_type_name (type_id));
-				igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
-				g_hash_table_insert (igenerator->type_map, ginode->node.name, ginode);
-				g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
-				ginode->gtype_name = ginode->node.name;
-				ginode->gtype_init = get_type_symbol;
-			} else if (type_fundamental == G_TYPE_ENUM) {
-				GIdlNodeEnum *ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_ENUM);
-				ginode->node.name = g_strdup (g_type_name (type_id));
-				igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
-				g_hash_table_insert (igenerator->type_map, ginode->node.name, ginode);
-				g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
-				ginode->gtype_name = ginode->node.name;
-				ginode->gtype_init = get_type_symbol;
-
-				GEnumClass *type_class = g_type_class_ref (type_id);
-				for (i = 0; i < type_class->n_values; i++) {
-					GIdlNodeValue *gival = (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
-					ginode->values = g_list_append (ginode->values, gival);
-					gival->node.name = g_strdup (type_class->values[i].value_name);
-					gival->value = type_class->values[i].value;
-				}
-			} else if (type_fundamental == G_TYPE_FLAGS) {
-				GIdlNodeEnum *ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_FLAGS);
-				ginode->node.name = g_strdup (g_type_name (type_id));
-				igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
-				g_hash_table_insert (igenerator->type_map, ginode->node.name, ginode);
-				g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
-				ginode->gtype_name = ginode->node.name;
-				ginode->gtype_init = get_type_symbol;
-
-				GFlagsClass *type_class = g_type_class_ref (type_id);
-				for (i = 0; i < type_class->n_values; i++) {
-					GIdlNodeValue *gival = (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
-					ginode->values = g_list_append (ginode->values, gival);
-					gival->node.name = g_strdup (type_class->values[i].value_name);
-					gival->value = type_class->values[i].value;
-				}
-			}
-		}
-	}
-}
-
-static GIdlNodeType *get_type_from_ctype (CType *ctype)
-{
-	GIdlNodeType *gitype = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
-	if (ctype->type == CTYPE_VOID) {
-		gitype->unparsed = g_strdup ("void");
-	} else if (ctype->type == CTYPE_BASIC_TYPE) {
-		gitype->unparsed = g_strdup (ctype->name);
-	} else if (ctype->type == CTYPE_TYPEDEF) {
-		gitype->unparsed = g_strdup (ctype->name);
-	} else if (ctype->type == CTYPE_STRUCT) {
-		if (ctype->name == NULL) {
-			/* anonymous struct */
-			gitype->unparsed = g_strdup ("gpointer");
-		} else {
-			gitype->unparsed = g_strdup_printf ("struct %s", ctype->name);
-		}
-	} else if (ctype->type == CTYPE_UNION) {
-		if (ctype->name == NULL) {
-			/* anonymous union */
-			gitype->unparsed = g_strdup ("gpointer");
-		} else {
-			gitype->unparsed = g_strdup_printf ("union %s", ctype->name);
-		}
-	} else if (ctype->type == CTYPE_ENUM) {
-		if (ctype->name == NULL) {
-			/* anonymous enum */
-			gitype->unparsed = g_strdup ("gint");
-		} else {
-			gitype->unparsed = g_strdup_printf ("enum %s", ctype->name);
-		}
-	} else if (ctype->type == CTYPE_POINTER) {
-		if (ctype->base_type->type == CTYPE_FUNCTION) {
-			/* anonymous function pointer */
-			gitype->unparsed = g_strdup ("GCallback");
-		} else {
-			GIdlNodeType *gibasetype = get_type_from_ctype (ctype->base_type);
-			gitype->unparsed = g_strdup_printf ("%s*", gibasetype->unparsed);
-		}
-	} else if (ctype->type == CTYPE_ARRAY) {
-		GIdlNodeType *gibasetype = get_type_from_ctype (ctype->base_type);
-		gitype->unparsed = g_strdup_printf ("%s[]", gibasetype->unparsed);
-	} else {
-		gitype->unparsed = g_strdup ("unknown");
-	}
-	return gitype;
-}
-
-static void g_igenerator_process_function_symbol (GIGenerator *igenerator, CSymbol *sym)
-{
-	GIdlNodeFunction *gifunc = (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_FUNCTION);
-	/* check whether this is a type method */
-	char *last_underscore = strrchr (sym->ident, '_');
-	while (last_underscore != NULL) {
-		char *prefix = str_replace (g_strndup (sym->ident, last_underscore - sym->ident), "_", "");
-		GIdlNode *ginode = g_hash_table_lookup (igenerator->type_by_lower_case_prefix, prefix);
-		if (ginode != NULL) {
-			gifunc->node.name = g_strdup (last_underscore + 1);
-			if (strcmp (gifunc->node.name, "get_type") == 0) {
-				/* ignore get_type functions in registered types */
-				return;
-			}
-			if ((ginode->type == G_IDL_NODE_OBJECT || ginode->type == G_IDL_NODE_BOXED) && g_str_has_prefix (gifunc->node.name, "new")) {
-				gifunc->is_constructor = TRUE;
-			} else {
-				gifunc->is_method = TRUE;
-			}
-			if (ginode->type == G_IDL_NODE_OBJECT || ginode->type == G_IDL_NODE_INTERFACE) {
-				GIdlNodeInterface *giiface = (GIdlNodeInterface *) ginode;
-				giiface->members = g_list_insert_sorted (giiface->members, gifunc, (GCompareFunc) g_idl_node_cmp);
-				break;
-			} else if (ginode->type == G_IDL_NODE_BOXED) {
-				GIdlNodeBoxed *giboxed = (GIdlNodeBoxed *) ginode;
-				giboxed->members = g_list_insert_sorted (giboxed->members, gifunc, (GCompareFunc) g_idl_node_cmp);
-				break;
-			} else if (ginode->type == G_IDL_NODE_STRUCT) {
-				GIdlNodeStruct *gistruct = (GIdlNodeStruct *) ginode;
-				gistruct->members = g_list_insert_sorted (gistruct->members, gifunc, (GCompareFunc) g_idl_node_cmp);
-				break;
-			} else if (ginode->type == G_IDL_NODE_UNION) {
-				GIdlNodeUnion *giunion = (GIdlNodeUnion *) ginode;
-				giunion->members = g_list_insert_sorted (giunion->members, gifunc, (GCompareFunc) g_idl_node_cmp);
-				break;
-			}
-		} else if (strcmp (igenerator->lower_case_namespace, prefix) == 0) {
-			gifunc->node.name = g_strdup (last_underscore + 1);
-			gifunc->is_constructor = FALSE;
-			gifunc->is_method = FALSE;
-			igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, gifunc, (GCompareFunc) g_idl_node_cmp);
-			break;
-		}
-		last_underscore = g_utf8_strrchr (sym->ident, last_underscore - sym->ident, '_');
-	}
-	
-	/* create a namespace function if no prefix matches */
-	if (gifunc->node.name == NULL) {
-		gifunc->node.name = sym->ident;
-		gifunc->is_constructor = FALSE;
-		gifunc->is_method = FALSE;
-		igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, gifunc, (GCompareFunc) g_idl_node_cmp);
-	}
-
-	gifunc->symbol = sym->ident;
-	gifunc->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
-	gifunc->result->type = get_type_from_ctype (sym->base_type->base_type);
-	GList *param_l;
-	int i;
-	for (param_l = sym->base_type->child_list, i = 1; param_l != NULL; param_l = param_l->next, i++) {
-		CSymbol *param_sym = param_l->data;
-		GIdlNodeParam *param = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
-		if (param_sym->ident == NULL) {
-			param->node.name = g_strdup_printf ("p%d", i);
-		} else {
-			param->node.name = param_sym->ident;
-		}
-		param->type = get_type_from_ctype (param_sym->base_type);
-		gifunc->parameters = g_list_append (gifunc->parameters, param);
-	}
-}
-
-static void g_igenerator_process_unregistered_struct_typedef (GIGenerator *igenerator, CSymbol *sym, CType *struct_type)
-{
-	GIdlNodeStruct *ginode = (GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT);
-	ginode->node.name = sym->ident;
-	igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
-	char *lower_case_prefix = g_ascii_strdown (sym->ident, -1);
-	g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
-	g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
-
-	GList *member_l;
-	for (member_l = struct_type->child_list; member_l != NULL; member_l = member_l->next) {
-		CSymbol *member = member_l->data;
-		GIdlNodeField *gifield = (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
-		ginode->members = g_list_append (ginode->members, gifield);
-		gifield->node.name = member->ident;
-		gifield->type = get_type_from_ctype (member->base_type);
-	}
-}
-
-static void g_igenerator_process_struct_typedef (GIGenerator *igenerator, CSymbol *sym)
-{
-	CType *struct_type = sym->base_type;
-	gboolean opaque_type = FALSE;
-	if (struct_type->child_list == NULL) {
-		g_assert (struct_type->name != NULL);
-		CSymbol *struct_symbol = g_hash_table_lookup (igenerator->struct_or_union_or_enum_table, struct_type->name);
-		if (struct_symbol != NULL) {
-			struct_type = struct_symbol->base_type;
-		}
-	}
-	if (struct_type->child_list == NULL) {
-		opaque_type = TRUE;
-	}
-	GIdlNode *gitype = g_hash_table_lookup (igenerator->type_map, sym->ident);
-	if (gitype != NULL) {
-		/* struct of a GTypeInstance */
-		if (!opaque_type && (gitype->type == G_IDL_NODE_OBJECT || gitype->type == G_IDL_NODE_INTERFACE)) {
-			GIdlNodeInterface *ginode = (GIdlNodeInterface *) gitype;
-			GList *member_l;
-			/* ignore first field => parent */
-			for (member_l = struct_type->child_list->next; member_l != NULL; member_l = member_l->next) {
-				CSymbol *member = member_l->data;
-				/* ignore private / reserved members */
-				if (member->ident[0] == '_' || g_str_has_prefix (member->ident, "priv")) {
-					continue;
-				}
-				GIdlNodeField *gifield = (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
-				ginode->members = g_list_append (ginode->members, gifield);
-				gifield->node.name = member->ident;
-				gifield->type = get_type_from_ctype (member->base_type);
-			}
-		} else if (gitype->type == G_IDL_NODE_BOXED) {
-			GIdlNodeBoxed *ginode = (GIdlNodeBoxed *) gitype;
-			GList *member_l;
-			for (member_l = struct_type->child_list; member_l != NULL; member_l = member_l->next) {
-				CSymbol *member = member_l->data;
-				GIdlNodeField *gifield = (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
-				ginode->members = g_list_append (ginode->members, gifield);
-				gifield->node.name = member->ident;
-				gifield->type = get_type_from_ctype (member->base_type);
-			}
-		}
-	} else if (!opaque_type && (g_str_has_suffix (sym->ident, "Class") || g_str_has_suffix (sym->ident, "Iface") || g_str_has_suffix (sym->ident, "Interface"))) {
-		char *base_name;
-		if (g_str_has_suffix (sym->ident, "Interface")) {
-			base_name = g_strndup (sym->ident, strlen (sym->ident) - strlen ("Interface"));
-		} else {
-			base_name = g_strndup (sym->ident, strlen (sym->ident) - strlen ("Class"));
-		}
-		gitype = g_hash_table_lookup (igenerator->type_map, base_name);
-		if (gitype == NULL || (gitype->type != G_IDL_NODE_OBJECT && gitype->type != G_IDL_NODE_INTERFACE)) {
-			g_igenerator_process_unregistered_struct_typedef (igenerator, sym, struct_type);
-			return;
-		}
-		GIdlNodeInterface *ginode = (GIdlNodeInterface *) gitype;
-
-		/* ignore first field => parent */
-		GList *member_l;
-		for (member_l = struct_type->child_list->next; member_l != NULL; member_l = member_l->next) {
-			CSymbol *member = member_l->data;
-			/* ignore private / reserved members */
-			if (member->ident[0] == '_') {
-				continue;
-			}
-			if (member->base_type->type == CTYPE_POINTER && member->base_type->base_type->type == CTYPE_FUNCTION) {
-				/* ignore default handlers of signals */
-				gboolean found_signal = FALSE;
-				GList *type_member_l;
-				for (type_member_l = ginode->members; type_member_l != NULL; type_member_l = type_member_l->next) {
-					GIdlNode *type_member = type_member_l->data;
-					char *normalized_name = str_replace (type_member->name, "-", "_");
-					if (type_member->type == G_IDL_NODE_SIGNAL && strcmp (normalized_name, member->ident) == 0) {
-						GList *vfunc_param_l;
-						GList *sig_param_l;
-						GIdlNodeSignal *sig = (GIdlNodeSignal *) type_member;
-						found_signal = TRUE;
-						/* set signal parameter names */
-						for (vfunc_param_l = member->base_type->base_type->child_list, sig_param_l = sig->parameters; vfunc_param_l != NULL && sig_param_l != NULL; vfunc_param_l = vfunc_param_l->next, sig_param_l = sig_param_l->next) {
-							CSymbol *vfunc_param = vfunc_param_l->data;
-							GIdlNodeParam *sig_param = sig_param_l->data;
-							if (vfunc_param->ident != NULL) {
-								g_free (sig_param->node.name);
-								sig_param->node.name = g_strdup (vfunc_param->ident);
-							}
-						}
-						break;
-					}
-				}
-				if (found_signal) {
-					continue;
-				}
-
-				GIdlNodeVFunc *givfunc = (GIdlNodeVFunc *) g_idl_node_new (G_IDL_NODE_VFUNC);
-				givfunc->node.name = member->ident;
-				ginode->members = g_list_insert_sorted (ginode->members, givfunc, (GCompareFunc) g_idl_node_cmp);
-				givfunc->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
-				givfunc->result->type = get_type_from_ctype (member->base_type->base_type->base_type);
-				GList *param_l;
-				int i;
-				for (param_l = member->base_type->base_type->child_list, i = 1; param_l != NULL; param_l = param_l->next, i++) {
-					CSymbol *param_sym = param_l->data;
-					GIdlNodeParam *param = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
-					if (param_sym->ident == NULL) {
-						param->node.name = g_strdup_printf ("p%d", i);
-					} else {
-						param->node.name = param_sym->ident;
-					}
-					param->type = get_type_from_ctype (param_sym->base_type);
-					givfunc->parameters = g_list_append (givfunc->parameters, param);
-				}
+  if (a->type < b->type)
+    {
+      return -1;
+    }
+  else if (a->type > b->type)
+    {
+      return 1;
+    }
+  else
+    {
+      return strcmp (a->name, b->name);
+    }
+}
+
+static GIGenerator *
+g_igenerator_new (const gchar *namespace,
+		  const gchar *shared_library)
+{
+  GIGenerator *igenerator = g_new0 (GIGenerator, 1);
+  igenerator->namespace = g_strdup (namespace); 
+  igenerator->shared_library = g_strdup (shared_library);
+  igenerator->lower_case_namespace =
+    g_ascii_strdown (igenerator->namespace, -1);
+  igenerator->module = g_idl_module_new (namespace, shared_library);
+
+  igenerator->typedef_table = g_hash_table_new (g_str_hash, g_str_equal);
+  igenerator->struct_or_union_or_enum_table =
+    g_hash_table_new (g_str_hash, g_str_equal);
+
+  igenerator->type_map = g_hash_table_new (g_str_hash, g_str_equal);
+  igenerator->type_by_lower_case_prefix =
+    g_hash_table_new (g_str_hash, g_str_equal);
+  igenerator->symbols = g_hash_table_new (g_str_hash, g_str_equal);
+
+  return igenerator;
+}
+
+static void
+g_igenerator_free (GIGenerator *generator)
+{
+  g_free (generator->namespace);
+  g_free (generator->shared_library);
+  g_free (generator->lower_case_namespace);
+#if 0
+  g_idl_module_free (generator->module);
+#endif  
+  g_hash_table_destroy (generator->typedef_table);
+  g_hash_table_destroy (generator->struct_or_union_or_enum_table);
+  g_hash_table_destroy (generator->type_map);
+  g_hash_table_destroy (generator->type_by_lower_case_prefix);
+  g_hash_table_destroy (generator->symbols);
+  g_list_foreach (generator->filenames, (GFunc)g_free, NULL);
+  g_list_free (generator->filenames);
+#if 0
+  g_list_foreach (generator->symbol_list, (GFunc)csymbol_free, NULL);
+  g_list_free (generator->symbol_list);
+#endif
+  g_free (generator);
+}
+
+static GIdlNodeType *
+get_type_from_type_id (GType type_id)
+{
+  GIdlNodeType *gitype = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
+
+  GType type_fundamental = g_type_fundamental (type_id);
+
+  if (type_fundamental == G_TYPE_STRING)
+    {
+      gitype->unparsed = g_strdup ("char*");
+    }
+  else if (type_id == G_TYPE_STRV)
+    {
+      gitype->unparsed = g_strdup ("char*[]");
+    }
+  else if (type_fundamental == G_TYPE_INTERFACE
+	   || type_fundamental == G_TYPE_BOXED
+	   || type_fundamental == G_TYPE_OBJECT)
+    {
+      gitype->unparsed = g_strdup_printf ("%s*", g_type_name (type_id));
+    }
+  else if (type_fundamental == G_TYPE_PARAM)
+    {
+      gitype->unparsed = g_strdup ("GParamSpec*");
+    }
+  else
+    {
+      gitype->unparsed = g_strdup (g_type_name (type_id));
+    }
+
+  return gitype;
+}
+
+static char *
+str_replace (const char *str, const char *needle, const char *replacement)
+{
+  char **strings = g_strsplit (str, needle, 0);
+  char *result = g_strjoinv (replacement, strings);
+  g_strfreev (strings);
+  return result;
+}
+
+static void
+g_igenerator_process_properties (GIGenerator * igenerator,
+				 GIdlNodeInterface * ginode, GType type_id)
+{
+  int i;
+  guint n_properties;
+  GParamSpec **properties;
+
+  if (ginode->node.type == G_IDL_NODE_OBJECT)
+    {
+      GObjectClass *type_class = g_type_class_ref (type_id);
+      properties = g_object_class_list_properties (type_class, &n_properties);
+    }
+  else if (ginode->node.type == G_IDL_NODE_INTERFACE)
+    {
+      GTypeInterface *iface = g_type_default_interface_ref (type_id);
+      properties = g_object_interface_list_properties (iface, &n_properties);
+    }
+  else
+    {
+      g_assert_not_reached ();
+    }
+
+  for (i = 0; i < n_properties; i++)
+    {
+      GIdlNodeProperty *giprop;
+
+      /* ignore inherited properties */
+      if (properties[i]->owner_type != type_id)
+	{
+	  continue;
+	}
+      giprop = (GIdlNodeProperty *) g_idl_node_new (G_IDL_NODE_PROPERTY);
+      giprop->node.name = properties[i]->name;
+      ginode->members =
+	g_list_insert_sorted (ginode->members, giprop,
+			      (GCompareFunc) g_idl_node_cmp);
+      giprop->type = get_type_from_type_id (properties[i]->value_type);
+      giprop->readable = (properties[i]->flags & G_PARAM_READABLE) != 0;
+      giprop->writable = (properties[i]->flags & G_PARAM_WRITABLE) != 0;
+      giprop->construct = (properties[i]->flags & G_PARAM_CONSTRUCT) != 0;
+      giprop->construct_only =
+	(properties[i]->flags & G_PARAM_CONSTRUCT_ONLY) != 0;
+    }
+}
+
+static void
+g_igenerator_process_signals (GIGenerator * igenerator,
+			      GIdlNodeInterface * ginode, GType type_id)
+{
+  int i, j;
+  guint n_signal_ids;
+  guint *signal_ids = g_signal_list_ids (type_id, &n_signal_ids);
+
+  for (i = 0; i < n_signal_ids; i++)
+    {
+      GSignalQuery signal_query;
+      GIdlNodeSignal *gisig;
+      GIdlNodeParam *giparam;
+      
+      g_signal_query (signal_ids[i], &signal_query);
+      gisig = (GIdlNodeSignal *) g_idl_node_new (G_IDL_NODE_SIGNAL);
+      gisig->node.name = g_strdup (signal_query.signal_name);
+      ginode->members =
+	g_list_insert_sorted (ginode->members, gisig,
+			      (GCompareFunc) g_idl_node_cmp);
+
+      gisig->run_first =
+	(signal_query.signal_flags & G_SIGNAL_RUN_FIRST) != 0;
+      gisig->run_last = (signal_query.signal_flags & G_SIGNAL_RUN_LAST) != 0;
+      gisig->run_cleanup =
+	(signal_query.signal_flags & G_SIGNAL_RUN_CLEANUP) != 0;
+
+      /* add sender parameter */
+      giparam = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+      gisig->parameters = g_list_append (gisig->parameters, giparam);
+      giparam->node.name = g_strdup ("object");
+      giparam->type = get_type_from_type_id (type_id);
+
+      for (j = 0; j < signal_query.n_params; j++)
+	{
+	  giparam = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+	  gisig->parameters = g_list_append (gisig->parameters, giparam);
+	  giparam->node.name = g_strdup_printf ("p%d", j);
+	  giparam->type = get_type_from_type_id (signal_query.param_types[j]);
+	}
+      gisig->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+      gisig->result->type = get_type_from_type_id (signal_query.return_type);
+    }
+}
+
+static const gchar *
+lookup_symbol (GIGenerator *igenerator, const gchar *typename)
+{
+  const gchar *name =
+    g_hash_table_lookup (igenerator->symbols, typename);
+
+  if (!name)
+    {
+      g_printerr ("Unknown symbol: %s\n", typename);
+      return typename;
+    }
+
+  return name;
+}
+
+static void
+g_igenerator_create_object (GIGenerator *igenerator,
+			    const char *symbol_name,
+			    GType type_id,
+			    char *lower_case_prefix)
+
+{
+  char *alt_lower_case_prefix;
+  GIdlNodeInterface *ginode;
+  guint n_type_interfaces;
+  GType *type_interfaces;
+  int i;
+
+  ginode = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_OBJECT);
+  ginode->node.name = g_strdup (g_type_name (type_id));
+  igenerator->module->entries =
+    g_list_insert_sorted (igenerator->module->entries, ginode,
+			  (GCompareFunc) g_idl_node_cmp);
+  g_hash_table_insert (igenerator->type_map, ginode->node.name,
+		       ginode);
+  g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+		       lower_case_prefix, ginode);
+  alt_lower_case_prefix = g_ascii_strdown (ginode->node.name, -1);
+  
+  if (strcmp (alt_lower_case_prefix, lower_case_prefix) != 0)
+    {
+      /* alternative prefix sometimes necessary, for example
+       * for GdkWindow
+       */
+      g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+			   alt_lower_case_prefix, ginode);
+    }
+  else
+    {
+      g_free (alt_lower_case_prefix);
+    }
+
+  ginode->gtype_name = ginode->node.name;
+  ginode->gtype_init = g_strdup (symbol_name);
+  ginode->parent = g_strdup (lookup_symbol (igenerator,
+					    g_type_name (g_type_parent (type_id))));
+  
+  type_interfaces = g_type_interfaces (type_id, &n_type_interfaces);
+  for (i = 0; i < n_type_interfaces; i++)
+    {
+      char *iface_name =
+	g_strdup (g_type_name (type_interfaces[i]));
+      /* workaround for AtkImplementorIface */
+      if (g_str_has_suffix (iface_name, "Iface"))
+	{
+	  iface_name[strlen (iface_name) - strlen ("Iface")] =
+	    '\0';
+	}
+      ginode->interfaces =
+	g_list_append (ginode->interfaces, iface_name);
+    }
+  
+  g_hash_table_insert (igenerator->symbols,
+		       g_strdup (ginode->gtype_name),
+		       /* FIXME: Strip igenerator->namespace */
+		       g_strdup (ginode->node.name));
+  
+  g_igenerator_process_properties (igenerator, ginode, type_id);
+  g_igenerator_process_signals (igenerator, ginode, type_id);
+}
+
+static void
+g_igenerator_create_interface (GIGenerator *igenerator,
+			       const char *symbol_name,
+			       GType type_id,
+			       char *lower_case_prefix)
+
+{
+  GIdlNodeInterface *ginode;
+  gboolean is_gobject = FALSE;
+  guint n_iface_prereqs;
+  GType *iface_prereqs;
+  int i;
+
+  ginode = (GIdlNodeInterface *) g_idl_node_new (G_IDL_NODE_INTERFACE);
+  ginode->node.name = g_strdup (g_type_name (type_id));
+  
+  /* workaround for AtkImplementorIface */
+  if (g_str_has_suffix (ginode->node.name, "Iface"))
+    {
+      ginode->node.name[strlen (ginode->node.name) -
+			strlen ("Iface")] = '\0';
+    }
+  igenerator->module->entries =
+    g_list_insert_sorted (igenerator->module->entries, ginode,
+			  (GCompareFunc) g_idl_node_cmp);
+  g_hash_table_insert (igenerator->type_map, ginode->node.name,
+		       ginode);
+  g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+		       lower_case_prefix, ginode);
+  ginode->gtype_name = ginode->node.name;
+  ginode->gtype_init = g_strdup (symbol_name);
+  
+  iface_prereqs =
+    g_type_interface_prerequisites (type_id, &n_iface_prereqs);
+
+  for (i = 0; i < n_iface_prereqs; i++)
+    {
+      if (g_type_fundamental (iface_prereqs[i]) == G_TYPE_OBJECT)
+	{
+	  is_gobject = TRUE;
+	}
+      ginode->prerequisites =
+	g_list_append (ginode->prerequisites,
+		       g_strdup (g_type_name (iface_prereqs[i])));
+    }
+  
+  if (is_gobject)
+    g_igenerator_process_properties (igenerator, ginode, type_id);
+  else
+    g_type_default_interface_ref (type_id);
+
+  g_igenerator_process_signals (igenerator, ginode, type_id);
+}
+
+static void
+g_igenerator_create_boxed (GIGenerator *igenerator,
+			   const char *symbol_name,
+			   GType type_id,
+			   char *lower_case_prefix)
+{
+  GIdlNodeBoxed *ginode =
+    (GIdlNodeBoxed *) g_idl_node_new (G_IDL_NODE_BOXED);
+  ginode->node.name = g_strdup (g_type_name (type_id));
+  igenerator->module->entries =
+    g_list_insert_sorted (igenerator->module->entries, ginode,
+			  (GCompareFunc) g_idl_node_cmp);
+  g_hash_table_insert (igenerator->type_map, ginode->node.name,
+		       ginode);
+  g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+		       lower_case_prefix, ginode);
+  ginode->gtype_name = ginode->node.name;
+  ginode->gtype_init = g_strdup (symbol_name);
+}
+
+static void
+g_igenerator_create_enum (GIGenerator *igenerator,
+			  const char *symbol_name,
+			  GType type_id,
+			  char *lower_case_prefix)
+{
+  GIdlNodeEnum *ginode;
+  int i;
+  GEnumClass *type_class;
+  
+  ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_ENUM);
+  ginode->node.name = g_strdup (g_type_name (type_id));
+  igenerator->module->entries =
+    g_list_insert_sorted (igenerator->module->entries, ginode,
+			  (GCompareFunc) g_idl_node_cmp);
+  g_hash_table_insert (igenerator->type_map, ginode->node.name,
+		       ginode);
+  g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+		       lower_case_prefix, ginode);
+  ginode->gtype_name = ginode->node.name;
+  ginode->gtype_init = g_strdup (symbol_name);
+  
+  type_class = g_type_class_ref (type_id);
+
+  for (i = 0; i < type_class->n_values; i++)
+    {
+      GIdlNodeValue *gival =
+	(GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
+      ginode->values = g_list_append (ginode->values, gival);
+      gival->node.name =
+	g_strdup (type_class->values[i].value_name);
+      gival->value = type_class->values[i].value;
+    }
+}
+
+static void
+g_igenerator_create_flags (GIGenerator *igenerator,
+			   const char *symbol_name,
+			   GType type_id,
+			   char *lower_case_prefix)
+{
+  GIdlNodeEnum *ginode;
+  GFlagsClass *type_class;
+  int i;
+  
+  ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_FLAGS);
+  ginode->node.name = g_strdup (g_type_name (type_id));
+  igenerator->module->entries =
+    g_list_insert_sorted (igenerator->module->entries, ginode,
+			  (GCompareFunc) g_idl_node_cmp);
+  g_hash_table_insert (igenerator->type_map, ginode->node.name,
+		       ginode);
+  g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+		       lower_case_prefix, ginode);
+  ginode->gtype_name = ginode->node.name;
+  ginode->gtype_init = g_strdup (symbol_name);
+  
+  type_class = g_type_class_ref (type_id);
+  
+  for (i = 0; i < type_class->n_values; i++)
+    {
+      GIdlNodeValue *gival =
+	(GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
+      ginode->values = g_list_append (ginode->values, gival);
+      gival->node.name =
+	g_strdup (type_class->values[i].value_name);
+      gival->value = type_class->values[i].value;
+    }
+}
+
+static gboolean
+g_igenerator_process_module_symbol (GIGenerator *igenerator,
+				    GModule *module,
+				    const gchar *symbol_name)
+{
+  TypeFunction type_fun;
+  GType type_id;
+  GType type_fundamental;
+  char *lower_case_prefix;
+      
+  /* ignore already processed functions */
+  if (symbol_name == NULL)
+    return FALSE;
+      
+  if (!g_module_symbol (module,
+			symbol_name,
+			(gpointer *) & type_fun))
+    return FALSE;
+      
+  type_id = type_fun ();
+  type_fundamental = g_type_fundamental (type_id);
+  lower_case_prefix =
+    str_replace (g_strndup
+		 (symbol_name,
+		  strlen (symbol_name) - strlen ("_get_type")),
+		 "_", "");
+
+  switch (type_fundamental)
+    {
+    case G_TYPE_OBJECT:
+      g_igenerator_create_object (igenerator, symbol_name, type_id,
+				  lower_case_prefix);
+      break;
+    case G_TYPE_INTERFACE:
+      g_igenerator_create_interface (igenerator, symbol_name, type_id,
+				     lower_case_prefix);
+      break;
+    case G_TYPE_BOXED:
+      g_igenerator_create_boxed (igenerator, symbol_name, type_id,
+				 lower_case_prefix);
+      break;
+    case G_TYPE_ENUM:
+      g_igenerator_create_enum (igenerator, symbol_name, type_id,
+				lower_case_prefix);
+      break;
+    case G_TYPE_FLAGS:
+      g_igenerator_create_flags (igenerator, symbol_name, type_id,
+				 lower_case_prefix);
+      break;
+    default:
+      break;
+    }
+  return TRUE;
+}
+
+static void
+g_igenerator_process_module (GIGenerator * igenerator,
+			     const gchar *filename)
+{
+  GModule *module;
+  GList *l;
+  
+  module = g_module_open (filename,
+			  G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+  
+  if (module == NULL)
+    {
+      g_critical ("Couldn't open module: %s", filename);
+      return;
+    }
+
+  for (l = igenerator->get_type_symbols; l != NULL; l = l->next)
+    {
+      if (g_igenerator_process_module_symbol (igenerator,
+					      module, (const char *)l->data))
+	/* symbol found, ignore in future iterations */
+	l->data = NULL;
+    }
+}
+
+static GIdlNodeType *
+get_type_from_ctype (CType * ctype)
+{
+  GIdlNodeType *gitype = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
+  if (ctype->type == CTYPE_VOID)
+    {
+      gitype->unparsed = g_strdup ("void");
+    }
+  else if (ctype->type == CTYPE_BASIC_TYPE)
+    {
+      gitype->unparsed = g_strdup (ctype->name);
+    }
+  else if (ctype->type == CTYPE_TYPEDEF)
+    {
+      gitype->unparsed = g_strdup (ctype->name);
+    }
+  else if (ctype->type == CTYPE_STRUCT)
+    {
+      if (ctype->name == NULL)
+	{
+	  /* anonymous struct */
+	  gitype->unparsed = g_strdup ("gpointer");
+	}
+      else
+	{
+	  gitype->unparsed = g_strdup_printf ("struct %s", ctype->name);
+	}
+    }
+  else if (ctype->type == CTYPE_UNION)
+    {
+      if (ctype->name == NULL)
+	{
+	  /* anonymous union */
+	  gitype->unparsed = g_strdup ("gpointer");
+	}
+      else
+	{
+	  gitype->unparsed = g_strdup_printf ("union %s", ctype->name);
+	}
+    }
+  else if (ctype->type == CTYPE_ENUM)
+    {
+      if (ctype->name == NULL)
+	{
+	  /* anonymous enum */
+	  gitype->unparsed = g_strdup ("gint");
+	}
+      else
+	{
+	  gitype->unparsed = g_strdup_printf ("enum %s", ctype->name);
+	}
+    }
+  else if (ctype->type == CTYPE_POINTER)
+    {
+      if (ctype->base_type->type == CTYPE_FUNCTION)
+	{
+	  /* anonymous function pointer */
+	  gitype->unparsed = g_strdup ("GCallback");
+	}
+      else
+	{
+	  GIdlNodeType *gibasetype = get_type_from_ctype (ctype->base_type);
+	  gitype->unparsed = g_strdup_printf ("%s*", gibasetype->unparsed);
+	}
+    }
+  else if (ctype->type == CTYPE_ARRAY)
+    {
+      GIdlNodeType *gibasetype = get_type_from_ctype (ctype->base_type);
+      gitype->unparsed = g_strdup_printf ("%s[]", gibasetype->unparsed);
+    }
+  else
+    {
+      gitype->unparsed = g_strdup ("unknown");
+    }
+  return gitype;
+}
+
+static void
+g_igenerator_process_function_symbol (GIGenerator * igenerator, CSymbol * sym)
+{
+  GIdlNodeFunction *gifunc =
+    (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_FUNCTION);
+  /* check whether this is a type method */
+  char *last_underscore = strrchr (sym->ident, '_');
+  GList *param_l;
+  int i;
+  GSList *l;
+
+  while (last_underscore != NULL)
+    {
+      char *prefix =
+	str_replace (g_strndup (sym->ident, last_underscore - sym->ident),
+		     "_", "");
+      GIdlNode *ginode =
+	g_hash_table_lookup (igenerator->type_by_lower_case_prefix, prefix);
+      if (ginode != NULL)
+	{
+	  gifunc->node.name = g_strdup (last_underscore + 1);
+	  if (strcmp (gifunc->node.name, "get_type") == 0)
+	    {
+	      /* ignore get_type functions in registered types */
+	      return;
+	    }
+	  if ((ginode->type == G_IDL_NODE_OBJECT
+	       || ginode->type == G_IDL_NODE_BOXED)
+	      && g_str_has_prefix (gifunc->node.name, "new"))
+	    {
+	      gifunc->is_constructor = TRUE;
+	    }
+	  else
+	    {
+	      gifunc->is_method = TRUE;
+	    }
+	  if (ginode->type == G_IDL_NODE_OBJECT
+	      || ginode->type == G_IDL_NODE_INTERFACE)
+	    {
+	      GIdlNodeInterface *giiface = (GIdlNodeInterface *) ginode;
+	      giiface->members =
+		g_list_insert_sorted (giiface->members, gifunc,
+				      (GCompareFunc) g_idl_node_cmp);
+	      break;
+	    }
+	  else if (ginode->type == G_IDL_NODE_BOXED)
+	    {
+	      GIdlNodeBoxed *giboxed = (GIdlNodeBoxed *) ginode;
+	      giboxed->members =
+		g_list_insert_sorted (giboxed->members, gifunc,
+				      (GCompareFunc) g_idl_node_cmp);
+	      break;
+	    }
+	  else if (ginode->type == G_IDL_NODE_STRUCT)
+	    {
+	      GIdlNodeStruct *gistruct = (GIdlNodeStruct *) ginode;
+	      gistruct->members =
+		g_list_insert_sorted (gistruct->members, gifunc,
+				      (GCompareFunc) g_idl_node_cmp);
+	      break;
+	    }
+	  else if (ginode->type == G_IDL_NODE_UNION)
+	    {
+	      GIdlNodeUnion *giunion = (GIdlNodeUnion *) ginode;
+	      giunion->members =
+		g_list_insert_sorted (giunion->members, gifunc,
+				      (GCompareFunc) g_idl_node_cmp);
+	      break;
+	    }
+	}
+      else if (strcmp (igenerator->lower_case_namespace, prefix) == 0)
+	{
+	  gifunc->node.name = g_strdup (last_underscore + 1);
+	  gifunc->is_constructor = FALSE;
+	  gifunc->is_method = FALSE;
+	  igenerator->module->entries =
+	    g_list_insert_sorted (igenerator->module->entries, gifunc,
+				  (GCompareFunc) g_idl_node_cmp);
+	  break;
+	}
+      last_underscore =
+	g_utf8_strrchr (sym->ident, last_underscore - sym->ident, '_');
+    }
+
+  /* create a namespace function if no prefix matches */
+  if (gifunc->node.name == NULL)
+    {
+      gifunc->node.name = sym->ident;
+      gifunc->is_constructor = FALSE;
+      gifunc->is_method = FALSE;
+      igenerator->module->entries =
+	g_list_insert_sorted (igenerator->module->entries, gifunc,
+			      (GCompareFunc) g_idl_node_cmp);
+    }
+
+  gifunc->symbol = sym->ident;
+  gifunc->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+  gifunc->result->type = get_type_from_ctype (sym->base_type->base_type);
+
+  for (param_l = sym->base_type->child_list, i = 1; param_l != NULL;
+       param_l = param_l->next, i++)
+    {
+      CSymbol *param_sym = param_l->data;
+      GIdlNodeParam *param =
+	(GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+      if (param_sym->ident == NULL)
+	{
+	  param->node.name = g_strdup_printf ("p%d", i);
+	}
+      else
+	{
+	  param->node.name = param_sym->ident;
+	}
+      param->type = get_type_from_ctype (param_sym->base_type);
+      gifunc->parameters = g_list_append (gifunc->parameters, param);
+    }
+
+  for (l = sym->directives; l; l = l->next)
+    {
+      CDirective *directive = (CDirective*)l->data;
+
+      if (!strcmp (directive->name, "deprecated"))
+	gifunc->deprecated = strcmp (directive->value, "1") == 0;
+      else
+	g_printerr ("Unknown function directive: %s\n",
+		    directive->name);
+    }
+}
+
+static void
+g_igenerator_process_unregistered_struct_typedef (GIGenerator * igenerator,
+						  CSymbol * sym,
+						  CType * struct_type)
+{
+  GIdlNodeStruct *ginode =
+    (GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT);
+  GList *member_l;
+  char *lower_case_prefix;
+
+  ginode->node.name = sym->ident;
+  igenerator->module->entries =
+    g_list_insert_sorted (igenerator->module->entries, ginode,
+			  (GCompareFunc) g_idl_node_cmp);
+  lower_case_prefix = g_ascii_strdown (sym->ident, -1);
+  g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
+  g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+		       lower_case_prefix, ginode);
+
+  for (member_l = struct_type->child_list; member_l != NULL;
+       member_l = member_l->next)
+    {
+      CSymbol *member = member_l->data;
+      GIdlNodeField *gifield =
+	(GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
+
+      ginode->members = g_list_append (ginode->members, gifield);
+      gifield->node.name = member->ident;
+      gifield->type = get_type_from_ctype (member->base_type);
+    }
+}
+
+static void
+g_igenerator_process_struct_typedef (GIGenerator * igenerator, CSymbol * sym)
+{
+  CType *struct_type = sym->base_type;
+  gboolean opaque_type = FALSE;
+  GIdlNode *gitype;
+  
+  if (struct_type->child_list == NULL)
+    {
+      CSymbol *struct_symbol;
+      g_assert (struct_type->name != NULL);
+      struct_symbol =
+	g_hash_table_lookup (igenerator->struct_or_union_or_enum_table,
+			     struct_type->name);
+      if (struct_symbol != NULL)
+	{
+	  struct_type = struct_symbol->base_type;
+	}
+    }
+
+  if (struct_type->child_list == NULL)
+    {
+      opaque_type = TRUE;
+    }
+  
+  gitype = g_hash_table_lookup (igenerator->type_map, sym->ident);
+  if (gitype != NULL)
+    {
+      /* struct of a GTypeInstance */
+      if (!opaque_type
+	  && (gitype->type == G_IDL_NODE_OBJECT
+	      || gitype->type == G_IDL_NODE_INTERFACE))
+	{
+	  GIdlNodeInterface *ginode = (GIdlNodeInterface *) gitype;
+	  GList *member_l;
+	  /* ignore first field => parent */
+	  for (member_l = struct_type->child_list->next; member_l != NULL;
+	       member_l = member_l->next)
+	    {
+	      CSymbol *member = member_l->data;
+	      /* ignore private / reserved members */
+	      if (member->ident[0] == '_'
+		  || g_str_has_prefix (member->ident, "priv"))
+		{
+		  continue;
+		}
+	      GIdlNodeField *gifield =
+		(GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
+	      ginode->members = g_list_append (ginode->members, gifield);
+	      gifield->node.name = member->ident;
+	      gifield->type = get_type_from_ctype (member->base_type);
+	    }
+	}
+      else if (gitype->type == G_IDL_NODE_BOXED)
+	{
+	  GIdlNodeBoxed *ginode = (GIdlNodeBoxed *) gitype;
+	  GList *member_l;
+	  for (member_l = struct_type->child_list; member_l != NULL;
+	       member_l = member_l->next)
+	    {
+	      CSymbol *member = member_l->data;
+	      GIdlNodeField *gifield =
+		(GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
+	      ginode->members = g_list_append (ginode->members, gifield);
+	      gifield->node.name = member->ident;
+	      gifield->type = get_type_from_ctype (member->base_type);
+	    }
+	}
+    }
+  else if (!opaque_type
+	   && (g_str_has_suffix (sym->ident, "Class")
+	       || g_str_has_suffix (sym->ident, "Iface")
+	       || g_str_has_suffix (sym->ident, "Interface")))
+    {
+      char *base_name;
+      GList *member_l;
+      GIdlNodeInterface *ginode;
+
+      if (g_str_has_suffix (sym->ident, "Interface"))
+	{
+	  base_name =
+	    g_strndup (sym->ident,
+		       strlen (sym->ident) - strlen ("Interface"));
+	}
+      else
+	{
+	  base_name =
+	    g_strndup (sym->ident, strlen (sym->ident) - strlen ("Class"));
+	}
+      gitype = g_hash_table_lookup (igenerator->type_map, base_name);
+      if (gitype == NULL
+	  || (gitype->type != G_IDL_NODE_OBJECT
+	      && gitype->type != G_IDL_NODE_INTERFACE))
+	{
+	  g_igenerator_process_unregistered_struct_typedef (igenerator, sym,
+							    struct_type);
+	  return;
+	}
+      ginode = (GIdlNodeInterface *) gitype;
+
+      /* ignore first field => parent */
+      for (member_l = struct_type->child_list->next; member_l != NULL;
+	   member_l = member_l->next)
+	{
+	  CSymbol *member = member_l->data;
+	  /* ignore private / reserved members */
+	  if (member->ident[0] == '_')
+	    {
+	      continue;
+	    }
+	  if (member->base_type->type == CTYPE_POINTER
+	      && member->base_type->base_type->type == CTYPE_FUNCTION)
+	    {
+	      /* ignore default handlers of signals */
+	      gboolean found_signal = FALSE;
+	      GList *type_member_l;
+	      GList *param_l;
+	      int i;
+	      GIdlNodeVFunc *givfunc;
+	      
+	      for (type_member_l = ginode->members; type_member_l != NULL;
+		   type_member_l = type_member_l->next)
+		{
+		  GIdlNode *type_member = type_member_l->data;
+		  char *normalized_name =
+		    str_replace (type_member->name, "-", "_");
+		  if (type_member->type == G_IDL_NODE_SIGNAL
+		      && strcmp (normalized_name, member->ident) == 0)
+		    {
+		      GList *vfunc_param_l;
+		      GList *sig_param_l;
+		      GIdlNodeSignal *sig = (GIdlNodeSignal *) type_member;
+		      found_signal = TRUE;
+		      /* set signal parameter names */
+		      for (vfunc_param_l =
+			   member->base_type->base_type->child_list,
+			   sig_param_l = sig->parameters;
+			   vfunc_param_l != NULL && sig_param_l != NULL;
+			   vfunc_param_l = vfunc_param_l->next, sig_param_l =
+			   sig_param_l->next)
+			{
+			  CSymbol *vfunc_param = vfunc_param_l->data;
+			  GIdlNodeParam *sig_param = sig_param_l->data;
+			  if (vfunc_param->ident != NULL)
+			    {
+			      g_free (sig_param->node.name);
+			      sig_param->node.name =
+				g_strdup (vfunc_param->ident);
+			    }
 			}
+		      break;
+		    }
 		}
-	} else if (g_str_has_suffix (sym->ident, "Private")) {
-		/* ignore private structs */
-	} else {
-		g_igenerator_process_unregistered_struct_typedef (igenerator, sym, struct_type);
-	}
-}
-
-static void g_igenerator_process_union_typedef (GIGenerator *igenerator, CSymbol *sym)
-{
-	CType *union_type = sym->base_type;
-	gboolean opaque_type = FALSE;
-	if (union_type->child_list == NULL) {
-		g_assert (union_type->name != NULL);
-		CSymbol *union_symbol = g_hash_table_lookup (igenerator->struct_or_union_or_enum_table, union_type->name);
-		if (union_symbol != NULL) {
-			union_type = union_symbol->base_type;
-		}
-	}
-	if (union_type->child_list == NULL) {
-		opaque_type = TRUE;
-	}
-	GIdlNode *gitype = g_hash_table_lookup (igenerator->type_map, sym->ident);
-	if (gitype != NULL) {
-		g_assert (gitype->type == G_IDL_NODE_BOXED);
-		GIdlNodeBoxed *ginode = (GIdlNodeBoxed *) gitype;
-		GList *member_l;
-		for (member_l = union_type->child_list; member_l != NULL; member_l = member_l->next) {
-			CSymbol *member = member_l->data;
-			GIdlNodeField *gifield = (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
-			ginode->members = g_list_append (ginode->members, gifield);
-			gifield->node.name = member->ident;
-			gifield->type = get_type_from_ctype (member->base_type);
-		}
-	} else {
-		GIdlNodeUnion *ginode = (GIdlNodeUnion *) g_idl_node_new (G_IDL_NODE_UNION);
-		ginode->node.name = sym->ident;
-		igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
-		char *lower_case_prefix = g_ascii_strdown (sym->ident, -1);
-		g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
-		g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
-
-		ginode->node.name = sym->ident;
-		GList *member_l;
-		for (member_l = union_type->child_list; member_l != NULL; member_l = member_l->next) {
-			CSymbol *member = member_l->data;
-			GIdlNodeField *gifield = (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
-			ginode->members = g_list_append (ginode->members, gifield);
-			gifield->node.name = member->ident;
-			gifield->type = get_type_from_ctype (member->base_type);
-		}
-	}
-}
-
-static void g_igenerator_process_enum_typedef (GIGenerator *igenerator, CSymbol *sym)
-{
-	CType *enum_type = sym->base_type;
-	if (enum_type->child_list == NULL) {
-		g_assert (enum_type->name != NULL);
-		CSymbol *enum_symbol = g_hash_table_lookup (igenerator->struct_or_union_or_enum_table, enum_type->name);
-		if (enum_symbol != NULL) {
-			enum_type = enum_symbol->base_type;
-		}
-	}
-	if (enum_type->child_list == NULL) {
-		/* opaque type */
-		return;
-	}
-	GIdlNodeEnum *ginode = g_hash_table_lookup (igenerator->type_map, sym->ident);
-	if (ginode != NULL) {
-		return;
-	}
-
-	ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_ENUM);
-	ginode->node.name = sym->ident;
-	igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
-
-	GList *member_l;
-	for (member_l = enum_type->child_list; member_l != NULL; member_l = member_l->next) {
-		CSymbol *member = member_l->data;
-		GIdlNodeValue *gival = (GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
-		ginode->values = g_list_append (ginode->values, gival);
-		gival->node.name = member->ident;
-		gival->value = member->const_int;
-	}
-}
-
-static void g_igenerator_process_function_typedef (GIGenerator *igenerator, CSymbol *sym)
-{
-	/* handle callback types */
-	GIdlNodeFunction *gifunc = (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_CALLBACK);
-
-	gifunc->node.name = sym->ident;
-	igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, gifunc, (GCompareFunc) g_idl_node_cmp);
-
-	gifunc->symbol = sym->ident;
-	gifunc->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
-	gifunc->result->type = get_type_from_ctype (sym->base_type->base_type->base_type);
-	GList *param_l;
-	int i;
-	for (param_l = sym->base_type->base_type->child_list, i = 1; param_l != NULL; param_l = param_l->next, i++) {
-		CSymbol *param_sym = param_l->data;
-		GIdlNodeParam *param = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
-		if (param_sym->ident == NULL) {
-			param->node.name = g_strdup_printf ("p%d", i);
-		} else {
-			param->node.name = param_sym->ident;
-		}
-		param->type = get_type_from_ctype (param_sym->base_type);
-		gifunc->parameters = g_list_append (gifunc->parameters, param);
-	}
-}
-
-static void g_igenerator_process_constant (GIGenerator *igenerator, CSymbol *sym)
-{
-	GIdlNodeConstant *giconst = (GIdlNodeConstant *) g_idl_node_new (G_IDL_NODE_CONSTANT);
-	giconst->node.name = sym->ident;
-	igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, giconst, (GCompareFunc) g_idl_node_cmp);
-
-	giconst->type = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
-	if (sym->const_int_set) {
-		giconst->type->unparsed = g_strdup ("int");
-		giconst->value = g_strdup_printf ("%d", sym->const_int);
-	} else if (sym->const_string != NULL) {
-		giconst->type->unparsed = g_strdup ("char*");
-		giconst->value = sym->const_string;
-	}
-}
-
-static void g_igenerator_process_symbols (GIGenerator *igenerator)
-{
-	GList *l;
-	/* process type symbols first to ensure complete type hashtables */
-	/* type symbols */
-	for (l = igenerator->symbol_list; l != NULL; l = l->next) {
-		CSymbol *sym = l->data;
-		if (sym->ident[0] == '_') {
-			/* ignore private / reserved symbols */
-			continue;
-		}
-		if (sym->type == CSYMBOL_TYPE_TYPEDEF) {
-			if (sym->base_type->type == CTYPE_STRUCT) {
-				g_igenerator_process_struct_typedef (igenerator, sym);
-			} else if (sym->base_type->type == CTYPE_UNION) {
-				g_igenerator_process_union_typedef (igenerator, sym);
-			} else if (sym->base_type->type == CTYPE_ENUM) {
-				g_igenerator_process_enum_typedef (igenerator, sym);
-			} else if (sym->base_type->type == CTYPE_POINTER && sym->base_type->base_type->type == CTYPE_FUNCTION) {
-				g_igenerator_process_function_typedef (igenerator, sym);
-			} else {
-				GIdlNodeStruct *ginode = (GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT);
-				ginode->node.name = sym->ident;
-				igenerator->module->entries = g_list_insert_sorted (igenerator->module->entries, ginode, (GCompareFunc) g_idl_node_cmp);
-				char *lower_case_prefix = g_ascii_strdown (sym->ident, -1);
-				g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
-				g_hash_table_insert (igenerator->type_by_lower_case_prefix, lower_case_prefix, ginode);
-			}
-		}
-	}
-	/* other symbols */
-	for (l = igenerator->symbol_list; l != NULL; l = l->next) {
-		CSymbol *sym = l->data;
-		if (sym->ident[0] == '_') {
-			/* ignore private / reserved symbols */
-			continue;
-		}
-		if (sym->type == CSYMBOL_TYPE_FUNCTION) {
-			g_igenerator_process_function_symbol (igenerator, sym);
-		} else if (sym->type == CSYMBOL_TYPE_CONST) {
-			g_igenerator_process_constant (igenerator, sym);
-		}
-	}
-}
-
-void g_igenerator_add_symbol (GIGenerator *igenerator, CSymbol *symbol)
-{
-	/* only add symbols of main file */
-	gboolean found_filename = FALSE;
-	GList *l;
-	for (l = igenerator->filenames; l != NULL; l = l->next) {
-		if (strcmp (l->data, igenerator->current_filename) == 0) {
-			found_filename = TRUE;
-			break;
-		}
-	}
-	if (found_filename || igenerator->macro_scan) {
-		igenerator->symbol_list = g_list_prepend (igenerator->symbol_list, symbol);
-	}
-
-	if (symbol->type == CSYMBOL_TYPE_TYPEDEF) {
-		g_hash_table_insert (igenerator->typedef_table, symbol->ident, symbol);
-	} else if (symbol->type == CSYMBOL_TYPE_STRUCT || symbol->type == CSYMBOL_TYPE_UNION || symbol->type == CSYMBOL_TYPE_ENUM) {
-		g_hash_table_insert (igenerator->struct_or_union_or_enum_table, symbol->ident, symbol);
-	}
-}
-
-gboolean g_igenerator_is_typedef (GIGenerator *igenerator, const char *name)
-{
-	gboolean b = g_hash_table_lookup (igenerator->typedef_table, name) != NULL;
-	return b;
-}
-
-void g_igenerator_generate (GIGenerator *igenerator)
-{
-	GList *l;
-	for (l = igenerator->symbol_list; l != NULL; l = l->next) {
-		CSymbol *sym = l->data;
-		if (sym->type == CSYMBOL_TYPE_FUNCTION && g_str_has_suffix (sym->ident, "_get_type")) {
-			if (sym->base_type->child_list == NULL) {
-				// ignore get_type functions with parameters
-				igenerator->get_type_symbols = g_list_prepend (igenerator->get_type_symbols, sym->ident);
-			}
-		}
-	}
-	g_igenerator_process_types (igenerator);
-	g_igenerator_process_symbols (igenerator);
-
-	g_igenerator_write (igenerator, "<?xml version=\"1.0\"?>\n");
-	g_igenerator_write_indent (igenerator, "<api version=\"1.0\">\n");
-	module_generate (igenerator, igenerator->module);
-	g_igenerator_write_unindent (igenerator, "</api>\n");
-}
-
-int main (int argc, char **argv)
-{
-	g_type_init ();
-
-	/* initialize threading as this may be required by libraries that we'll use */
-	g_thread_init (NULL);
-
-	GIGenerator *igenerator = g_igenerator_new ();
-
-	int cpp_argc = 0;
-	char **cpp_argv = g_new0 (char *, argc + 2);
-	cpp_argv[cpp_argc++] = "cc";
-	cpp_argv[cpp_argc++] = "-E";
-
-	int i;
-	for (i = 1; i < argc; i++) {
-		if (argv[i][0] == '-') {
-			switch (argv[i][1]) {
-			case '-':
-				if (g_str_has_prefix (argv[i], "--namespace=")) {
-					igenerator->namespace = argv[i] + strlen ("--namespace=");
-					g_free (igenerator->lower_case_namespace);
-					igenerator->lower_case_namespace = g_ascii_strdown (igenerator->namespace, -1);
-				}
-				break;
-			case 'I':
-			case 'D':
-			case 'U':
-				cpp_argv[cpp_argc++] = argv[i];
-				break;
-			}
-		} else if (g_str_has_suffix (argv[i], ".h")) {
-			igenerator->filenames = g_list_append (igenerator->filenames, argv[i]);
-		} else if (g_str_has_suffix (argv[i], ".la") ||
-		           g_str_has_suffix (argv[i], ".so") ||
-		           g_str_has_suffix (argv[i], ".dll")) {
-			igenerator->libraries = g_list_append (igenerator->libraries, argv[i]);
-		}
-	}
-
-
-	GError *error = NULL;
-
-	char *tmp_name = NULL;
-	FILE *f= fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error), "w");
-
-
-	GList *l;
-	for (l = igenerator->filenames; l != NULL; l = l->next) {
-		fprintf (f, "#include <%s>\n", (char *) l->data);
-	}
-
-
-	fclose (f);
-
-	cpp_argv[cpp_argc++] = tmp_name;
-	cpp_argv[cpp_argc++] = NULL;
-
-	int cpp_out = -1;
-	g_spawn_async_with_pipes (NULL, cpp_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, NULL, &cpp_out, NULL, &error);
-	if (error != NULL) {
-		g_error ("%s", error->message);
-	}
-
-	g_igenerator_parse (igenerator, fdopen (cpp_out, "r"));
-
-	g_unlink (tmp_name);
-
-	g_igenerator_parse_macros (igenerator);
-
-	igenerator->module = g_idl_module_new (igenerator->namespace);
-	g_igenerator_generate (igenerator);
-
-	return 0;
-}
-
-CSymbol *csymbol_new (CSymbolType type) {
-	CSymbol *s = g_new0 (CSymbol, 1);
-	s->type = type;
-	return s;
-}
-
-gboolean csymbol_get_const_boolean (CSymbol *symbol) {
-	return (symbol->const_int_set && symbol->const_int) || symbol->const_string;
-}
-
-CType *ctype_new (CTypeType type) {
-	CType *t = g_new0 (CType, 1);
-	t->type = type;
-	return t;
-}
-
-CType *ctype_copy (CType *type) {
-	return g_memdup (type, sizeof (CType));
-}
-
-CType *cbasic_type_new (const char *name) {
-	CType *basic_type = ctype_new (CTYPE_BASIC_TYPE);
-	basic_type->name = g_strdup (name);
-	return basic_type;
-}
-
-CType *ctypedef_new (const char *name) {
-	CType *typedef_ = ctype_new (CTYPE_TYPEDEF);
-	typedef_->name = g_strdup (name);
-	return typedef_;
-}
-
-CType *cstruct_new (const char *name) {
-	CType *struct_ = ctype_new (CTYPE_STRUCT);
-	struct_->name = g_strdup (name);
-	return struct_;
-}
-
-CType *cunion_new (const char *name) {
-	CType *union_ = ctype_new (CTYPE_UNION);
-	union_->name = g_strdup (name);
-	return union_;
-}
-
-CType *cenum_new (const char *name) {
-	CType *enum_ = ctype_new (CTYPE_ENUM);
-	enum_->name = g_strdup (name);
-	return enum_;
-}
-
-CType *cpointer_new (CType *base_type) {
-	CType *pointer = ctype_new (CTYPE_POINTER);
-	pointer->base_type = base_type;
-	return pointer;
-}
-
-CType *carray_new (void) {
-	CType *array = ctype_new (CTYPE_ARRAY);
-	return array;
-}
-
-CType *cfunction_new (void) {
-	CType *func = ctype_new (CTYPE_FUNCTION);
-	return func;
-}
-
-static int eat_hspace (FILE *f) {
-	int c;
-	do {
-		c = fgetc (f);
-	} while (c == ' ' || c == '\t');
-	return c;
-}
-
-static int eat_line (FILE *f, int c) {
-	while (c != EOF && c != '\n') {
-		c = fgetc (f);
-	}
-	if (c == '\n') {
-		c = fgetc (f);
-		if (c == ' ' || c == '\t') {
-			c = eat_hspace (f);
-		}
-	}
-	return c;
-}
-
-static int read_identifier (FILE *f, int c, char **identifier) {
-	GString *id = g_string_new ("");
-	while (isalnum (c) || c == '_') {
-		g_string_append_c (id, c);
-		c = fgetc (f);
-	}
-	*identifier = g_string_free (id, FALSE);
-	return c;
-}
-
-static void g_igenerator_parse_macros (GIGenerator *igenerator) {
-	GError *error = NULL;
-	char *tmp_name = NULL;
-	FILE *fmacros = fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error), "w+");
-	g_unlink (tmp_name);
-
-	GList *l;
-	for (l = igenerator->filenames; l != NULL; l = l->next) {
-		FILE *f = fopen (l->data, "r");
-		int line = 1;
-
-		GString *define_line;
-		char *str;
-		gboolean error_line = FALSE;
-		int c = eat_hspace (f);
-		while (c != EOF) {
-			if (c != '#') {
-				/* ignore line */
-				c = eat_line (f, c);
-				line++;
-				continue;
-			}
-
-			/* print current location */
-			str = g_strescape (l->data, "");
-			fprintf (fmacros, "# %d \"%s\"\n", line, str);
-			g_free (str);
-
-			c = eat_hspace (f);
-			c = read_identifier (f, c, &str);
-			if (strcmp (str, "define") != 0 || (c != ' ' && c != '\t')) {
-				g_free (str);
-				/* ignore line */
-				c = eat_line (f, c);
-				line++;
-				continue;
-			}
-			g_free (str);
-			c = eat_hspace (f);
-			c = read_identifier (f, c, &str);
-			if (strlen (str) == 0 || (c != ' ' && c != '\t' && c != '(')) {
-				g_free (str);
-				/* ignore line */
-				c = eat_line (f, c);
-				line++;
-				continue;
-			}
-			define_line = g_string_new ("#define ");
-			g_string_append (define_line, str);
-			g_free (str);
-			if (c == '(') {
-				while (c != ')') {
-					g_string_append_c (define_line, c);
-					c = fgetc (f);
-					if (c == EOF || c == '\n') {
-						error_line = TRUE;
-						break;
-					}
-				}
-				if (error_line) {
-					g_string_free (define_line, TRUE);
-					/* ignore line */
-					c = eat_line (f, c);
-					line++;
-					continue;
-				}
-
-				g_assert (c == ')');
-				g_string_append_c (define_line, c);
-				c = fgetc (f);
-
-				/* found function-like macro */
-				fprintf (fmacros, "%s\n", define_line->str);
-
-				g_string_free (define_line, TRUE);
-				/* ignore rest of line */
-				c = eat_line (f, c);
-				line++;
-				continue;
-			}
-			if (c != ' ' && c != '\t') {
-				g_string_free (define_line, TRUE);
-				/* ignore line */
-				c = eat_line (f, c);
-				line++;
-				continue;
-			}
-			while (c != EOF && c != '\n') {
-				g_string_append_c (define_line, c);
-				c = fgetc (f);
-				if (c == '\\') {
-					c = fgetc (f);
-					if (c == '\n') {
-						/* fold lines when seeing backslash new-line sequence */
-						c = fgetc (f);
-					} else {
-						g_string_append_c (define_line, '\\');
-					}
-				}
-			}
-
-			/* found object-like macro */
-			fprintf (fmacros, "%s\n", define_line->str);
-
-			c = eat_line (f, c);
-			line++;
-		}
-
-		fclose (f);
+	      if (found_signal)
+		{
+		  continue;
+		}
+
+	      givfunc = (GIdlNodeVFunc *) g_idl_node_new (G_IDL_NODE_VFUNC);
+	      givfunc->node.name = member->ident;
+	      ginode->members =
+		g_list_insert_sorted (ginode->members, givfunc,
+				      (GCompareFunc) g_idl_node_cmp);
+	      givfunc->result =
+		(GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+	      givfunc->result->type =
+		get_type_from_ctype (member->base_type->base_type->base_type);
+	      for (param_l = member->base_type->base_type->child_list, i = 1;
+		   param_l != NULL; param_l = param_l->next, i++)
+		{
+		  CSymbol *param_sym = param_l->data;
+		  GIdlNodeParam *param =
+		    (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+		  if (param_sym->ident == NULL)
+		    {
+		      param->node.name = g_strdup_printf ("p%d", i);
+		    }
+		  else
+		    {
+		      param->node.name = param_sym->ident;
+		    }
+		  param->type = get_type_from_ctype (param_sym->base_type);
+		  givfunc->parameters =
+		    g_list_append (givfunc->parameters, param);
+		}
+	    }
+	}
+    }
+  else if (g_str_has_suffix (sym->ident, "Private"))
+    {
+      /* ignore private structs */
+    }
+  else
+    {
+      g_igenerator_process_unregistered_struct_typedef (igenerator, sym,
+							struct_type);
+    }
+}
+
+static void
+g_igenerator_process_union_typedef (GIGenerator * igenerator, CSymbol * sym)
+{
+  CType *union_type = sym->base_type;
+  gboolean opaque_type = FALSE;
+  GIdlNode *gitype;
+  
+  if (union_type->child_list == NULL)
+    {
+      g_assert (union_type->name != NULL);
+      CSymbol *union_symbol =
+	g_hash_table_lookup (igenerator->struct_or_union_or_enum_table,
+			     union_type->name);
+      if (union_symbol != NULL)
+	{
+	  union_type = union_symbol->base_type;
+	}
+    }
+  if (union_type->child_list == NULL)
+    {
+      opaque_type = TRUE;
+    }
+
+  gitype = g_hash_table_lookup (igenerator->type_map, sym->ident);
+  if (gitype != NULL)
+    {
+      g_assert (gitype->type == G_IDL_NODE_BOXED);
+      GIdlNodeBoxed *ginode = (GIdlNodeBoxed *) gitype;
+      GList *member_l;
+      for (member_l = union_type->child_list; member_l != NULL;
+	   member_l = member_l->next)
+	{
+	  CSymbol *member = member_l->data;
+	  GIdlNodeField *gifield =
+	    (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
+	  ginode->members = g_list_append (ginode->members, gifield);
+	  gifield->node.name = member->ident;
+	  gifield->type = get_type_from_ctype (member->base_type);
+	}
+    }
+  else
+    {
+      GIdlNodeUnion *ginode =
+	(GIdlNodeUnion *) g_idl_node_new (G_IDL_NODE_UNION);
+      char *lower_case_prefix;
+      GList *member_l;
+      
+      ginode->node.name = sym->ident;
+      igenerator->module->entries =
+	g_list_insert_sorted (igenerator->module->entries, ginode,
+			      (GCompareFunc) g_idl_node_cmp);
+      lower_case_prefix = g_ascii_strdown (sym->ident, -1);
+      g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
+      g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+			   lower_case_prefix, ginode);
+
+      ginode->node.name = sym->ident;
+      for (member_l = union_type->child_list; member_l != NULL;
+	   member_l = member_l->next)
+	{
+	  CSymbol *member = member_l->data;
+	  GIdlNodeField *gifield =
+	    (GIdlNodeField *) g_idl_node_new (G_IDL_NODE_FIELD);
+	  ginode->members = g_list_append (ginode->members, gifield);
+	  gifield->node.name = member->ident;
+	  gifield->type = get_type_from_ctype (member->base_type);
+	}
+    }
+}
+
+static void
+g_igenerator_process_enum_typedef (GIGenerator * igenerator, CSymbol * sym)
+{
+  CType *enum_type;
+  GList *member_l;
+  GIdlNodeEnum *ginode;
+  CSymbol *enum_symbol;
+
+  enum_type = sym->base_type;
+  if (enum_type->child_list == NULL)
+    {
+      g_assert (enum_type->name != NULL);
+      enum_symbol =
+	g_hash_table_lookup (igenerator->struct_or_union_or_enum_table,
+			     enum_type->name);
+      if (enum_symbol != NULL)
+	{
+	  enum_type = enum_symbol->base_type;
+	}
+    }
+  if (enum_type->child_list == NULL)
+    {
+      /* opaque type */
+      return;
+    }
+  
+  ginode = g_hash_table_lookup (igenerator->type_map, sym->ident);
+  if (ginode != NULL)
+    {
+      return;
+    }
+
+  ginode = (GIdlNodeEnum *) g_idl_node_new (G_IDL_NODE_ENUM);
+  ginode->node.name = sym->ident;
+  igenerator->module->entries =
+    g_list_insert_sorted (igenerator->module->entries, ginode,
+			  (GCompareFunc) g_idl_node_cmp);
+
+  for (member_l = enum_type->child_list; member_l != NULL;
+       member_l = member_l->next)
+    {
+      CSymbol *member = member_l->data;
+      GIdlNodeValue *gival =
+	(GIdlNodeValue *) g_idl_node_new (G_IDL_NODE_VALUE);
+      ginode->values = g_list_append (ginode->values, gival);
+      gival->node.name = member->ident;
+      gival->value = member->const_int;
+    }
+}
+
+static void
+g_igenerator_process_function_typedef (GIGenerator * igenerator,
+				       CSymbol * sym)
+{
+  GList *param_l;
+  int i;
+
+  /* handle callback types */
+  GIdlNodeFunction *gifunc =
+    (GIdlNodeFunction *) g_idl_node_new (G_IDL_NODE_CALLBACK);
+
+  gifunc->node.name = sym->ident;
+  igenerator->module->entries =
+    g_list_insert_sorted (igenerator->module->entries, gifunc,
+			  (GCompareFunc) g_idl_node_cmp);
+
+  gifunc->symbol = sym->ident;
+  gifunc->result = (GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+  gifunc->result->type =
+    get_type_from_ctype (sym->base_type->base_type->base_type);
+
+  for (param_l = sym->base_type->base_type->child_list, i = 1;
+       param_l != NULL; param_l = param_l->next, i++)
+    {
+      CSymbol *param_sym = param_l->data;
+      GIdlNodeParam *param =
+	(GIdlNodeParam *) g_idl_node_new (G_IDL_NODE_PARAM);
+      if (param_sym->ident == NULL)
+	{
+	  param->node.name = g_strdup_printf ("p%d", i);
+	}
+      else
+	{
+	  param->node.name = param_sym->ident;
+	}
+      param->type = get_type_from_ctype (param_sym->base_type);
+      gifunc->parameters = g_list_append (gifunc->parameters, param);
+    }
+}
+
+static void
+g_igenerator_process_constant (GIGenerator * igenerator, CSymbol * sym)
+{
+  GIdlNodeConstant *giconst =
+    (GIdlNodeConstant *) g_idl_node_new (G_IDL_NODE_CONSTANT);
+  giconst->node.name = sym->ident;
+  igenerator->module->entries =
+    g_list_insert_sorted (igenerator->module->entries, giconst,
+			  (GCompareFunc) g_idl_node_cmp);
+
+  giconst->type = (GIdlNodeType *) g_idl_node_new (G_IDL_NODE_TYPE);
+  if (sym->const_int_set)
+    {
+      giconst->type->unparsed = g_strdup ("int");
+      giconst->value = g_strdup_printf ("%d", sym->const_int);
+    }
+  else if (sym->const_string != NULL)
+    {
+      giconst->type->unparsed = g_strdup ("char*");
+      giconst->value = sym->const_string;
+    }
+}
+
+static void
+g_igenerator_process_symbols (GIGenerator * igenerator)
+{
+  GList *l;
+  /* process type symbols first to ensure complete type hashtables */
+  /* type symbols */
+  for (l = igenerator->symbol_list; l != NULL; l = l->next)
+    {
+      CSymbol *sym = l->data;
+      if (sym->ident[0] == '_')
+	{
+	  /* ignore private / reserved symbols */
+	  continue;
+	}
+      if (sym->type == CSYMBOL_TYPE_TYPEDEF)
+	{
+	  if (sym->base_type->type == CTYPE_STRUCT)
+	    {
+	      g_igenerator_process_struct_typedef (igenerator, sym);
+	    }
+	  else if (sym->base_type->type == CTYPE_UNION)
+	    {
+	      g_igenerator_process_union_typedef (igenerator, sym);
+	    }
+	  else if (sym->base_type->type == CTYPE_ENUM)
+	    {
+	      g_igenerator_process_enum_typedef (igenerator, sym);
+	    }
+	  else if (sym->base_type->type == CTYPE_POINTER
+		   && sym->base_type->base_type->type == CTYPE_FUNCTION)
+	    {
+	      g_igenerator_process_function_typedef (igenerator, sym);
+	    }
+	  else
+	    {
+	      GIdlNodeStruct *ginode =
+		(GIdlNodeStruct *) g_idl_node_new (G_IDL_NODE_STRUCT);
+	      char *lower_case_prefix;
+	      
+	      ginode->node.name = sym->ident;
+	      igenerator->module->entries =
+		g_list_insert_sorted (igenerator->module->entries, ginode,
+				      (GCompareFunc) g_idl_node_cmp);
+	      lower_case_prefix = g_ascii_strdown (sym->ident, -1);
+	      g_hash_table_insert (igenerator->type_map, sym->ident, ginode);
+	      g_hash_table_insert (igenerator->type_by_lower_case_prefix,
+				   lower_case_prefix, ginode);
+	    }
+	}
+    }
+  /* other symbols */
+  for (l = igenerator->symbol_list; l != NULL; l = l->next)
+    {
+      CSymbol *sym = l->data;
+      if (sym->ident[0] == '_')
+	{
+	  /* ignore private / reserved symbols */
+	  continue;
+	}
+      if (sym->type == CSYMBOL_TYPE_FUNCTION)
+	{
+	  g_igenerator_process_function_symbol (igenerator, sym);
+	}
+      else if (sym->type == CSYMBOL_TYPE_CONST)
+	{
+	  g_igenerator_process_constant (igenerator, sym);
+	}
+    }
+}
+
+void
+g_igenerator_add_symbol (GIGenerator * igenerator, CSymbol * symbol)
+{
+  /* only add symbols of main file */
+  gboolean found_filename = FALSE;
+  GList *l;
+  for (l = igenerator->filenames; l != NULL; l = l->next)
+    {
+      if (strcmp (l->data, igenerator->current_filename) == 0)
+	{
+	  found_filename = TRUE;
+	  break;
+	}
+    }
+
+  symbol->directives = g_slist_reverse (igenerator->directives);
+  igenerator->directives = NULL;
+
+  if (found_filename || igenerator->macro_scan)
+    {
+      igenerator->symbol_list =
+	g_list_prepend (igenerator->symbol_list, symbol);
+    }
+
+  if (symbol->type == CSYMBOL_TYPE_TYPEDEF)
+
+    {
+      g_hash_table_insert (igenerator->typedef_table, symbol->ident, symbol);
+    }
+  else if (symbol->type == CSYMBOL_TYPE_STRUCT
+	   || symbol->type == CSYMBOL_TYPE_UNION
+	   || symbol->type == CSYMBOL_TYPE_ENUM)
+    {
+      g_hash_table_insert (igenerator->struct_or_union_or_enum_table,
+			   symbol->ident, symbol);
+    }
+}
+
+gboolean
+g_igenerator_is_typedef (GIGenerator * igenerator, const char *name)
+{
+  gboolean b = g_hash_table_lookup (igenerator->typedef_table, name) != NULL;
+  return b;
+}
+
+void
+g_igenerator_generate (GIGenerator * igenerator,
+		       const gchar * filename,
+		       GList *libraries)
+{
+  GList *l;
+  
+  for (l = igenerator->symbol_list; l != NULL; l = l->next)
+    {
+      CSymbol *sym = l->data;
+      if (sym->type == CSYMBOL_TYPE_FUNCTION
+	  && g_str_has_suffix (sym->ident, "_get_type"))
+	{
+	  if (sym->base_type->child_list == NULL)
+	    {
+	      // ignore get_type functions with parameters
+	      igenerator->get_type_symbols =
+		g_list_prepend (igenerator->get_type_symbols, sym->ident);
+	    }
+	}
+    }
+
+  /* ensure to initialize GObject */
+  g_type_class_ref (G_TYPE_OBJECT);
+
+  for (l = libraries; l; l = l->next)
+      g_igenerator_process_module (igenerator, (const gchar*)l->data);
+
+  g_igenerator_process_symbols (igenerator);
+
+  g_idl_writer_save_file (igenerator->module, filename);
+}
+
+static int
+eat_hspace (FILE * f)
+{
+  int c;
+  do
+    {
+      c = fgetc (f);
+    }
+  while (c == ' ' || c == '\t');
+  return c;
+}
+
+static int
+eat_line (FILE * f, int c)
+{
+  while (c != EOF && c != '\n')
+    {
+      c = fgetc (f);
+    }
+  if (c == '\n')
+    {
+      c = fgetc (f);
+      if (c == ' ' || c == '\t')
+	{
+	  c = eat_hspace (f);
+	}
+    }
+  return c;
+}
+
+static int
+read_identifier (FILE * f, int c, char **identifier)
+{
+  GString *id = g_string_new ("");
+  while (isalnum (c) || c == '_')
+    {
+      g_string_append_c (id, c);
+      c = fgetc (f);
+    }
+  *identifier = g_string_free (id, FALSE);
+  return c;
+}
+
+static void
+g_igenerator_parse_macros (GIGenerator * igenerator)
+{
+  GError *error = NULL;
+  char *tmp_name = NULL;
+  FILE *fmacros =
+    fdopen (g_file_open_tmp ("gen-introspect-XXXXXX.h", &tmp_name, &error),
+	    "w+");
+  g_unlink (tmp_name);
+
+  GList *l;
+  for (l = igenerator->filenames; l != NULL; l = l->next)
+    {
+      FILE *f = fopen (l->data, "r");
+      int line = 1;
+
+      GString *define_line;
+      char *str;
+      gboolean error_line = FALSE;
+      int c = eat_hspace (f);
+      while (c != EOF)
+	{
+	  if (c != '#')
+	    {
+	      /* ignore line */
+	      c = eat_line (f, c);
+	      line++;
+	      continue;
+	    }
+
+	  /* print current location */
+	  str = g_strescape (l->data, "");
+	  fprintf (fmacros, "# %d \"%s\"\n", line, str);
+	  g_free (str);
+
+	  c = eat_hspace (f);
+	  c = read_identifier (f, c, &str);
+	  if (strcmp (str, "define") != 0 || (c != ' ' && c != '\t'))
+	    {
+	      g_free (str);
+	      /* ignore line */
+	      c = eat_line (f, c);
+	      line++;
+	      continue;
+	    }
+	  g_free (str);
+	  c = eat_hspace (f);
+	  c = read_identifier (f, c, &str);
+	  if (strlen (str) == 0 || (c != ' ' && c != '\t' && c != '('))
+	    {
+	      g_free (str);
+	      /* ignore line */
+	      c = eat_line (f, c);
+	      line++;
+	      continue;
+	    }
+	  define_line = g_string_new ("#define ");
+	  g_string_append (define_line, str);
+	  g_free (str);
+	  if (c == '(')
+	    {
+	      while (c != ')')
+		{
+		  g_string_append_c (define_line, c);
+		  c = fgetc (f);
+		  if (c == EOF || c == '\n')
+		    {
+		      error_line = TRUE;
+		      break;
+		    }
+		}
+	      if (error_line)
+		{
+		  g_string_free (define_line, TRUE);
+		  /* ignore line */
+		  c = eat_line (f, c);
+		  line++;
+		  continue;
+		}
+
+	      g_assert (c == ')');
+	      g_string_append_c (define_line, c);
+	      c = fgetc (f);
+
+	      /* found function-like macro */
+	      fprintf (fmacros, "%s\n", define_line->str);
+
+	      g_string_free (define_line, TRUE);
+	      /* ignore rest of line */
+	      c = eat_line (f, c);
+	      line++;
+	      continue;
+	    }
+	  if (c != ' ' && c != '\t')
+	    {
+	      g_string_free (define_line, TRUE);
+	      /* ignore line */
+	      c = eat_line (f, c);
+	      line++;
+	      continue;
+	    }
+	  while (c != EOF && c != '\n')
+	    {
+	      g_string_append_c (define_line, c);
+	      c = fgetc (f);
+	      if (c == '\\')
+		{
+		  c = fgetc (f);
+		  if (c == '\n')
+		    {
+		      /* fold lines when seeing backslash new-line sequence */
+		      c = fgetc (f);
+		    }
+		  else
+		    {
+		      g_string_append_c (define_line, '\\');
+		    }
+		}
+	    }
+
+	  /* found object-like macro */
+	  fprintf (fmacros, "%s\n", define_line->str);
+
+	  c = eat_line (f, c);
+	  line++;
+	}
+
+      fclose (f);
+    }
+
+  igenerator->macro_scan = TRUE;
+  rewind (fmacros);
+
+  g_igenerator_parse_file (igenerator, fmacros);
+  fclose (fmacros);
+
+  igenerator->macro_scan = FALSE;
+}
+
+static void
+g_igenerator_add_module (GIGenerator *igenerator,
+			 GIdlModule *module)
+{
+  GList *l;
+
+  for (l = module->entries; l; l = l->next)
+    {
+      GIdlNode *node = (GIdlNode*)l->data;
+      
+      if (node->type == G_IDL_NODE_OBJECT)
+	{
+	  GIdlNodeInterface *object = (GIdlNodeInterface*)node;
+	  gchar *name;
+	  if (strcmp(module->name, igenerator->namespace) == 0)
+	    name = g_strdup (node->name);
+	  else
+	    name = g_strdup_printf ("%s.%s", module->name, node->name);
+	  g_hash_table_insert (igenerator->symbols,
+			       g_strdup (object->gtype_name),
+			       name);
+	}
+    }
+}
+
+static void
+g_igenerator_add_include_idl (GIGenerator *igenerator,
+			      const gchar *filename)
+{
+  GList *l;
+  GList *modules;
+  
+  GError *error = NULL;
+
+  modules = g_idl_parse_file (filename, &error);
+  if (error)
+    {
+      g_printerr ("An error occured while parsing %s: %s\n",
+		  filename, error->message);
+      return;
+    }
+  
+  for (l = modules; l; l = l->next)
+    {
+      GIdlModule *module = (GIdlModule*)l->data;
+      g_igenerator_add_module (igenerator, module);
+    }
+}		     
+
+static FILE *
+g_igenerator_start_preprocessor (GIGenerator *igenerator,
+				 GList       *cpp_options)
+{
+  int cpp_out = -1, cpp_in = -1;
+  int cpp_argc = 0;
+  char **cpp_argv;
+  GList *l;
+  GError *error = NULL;
+  FILE *f, *out;
+  GPid pid;
+  int status = 0;
+  int read_bytes;
+  int i;
+  char **buffer;
+  int tmp;
+  char *tmpname;
+
+  cpp_argv = g_new0 (char *, g_list_length (cpp_options) + 4);
+  cpp_argv[cpp_argc++] = "cpp";
+  cpp_argv[cpp_argc++] = "-C";
+
+  /* Disable GCC extensions as we cannot parse them yet */
+  cpp_argv[cpp_argc++] = "-U__GNUC__";
+
+  for (l = cpp_options; l; l = l->next)
+    cpp_argv[cpp_argc++] = (char*)l->data;
+
+  cpp_argv[cpp_argc++] = NULL;
+
+  if (igenerator->verbose)
+    {
+      GString *args = g_string_new ("");
+      
+      for (i = 0; i < cpp_argc - 1; i++)
+	{
+	  g_string_append (args, cpp_argv[i]);
+	  if (i < cpp_argc - 2)
+	    g_string_append_c (args, ' ');
+	}
+
+      g_printf ("Executing '%s'\n", args->str);
+      g_string_free (args, FALSE);
+    }
+  g_spawn_async_with_pipes (NULL, cpp_argv, NULL,
+			    G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+			    NULL, NULL, &pid, &cpp_in, &cpp_out, NULL, &error);
+
+  g_free (cpp_argv);
+  if (error != NULL)
+    {
+      g_error ("%s", error->message);
+      return NULL;
+    }
+
+  f = fdopen (cpp_in, "w");
+
+  for (l = igenerator->filenames; l != NULL; l = l->next)
+    {
+      if (igenerator->verbose)
+	g_printf ("Pre-processing %s\n", (char*)l->data);
+
+      fprintf (f, "#include <%s>\n", (char *) l->data);
+
+    }
+
+  fclose (f);
+  close (cpp_in);
+
+  tmp = g_file_open_tmp (NULL, &tmpname, &error);
+  if (error != NULL)
+    {
+      g_error (error->message);
+      return NULL;
+    }
+
+  buffer = g_malloc0 (4096 * sizeof (char));
+
+  while (1)
+    {
+      read_bytes = read (cpp_out, buffer, 4096);
+      if (read_bytes == 0)
+	break;
+      write (tmp, buffer, read_bytes);
+    }
+
+  g_free (buffer);
+
+  close (cpp_out);
+
+  if (waitpid (pid, &status, 0) > 0)
+    {
+      if (status != 0)
+	{
+	  g_spawn_close_pid (pid);
+	  kill (pid, SIGKILL);
+
+	  g_error ("cpp returned error code: %d\n", status);
+	  unlink (tmpname);
+	  g_free (tmpname);
+	  return NULL;
+	}
+    }
+
+  f = fdopen (tmp, "r");
+  if (!f)
+    {
+      g_error (strerror (errno));
+      unlink (tmpname);
+      g_free (tmpname);
+      return NULL;
+    }
+  rewind (f);
+  unlink (tmpname);
+  g_free (tmpname);
+
+  return f;
+}
+
+
+void
+g_igenerator_set_verbose (GIGenerator *igenerator,
+			  gboolean     verbose)
+{
+  igenerator->verbose = verbose;
+}
+
+int
+main (int argc, char **argv)
+{
+  GOptionContext *ctx;
+  gchar *namespace = NULL;
+  gchar *shared_library = NULL;
+  gchar **include_idls = NULL;
+  gchar *output = NULL;
+  gboolean verbose = FALSE;
+
+  GIGenerator *igenerator;
+  int gopt_argc, i;
+  char **gopt_argv;
+  GList *filenames = NULL;
+  GError *error = NULL;
+  GList *l, *libraries = NULL;
+  GList *cpp_options = NULL;
+  char *buffer;
+  size_t size;
+  FILE *tmp;
+  GOptionEntry entries[] = 
+    {
+      { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose,
+	"Be verbose" },
+      { "output", 'o', 0, G_OPTION_ARG_STRING, &output,
+	"write output here instead of stdout", "FILE" },
+      { "namespace", 'n', 0, G_OPTION_ARG_STRING, &namespace,
+	"Namespace of the module, like 'Gtk'", "NAMESPACE" },
+      { "shared-library", 0, 0, G_OPTION_ARG_FILENAME, &shared_library,
+	"Shared library which contains the symbols", "FILE" }, 
+      { "include-idl", 0, 0, G_OPTION_ARG_STRING_ARRAY, &include_idls,
+	"Other gidls to include", "IDL" },
+      { NULL }
+    };
+
+  gopt_argc = 1;
+  gopt_argv = (char**)g_malloc (argc * sizeof (char*));
+  gopt_argv[0] = argv[0];
+
+  for (i = 1; i < argc; i++)
+    {
+      if (argv[i][0] == '-')
+	{
+	  switch (argv[i][1])
+	    {
+	    case 'I':
+	    case 'D':
+	    case 'U':
+	      cpp_options = g_list_prepend (cpp_options, g_strdup (argv[i]));
+	      break;
+	    default:
+	      gopt_argv[gopt_argc++] = argv[i];
+	      break;
+	    }
+	}
+      else if (g_str_has_suffix (argv[i], ".h"))
+	{
+	  gchar* filename;
+
+	  if (!g_path_is_absolute (argv[i]))
+	    {
+	      gchar *dir = g_get_current_dir ();
+	      filename = g_strdup_printf ("%s/%s", dir,
+					    argv[i]);
+	      g_free (dir);
+	    }
+	  else
+	    filename = g_strdup (argv[i]);
+		
+	  filenames = g_list_append (filenames, filename);
 	}
-
-	igenerator->macro_scan = TRUE;
-	rewind (fmacros);
-	g_igenerator_parse (igenerator, fmacros);
-	igenerator->macro_scan = FALSE;
+      else if (g_str_has_suffix (argv[i], ".la") ||
+	       g_str_has_suffix (argv[i], ".so") ||
+	       g_str_has_suffix (argv[i], ".dll"))
+	{
+	  libraries = g_list_prepend (libraries, g_strdup (argv[i]));
+	}
+      else
+	{
+	  gopt_argv[gopt_argc++] = argv[i];
+	}
+    }
+
+  ctx = g_option_context_new ("");
+  g_option_context_add_main_entries (ctx, entries, NULL);
+
+  if (!g_option_context_parse (ctx, &gopt_argc, &gopt_argv, &error))
+    {
+      g_printerr ("Parsing error: %s\n", error->message);
+      g_option_context_free (ctx);
+      return 1;
+    }
+
+  g_free (gopt_argv);
+  g_option_context_free (ctx);
+  
+  if (!namespace)
+    {
+      g_printerr ("ERROR: namespace must be specified\n");
+      return 1;
+    }
+
+  igenerator = g_igenerator_new (namespace, shared_library);
+
+  if (verbose)
+    g_igenerator_set_verbose (igenerator, TRUE);
+
+  if (!filenames)
+    {
+      g_printerr ("ERROR: Need at least one header file.\n");
+      g_igenerator_free (igenerator);  
+      return 0;
+    }
+  igenerator->filenames = filenames;
+  cpp_options = g_list_reverse (cpp_options);
+  libraries = g_list_reverse (libraries);
+
+  g_type_init ();
+
+  /* initialize threading as this may be required by libraries that we'll use
+   * libsoup-2.2 is an example of that.
+   */
+  g_thread_init (NULL);
+
+  if (include_idls)
+    {
+      for (i = 0; i < g_strv_length (include_idls); i++)
+	g_igenerator_add_include_idl (igenerator, include_idls[i]);
+    }
+
+  tmp = g_igenerator_start_preprocessor (igenerator, cpp_options);
+  if (!tmp)
+    {
+      g_error ("ERROR in pre-processor.\n");
+      g_igenerator_free (igenerator);  
+      return 1;
+    }
+
+  if (!g_igenerator_parse_file (igenerator, tmp))
+    {
+      fclose (tmp);
+      g_igenerator_free (igenerator);  
+      return 1;
+    }
+
+  g_igenerator_parse_macros (igenerator);
+
+  g_igenerator_generate (igenerator, output, libraries);
+
+  fclose (tmp);
+  g_igenerator_free (igenerator);
+  
+  return 0;
 }
 
-
-

Copied: trunk/gobject-introspection/scanner.h (from r809, /trunk/gobject-introspection/gen-introspect.h)
==============================================================================
--- /trunk/gobject-introspection/gen-introspect.h	(original)
+++ trunk/gobject-introspection/scanner.h	Fri Jan 11 21:44:01 2008
@@ -27,131 +27,141 @@
 #include <glib.h>
 #include "gidlmodule.h"
 
-G_BEGIN_DECLS
-
-typedef struct _GIGenerator GIGenerator;
+G_BEGIN_DECLS typedef struct _GIGenerator GIGenerator;
 typedef struct _CSymbol CSymbol;
 typedef struct _CType CType;
+typedef struct _CDirective CDirective;
 
-struct _GIGenerator {
-	const char *namespace;
-	char *lower_case_namespace;
-	/* specified files to be parsed */
-	GList *filenames;
-	GList *libraries;
-	/* source reference of current lexer position */
-	char *current_filename;
-	GList *symbol_list;
-	GHashTable *typedef_table;
-	GHashTable *struct_or_union_or_enum_table;
-
-	gboolean macro_scan;
-
-	GIdlModule *module;
-	GList *get_type_symbols;
-	GHashTable *type_map;
-	GHashTable *type_by_lower_case_prefix;
-
-	int indent;
+struct _GIGenerator
+{
+  /* parameters */
+  char *namespace;
+  char *shared_library;
+  char *lower_case_namespace;
+  gboolean verbose;
+
+  /* specified files to be parsed */
+  GList *filenames;
+  /* source reference of current lexer position */
+  char *current_filename;
+  GList *symbol_list;
+  GHashTable *typedef_table;
+  GHashTable *struct_or_union_or_enum_table;
+
+  GIdlModule *module;
+  GList *get_type_symbols;
+  GHashTable *type_map;
+  GHashTable *type_by_lower_case_prefix;
+
+  GHashTable *symbols; /* typename -> module.name */
+
+  /* scanner variables */
+  gboolean macro_scan;
+  GSList *directives; /* list of CDirective for the current symbol */
 };
 
-GIGenerator *g_igenerator_new (void);
-void g_igenerator_parse (GIGenerator *igenerator, FILE *f);
-void g_igenerator_add_symbol (GIGenerator *igenerator, CSymbol *symbol);
-gboolean g_igenerator_is_typedef (GIGenerator *igenerator, const char *name);
-void g_igenerator_generate (GIGenerator *igenerator);
-
-GIGenerator *the_igenerator;
-
-typedef enum {
-	CSYMBOL_TYPE_INVALID,
-	CSYMBOL_TYPE_CONST,
-	CSYMBOL_TYPE_OBJECT,
-	CSYMBOL_TYPE_FUNCTION,
-	CSYMBOL_TYPE_STRUCT,
-	CSYMBOL_TYPE_UNION,
-	CSYMBOL_TYPE_ENUM,
-	CSYMBOL_TYPE_TYPEDEF
+typedef enum
+{
+  CSYMBOL_TYPE_INVALID,
+  CSYMBOL_TYPE_CONST,
+  CSYMBOL_TYPE_OBJECT,
+  CSYMBOL_TYPE_FUNCTION,
+  CSYMBOL_TYPE_STRUCT,
+  CSYMBOL_TYPE_UNION,
+  CSYMBOL_TYPE_ENUM,
+  CSYMBOL_TYPE_TYPEDEF
 } CSymbolType;
 
-struct _CSymbol {
-	CSymbolType type;
-	int id;
-	char *ident;
-	CType *base_type;
-	gboolean const_int_set;
-	int const_int;
-	char *const_string;
+struct _CSymbol
+{
+  CSymbolType type;
+  int id;
+  char *ident;
+  CType *base_type;
+  gboolean const_int_set;
+  int const_int;
+  char *const_string;
+  GSList *directives; /* list of CDirective */
 };
 
-CSymbol *csymbol_new (CSymbolType type);
-gboolean csymbol_get_const_boolean (CSymbol *symbol);
-
-typedef enum {
-	CTYPE_INVALID,
-	CTYPE_VOID,
-	CTYPE_BASIC_TYPE,
-	CTYPE_TYPEDEF,
-	CTYPE_STRUCT,
-	CTYPE_UNION,
-	CTYPE_ENUM,
-	CTYPE_POINTER,
-	CTYPE_ARRAY,
-	CTYPE_FUNCTION
+typedef enum
+{
+  CTYPE_INVALID,
+  CTYPE_VOID,
+  CTYPE_BASIC_TYPE,
+  CTYPE_TYPEDEF,
+  CTYPE_STRUCT,
+  CTYPE_UNION,
+  CTYPE_ENUM,
+  CTYPE_POINTER,
+  CTYPE_ARRAY,
+  CTYPE_FUNCTION
 } CTypeType;
 
-typedef enum {
-	STORAGE_CLASS_NONE = 0,
-	STORAGE_CLASS_TYPEDEF = 1 << 1,
-	STORAGE_CLASS_EXTERN = 1 << 2,
-	STORAGE_CLASS_STATIC = 1 << 3,
-	STORAGE_CLASS_AUTO = 1 << 4,
-	STORAGE_CLASS_REGISTER = 1 << 5
+typedef enum
+{
+  STORAGE_CLASS_NONE = 0,
+  STORAGE_CLASS_TYPEDEF = 1 << 1,
+  STORAGE_CLASS_EXTERN = 1 << 2,
+  STORAGE_CLASS_STATIC = 1 << 3,
+  STORAGE_CLASS_AUTO = 1 << 4,
+  STORAGE_CLASS_REGISTER = 1 << 5
 } StorageClassSpecifier;
 
-typedef enum {
-	TYPE_QUALIFIER_NONE = 0,
-	TYPE_QUALIFIER_CONST = 1 << 1,
-	TYPE_QUALIFIER_RESTRICT = 1 << 2,
-	TYPE_QUALIFIER_VOLATILE = 1 << 3
+typedef enum
+{
+  TYPE_QUALIFIER_NONE = 0,
+  TYPE_QUALIFIER_CONST = 1 << 1,
+  TYPE_QUALIFIER_RESTRICT = 1 << 2,
+  TYPE_QUALIFIER_VOLATILE = 1 << 3
 } TypeQualifier;
 
-typedef enum {
-	FUNCTION_NONE = 0,
-	FUNCTION_INLINE = 1 << 1
+typedef enum
+{
+  FUNCTION_NONE = 0,
+  FUNCTION_INLINE = 1 << 1
 } FunctionSpecifier;
 
-typedef enum {
-	UNARY_ADDRESS_OF,
-	UNARY_POINTER_INDIRECTION,
-	UNARY_PLUS,
-	UNARY_MINUS,
-	UNARY_BITWISE_COMPLEMENT,
-	UNARY_LOGICAL_NEGATION
+typedef enum
+{
+  UNARY_ADDRESS_OF,
+  UNARY_POINTER_INDIRECTION,
+  UNARY_PLUS,
+  UNARY_MINUS,
+  UNARY_BITWISE_COMPLEMENT,
+  UNARY_LOGICAL_NEGATION
 } UnaryOperator;
 
-struct _CType {
-	CTypeType type;
-	StorageClassSpecifier storage_class_specifier;
-	TypeQualifier type_qualifier;
-	FunctionSpecifier function_specifier;
-	char *name;
-	CType *base_type;
-	GList *child_list;
+struct _CType
+{
+  CTypeType type;
+  StorageClassSpecifier storage_class_specifier;
+  TypeQualifier type_qualifier;
+  FunctionSpecifier function_specifier;
+  char *name;
+  CType *base_type;
+  GList *child_list;
 };
 
-CType *ctype_new (CTypeType type);
-CType *ctype_copy (CType *type);
-CType *cbasic_type_new (const char *name);
-CType *ctypedef_new (const char *name);
-CType *cstruct_new (const char *name);
-CType *cunion_new (const char *name);
-CType *cenum_new (const char *name);
-CType *cpointer_new (CType *base_type);
-CType *carray_new (void);
-CType *cfunction_new (void);
+struct _CDirective {
+  char *name;
+  char *value;
+};
 
+CSymbol *    csymbol_new               (CSymbolType  type);
+gboolean     csymbol_get_const_boolean (CSymbol     *symbol);
+void         csymbol_free              (CSymbol     *symbol);
+CDirective * cdirective_new            (const gchar *name,
+					const gchar *value);
+void         cdirective_free           (CDirective  *directive);
+
+gboolean g_igenerator_parse_file    (GIGenerator *igenerator,
+				     FILE        *file);
+void     g_igenerator_set_verbose   (GIGenerator *igenerator,
+				     gboolean     verbose);
+void     g_igenerator_add_symbol    (GIGenerator *igenerator,
+				     CSymbol     *symbol);
+gboolean g_igenerator_is_typedef    (GIGenerator *igenerator,
+				     const char  *name);
 G_END_DECLS
-
 #endif
-

Copied: trunk/gobject-introspection/scannerlexer.l (from r809, /trunk/gobject-introspection/clexer.l)
==============================================================================
--- /trunk/gobject-introspection/clexer.l	(original)
+++ trunk/gobject-introspection/scannerlexer.l	Fri Jan 11 21:44:01 2008
@@ -1,3 +1,4 @@
+/* -*- Mode: C -*-
 /* GObject introspection: C lexer
  *
  * Copyright (c) 1997 Sandro Sigala  <ssigala globalnet it>
@@ -30,36 +31,38 @@
 #include <ctype.h>
 #include <stdio.h>
 
-#include "gen-introspect.h"
-#include "cparser.h"
+#include "scanner.h"
+#include "scannerparser.h"
 
 int lineno;
 
+extern int yylex (GIGenerator *igenerator);
+#define YY_DECL int yylex (GIGenerator *igenerator)
 static int yywrap (void);
-static void skip_comment (void);
-static void process_directive (void);
-static int check_identifier (const char *);
+static void parse_comment (GIGenerator *igenerator);
+static void process_directive (GIGenerator *igenerator);
+static int check_identifier (GIGenerator *igenerator, const char *);
 %}
 
 intsuffix				([uU][lL]?)|([lL][uU]?)
 fracconst				([0-9]*\.[0-9]+)|([0-9]+\.)
 exppart					[eE][-+]?[0-9]+
 floatsuffix				[fFlL]
-chartext				([^'])|(\\.)
-stringtext				([^"])|(\\.)
+chartext				([^\'])|(\\.) 
+stringtext				([^\"])|(\\.)
 
 %%
 
-"\n"					{ ++lineno; }
+"\n"					{ ++lineno; } /* " */
 [\t\f\v\r ]+				{ /* Ignore whitespace. */ }
 
-"/*"					{ skip_comment(); }
+"/*"					{ parse_comment(igenerator); }
 "//".*					{ }
 
 "#define "[a-zA-Z_][a-zA-Z_0-9]*"("	{ yyless (yyleng - 1); return FUNCTION_MACRO; }
 "#define "[a-zA-Z_][a-zA-Z_0-9]*	{ return OBJECT_MACRO; }
 
-"#"					{ process_directive(); }
+"#"					{ process_directive(igenerator); }
 
 "{"					{ return '{'; }
 "<%"					{ return '{'; }
@@ -112,7 +115,7 @@
 ","					{ return ','; }
 "->"					{ return ARROW; }
 
-[a-zA-Z_][a-zA-Z_0-9]*			{ if (the_igenerator->macro_scan) return IDENTIFIER; else REJECT; }
+[a-zA-Z_][a-zA-Z_0-9]*			{ if (igenerator->macro_scan) return IDENTIFIER; else REJECT; }
 
 "auto"					{ return AUTO; }
 "break"					{ return BREAK; }
@@ -149,7 +152,7 @@
 "volatile"				{ return VOLATILE; }
 "while"					{ return WHILE; }
 
-[a-zA-Z_][a-zA-Z_0-9]*			{ return check_identifier(yytext); }
+[a-zA-Z_][a-zA-Z_0-9]*			{ return check_identifier(igenerator, yytext); }
 
 "0"[xX][0-9a-fA-F]+{intsuffix}?		{ return INTEGER; }
 "0"[0-7]+{intsuffix}?			{ return INTEGER; }
@@ -164,38 +167,95 @@
 "\""{stringtext}*"\""			{ return STRING; }
 "L\""{stringtext}*"\""			{ return STRING; }
 
-.					{ fprintf(stderr, "%s:%d: unexpected character `%c'\n", the_igenerator->current_filename, lineno, yytext[0]); }
+.					{ fprintf(stderr, "%s:%d: unexpected character `%c'\n", igenerator->current_filename, lineno, yytext[0]); }
 
 %%
 
 static int yywrap (void)
 {
-	return 1;
+  return 1;
 }
 
-static void skip_comment (void)
+static void parse_gtkdoc (GIGenerator *igenerator, int *c1, int *c2)
 {
-	int c1, c2;
+  gboolean isline = FALSE;
+  gchar line[256];
+  int i;
+  gchar **parts;
+  CDirective *directive;
+  char *name, *value;
+
+  i = 0;
+  do {
+      *c1 = *c2;
+      if (*c1 == '\n')
+	{
+	  isline = TRUE;
+	  break;
+	}
+      if (i >= 256)
+	break;
+      line[i++] = *c1;
+      *c2 = input();
+
+  } while (*c2 != EOF && !(*c1 == '*' && *c2 == '/'));
+  
+  if (!isline)
+    return;
+
+  line[i] = '\0';
+
+  parts = g_strsplit (line, ": ", 2);
+
+  if (g_strv_length (parts) == 2)
+    {
+      name = parts[0];
+      value = parts[1];
+    }
+  else /* parts == 1 */
+    {
+      name = parts[0];
+      value = "1";
+    }
+  
+  directive = cdirective_new (name, value);
+  igenerator->directives = g_slist_prepend (igenerator->directives,
+					    directive);
 
-	c1 = input();
-	c2 = input();
+  g_strfreev (parts);
+}
 
-	while (c2 != EOF && !(c1 == '*' && c2 == '/')) {
-		if (c1 == '\n')
-			++lineno;
-		c1 = c2;
-		c2 = input();
+static void parse_comment (GIGenerator *igenerator)
+{
+  int c1, c2;
+  
+  c1 = input();
+  c2 = input();
+
+  while (c2 != EOF && !(c1 == '*' && c2 == '/'))
+    {
+      if (c1 == '\n')
+	++lineno;
+      c1 = c2;
+      c2 = input();
+
+      if (c1 == ' ' && c2 == '@')
+	{
+	  c1 = c2;
+	  c2 = input();
+	  parse_gtkdoc (igenerator, &c1, &c2);
 	}
+    }
 }
 
-static int check_identifier (const char *s)
+static int check_identifier (GIGenerator *igenerator, const char *s)
 {
 	/*
 	 * This function checks if `s' is a type name or an
 	 * identifier.
 	 */
 
-	if (g_igenerator_is_typedef (the_igenerator, s)) {
+	if (g_igenerator_is_typedef (igenerator, s)) {
 		return TYPEDEF_NAME;
 	} else if (strcmp (s, "__builtin_va_list") == 0) {
 		return TYPEDEF_NAME;
@@ -204,7 +264,7 @@
 	return IDENTIFIER;
 }
 
-static void process_directive (void)
+static void process_directive (GIGenerator *igenerator)
 {
 	/* extract current filename from #line directives */
 	GString *filename_builder;
@@ -242,8 +302,8 @@
 
 	if (filename_builder->len > 0) {
 		char *filename = g_strcompress (filename_builder->str);
-		g_free (the_igenerator->current_filename);
-		the_igenerator->current_filename = filename;
+		g_free (igenerator->current_filename);
+		igenerator->current_filename = filename;
 	}
 
 	g_string_free (filename_builder, TRUE);

Copied: trunk/gobject-introspection/scannerparser.y (from r809, /trunk/gobject-introspection/cparser.y)
==============================================================================
--- /trunk/gobject-introspection/cparser.y	(original)
+++ trunk/gobject-introspection/scannerparser.y	Fri Jan 11 21:44:01 2008
@@ -30,41 +30,177 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include "gen-introspect.h"
+#include <errno.h>
+#include "scanner.h"
 
 extern FILE *yyin;
 extern int lineno;
 extern char *yytext;
 
-extern int yylex (void);
-static void yyerror(const char *s);
-
+extern int yylex (GIGenerator *igenerator);
+static void yyerror(GIGenerator *igenerator, const char *s);
+ 
 static int last_enum_value = -1;
 static GHashTable *const_table = NULL;
 
+CSymbol *
+csymbol_new (CSymbolType type)
+{
+  CSymbol *s = g_new0 (CSymbol, 1);
+  s->type = type;
+  return s;
+}
+
+static void
+ctype_free (CType * type)
+{
+  g_free (type);
+  g_free (type->name);
+  g_list_foreach (type->child_list, (GFunc)ctype_free, NULL);
+  g_list_free (type->child_list);
+}
+
+void
+csymbol_free (CSymbol * symbol)
+{
+  g_free (symbol->ident);
+  ctype_free (symbol->base_type);
+  g_free (symbol->const_string);
+  g_free (symbol);
+  g_slist_foreach (symbol->directives, (GFunc)cdirective_free, NULL);
+  g_slist_free (symbol->directives);
+}
+ 
+gboolean
+csymbol_get_const_boolean (CSymbol * symbol)
+{
+  return (symbol->const_int_set && symbol->const_int) || symbol->const_string;
+}
+
+CType *
+ctype_new (CTypeType type)
+{
+  CType *t = g_new0 (CType, 1);
+  t->type = type;
+  return t;
+}
+
+CType *
+ctype_copy (CType * type)
+{
+  return g_memdup (type, sizeof (CType));
+}
+
+CType *
+cbasic_type_new (const char *name)
+{
+  CType *basic_type = ctype_new (CTYPE_BASIC_TYPE);
+  basic_type->name = g_strdup (name);
+  return basic_type;
+}
+
+CType *
+ctypedef_new (const char *name)
+{
+  CType *typedef_ = ctype_new (CTYPE_TYPEDEF);
+  typedef_->name = g_strdup (name);
+  return typedef_;
+}
+
+CType *
+cstruct_new (const char *name)
+{
+  CType *struct_ = ctype_new (CTYPE_STRUCT);
+  struct_->name = g_strdup (name);
+  return struct_;
+}
+
+CType *
+cunion_new (const char *name)
+{
+  CType *union_ = ctype_new (CTYPE_UNION);
+  union_->name = g_strdup (name);
+  return union_;
+}
+
+CType *
+cenum_new (const char *name)
+{
+  CType *enum_ = ctype_new (CTYPE_ENUM);
+  enum_->name = g_strdup (name);
+  return enum_;
+}
+
+CType *
+cpointer_new (CType * base_type)
+{
+  CType *pointer = ctype_new (CTYPE_POINTER);
+  pointer->base_type = ctype_copy (base_type);
+  return pointer;
+}
+
+CType *
+carray_new (void)
+{
+  CType *array = ctype_new (CTYPE_ARRAY);
+  return array;
+}
+
+CType *
+cfunction_new (void)
+{
+  CType *func = ctype_new (CTYPE_FUNCTION);
+  return func;
+}
+
 /* use specified type as base type of symbol */
-static void csymbol_merge_type (CSymbol *symbol, CType *type)
+static void
+csymbol_merge_type (CSymbol *symbol, CType *type)
+{
+  CType **foundation_type = &(symbol->base_type);
+  while (*foundation_type != NULL) {
+    foundation_type = &((*foundation_type)->base_type);
+  }
+  *foundation_type = ctype_copy (type);
+}
+
+CDirective *
+cdirective_new (const gchar *name,
+		const gchar *value)
+{
+  CDirective *directive;
+    
+  directive = g_slice_new (CDirective);
+  directive->name = g_strdup (name);
+  directive->value = g_strdup (value);
+  return directive;
+}
+
+void
+cdirective_free (CDirective *directive)
 {
-	CType **foundation_type = &(symbol->base_type);
-	while (*foundation_type != NULL) {
-		foundation_type = &((*foundation_type)->base_type);
-	}
-	*foundation_type = ctype_copy (type);
+  g_free (directive->name);
+  g_free (directive->value);
+  g_slice_free (CDirective, directive);
 }
+
 %}
 
 %error-verbose
 %union {
-	char *str;
-	GList *list;
-	CSymbol *symbol;
-	CType *ctype;
-	StorageClassSpecifier storage_class_specifier;
-	TypeQualifier type_qualifier;
-	FunctionSpecifier function_specifier;
-	UnaryOperator unary_operator;
+  char *str;
+  GList *list;
+  CSymbol *symbol;
+  CType *ctype;
+  StorageClassSpecifier storage_class_specifier;
+  TypeQualifier type_qualifier;
+  FunctionSpecifier function_specifier;
+  UnaryOperator unary_operator;
 }
 
+%parse-param { GIGenerator* igenerator }
+%lex-param { GIGenerator* igenerator }
+
 %token <str> IDENTIFIER "identifier"
 %token <str> TYPEDEF_NAME "typedef-name"
 
@@ -530,7 +666,7 @@
 			} else {
 				sym->type = CSYMBOL_TYPE_OBJECT;
 			}
-			g_igenerator_add_symbol (the_igenerator, sym);
+			g_igenerator_add_symbol (igenerator, sym);
 		}
 	  }
 	| declaration_specifiers ';'
@@ -676,7 +812,7 @@
 		}
 		sym->ident = g_strdup ($$->name);
 		sym->base_type = ctype_copy ($$);
-		g_igenerator_add_symbol (the_igenerator, sym);
+		g_igenerator_add_symbol (igenerator, sym);
 	  }
 	| struct_or_union '{' struct_declaration_list '}'
 	  {
@@ -817,7 +953,7 @@
 		$$->ident = $1;
 		$$->const_int_set = TRUE;
 		$$->const_int = ++last_enum_value;
-		g_hash_table_insert (const_table, $$->ident, $$);
+		g_hash_table_insert (const_table, g_strdup ($$->ident), $$);
 	  }
 	| identifier '=' constant_expression
 	  {
@@ -826,7 +962,7 @@
 		$$->const_int_set = TRUE;
 		$$->const_int = $3->const_int;
 		last_enum_value = $$->const_int;
-		g_hash_table_insert (const_table, $$->ident, $$);
+		g_hash_table_insert (const_table, g_strdup ($$->ident), $$);
 	  }
 	;
 
@@ -1192,7 +1328,7 @@
 	  {
 		if ($2->const_int_set || $2->const_string != NULL) {
 			$2->ident = $1;
-			g_igenerator_add_symbol (the_igenerator, $2);
+			g_igenerator_add_symbol (igenerator, $2);
 		}
 	  }
 	;
@@ -1206,31 +1342,35 @@
 %%
 
 static void
-yyerror(const char *s)
+yyerror (GIGenerator *igenerator, const char *s)
 {
-	/* ignore errors while doing a macro scan as not all object macros
-	 * have valid expressions */
-	if (!the_igenerator->macro_scan) {
-		fprintf(stderr, "%s:%d: %s\n", the_igenerator->current_filename, lineno, s);
-	}
+  /* ignore errors while doing a macro scan as not all object macros
+   * have valid expressions */
+  if (!igenerator->macro_scan)
+    {
+      fprintf(stderr, "%s:%d: %s\n",
+	      igenerator->current_filename, lineno, s);
+    }
 }
 
-void g_igenerator_parse (GIGenerator *igenerator, FILE *f)
+gboolean
+g_igenerator_parse_file (GIGenerator *igenerator, FILE *file)
 {
-	yyin = f;
-	if (yyin == NULL) {
-		return;
-	}
-
-	const_table = g_hash_table_new (g_str_hash, g_str_equal);
+  g_return_val_if_fail (file != NULL, FALSE);
+  
+  const_table = g_hash_table_new_full (g_str_hash, g_str_equal,
+				       g_free, NULL);
+  
+  lineno = 1;
+  yyin = file;
+  yyparse (igenerator);
+  
+  g_hash_table_destroy (const_table);
+  const_table = NULL;
+  
+  yyin = NULL;
 
-	lineno = 1;
-	yyparse();
-
-	g_hash_table_unref (const_table);
-	const_table = NULL;
-
-	fclose (yyin);
-	yyin = NULL;
+  return TRUE;
 }
 
+

Modified: trunk/vapigen/vala-gen-introspect/vala-gen-introspect.in
==============================================================================
--- trunk/vapigen/vala-gen-introspect/vala-gen-introspect.in	(original)
+++ trunk/vapigen/vala-gen-introspect/vala-gen-introspect.in	Fri Jan 11 21:44:01 2008
@@ -29,5 +29,5 @@
 	PKGDEFINES=$(cat $PKGBASE.defines)
 fi
 
-$pkglibdir/gen-introspect --namespace=`cat $PKGBASE.namespace` -U__GNUC__ $PKGDEFINES `pkg-config --cflags $PKGNAME` $FILES > $PKGBASE.gi
+$pkglibdir/gen-introspect --namespace=`cat $PKGBASE.namespace` $PKGDEFINES `pkg-config --cflags $PKGNAME | sed 's/-pthread//g'` $FILES > $PKGBASE.gi
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]