update from gobject-introspection SVN, fixes bug 505920
authorJuerg Billeter <j@bitron.ch>
Fri, 11 Jan 2008 21:44:01 +0000 (21:44 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Fri, 11 Jan 2008 21:44:01 +0000 (21:44 +0000)
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

svn path=/trunk/; revision=829

17 files changed:
ChangeLog
gobject-introspection/Makefile.am
gobject-introspection/gen-introspect.c [deleted file]
gobject-introspection/gen-introspect.h [deleted file]
gobject-introspection/gidlmodule.c
gobject-introspection/gidlmodule.h
gobject-introspection/gidlparser.c
gobject-introspection/gidlwriter.c [new file with mode: 0644]
gobject-introspection/gidlwriter.h [new file with mode: 0644]
gobject-introspection/girepository.h [new file with mode: 0644]
gobject-introspection/gmetadata.c [new file with mode: 0644]
gobject-introspection/gmetadata.h
gobject-introspection/scanner.c [new file with mode: 0644]
gobject-introspection/scanner.h [new file with mode: 0644]
gobject-introspection/scannerlexer.l [moved from gobject-introspection/clexer.l with 72% similarity]
gobject-introspection/scannerparser.y [moved from gobject-introspection/cparser.y with 86% similarity]
vapigen/vala-gen-introspect/vala-gen-introspect.in

index 408cfdb..52cdf82 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2008-01-11  Jürg 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
+
 2008-01-10  Jürg Billeter  <j@bitron.ch>
 
        * vapi/packages/gnome-desktop-2.0/: update to gnome-desktop 2.21.4
index 47e771f..4ec0275 100644 (file)
@@ -15,24 +15,29 @@ libgidl_la_SOURCES = \
        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 = \
diff --git a/gobject-introspection/gen-introspect.c b/gobject-introspection/gen-introspect.c
deleted file mode 100644 (file)
index edd64ab..0000000
+++ /dev/null
@@ -1,1372 +0,0 @@
-/* GObject introspection: gen-introspect
- *
- * Copyright (C) 2007  Jürg Billeter
- *
- * 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 <string.h>
-#include <ctype.h>
-#include <glib.h>
-#include <glib/gstdio.h>
-#include <glib-object.h>
-#include <gmodule.h>
-#include "gen-introspect.h"
-#include "gidlmodule.h"
-#include "gidlnode.h"
-
-typedef GType (*TypeFunction) (void);
-
-static void node_generate (GIGenerator *igenerator, GIdlNode *node);
-static void g_igenerator_parse_macros (GIGenerator *igenerator);
-
-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);
-                               }
-                       }
-               }
-       } 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);
-       }
-
-       igenerator->macro_scan = TRUE;
-       rewind (fmacros);
-       g_igenerator_parse (igenerator, fmacros);
-       igenerator->macro_scan = FALSE;
-}
-
-
-
diff --git a/gobject-introspection/gen-introspect.h b/gobject-introspection/gen-introspect.h
deleted file mode 100644 (file)
index 91d4ab0..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/* GObject introspection: gen-introspect
- *
- * Copyright (C) 2007  Jürg Billeter
- *
- * 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>
- */
-
-#ifndef __GEN_INTROSPECT_H__
-#define __GEN_INTROSPECT_H__
-
-#include <glib.h>
-#include "gidlmodule.h"
-
-G_BEGIN_DECLS
-
-typedef struct _GIGenerator GIGenerator;
-typedef struct _CSymbol CSymbol;
-typedef struct _CType CType;
-
-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;
-};
-
-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
-} CSymbolType;
-
-struct _CSymbol {
-       CSymbolType type;
-       int id;
-       char *ident;
-       CType *base_type;
-       gboolean const_int_set;
-       int const_int;
-       char *const_string;
-};
-
-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
-} 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
-} StorageClassSpecifier;
-
-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
-} FunctionSpecifier;
-
-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;
-};
-
-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);
-
-G_END_DECLS
-
-#endif
-
index 2d4929e..d17a249 100644 (file)
 
 #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_idl_module_free (GIdlModule *module)
   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 @@ g_idl_module_build_metadata (GIdlModule  *module,
   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_idl_module_build_metadata (GIdlModule  *module,
   
   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);
 }
 
index 1713576..3564a75 100644 (file)
@@ -22,6 +22,7 @@
 #define __G_IDL_MODULE_H__
 
 #include <glib.h>
+#include "gmetadata.h"
 
 G_BEGIN_DECLS
 
@@ -31,16 +32,16 @@ typedef struct _GIdlModule GIdlModule;
 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
 
index 1508617..3d52926 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <stdlib.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include <glib.h>
 #include "gidlmodule.h"
@@ -92,6 +93,11 @@ parse_type_internal (gchar *str, gchar **rest)
     { "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 @@ start_element_handler (GMarkupParseContext *context,
     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 @@ end_element_handler (GMarkupParseContext *context,
 
     case STATE_NAMESPACE:
       if (strcmp (element_name, "namespace") == 0)
-        {
+       {
           ctx->current_module = NULL;
           ctx->state = STATE_ROOT;
         }
diff --git a/gobject-introspection/gidlwriter.c b/gobject-introspection/gidlwriter.c
new file mode 100644 (file)
index 0000000..d46762b
--- /dev/null
@@ -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);
+}
diff --git a/gobject-introspection/gidlwriter.h b/gobject-introspection/gidlwriter.h
new file mode 100644 (file)
index 0000000..5d41a0c
--- /dev/null
@@ -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__ */
diff --git a/gobject-introspection/girepository.h b/gobject-introspection/girepository.h
new file mode 100644 (file)
index 0000000..7ad1067
--- /dev/null
@@ -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__ */
+
diff --git a/gobject-introspection/gmetadata.c b/gobject-introspection/gmetadata.c
new file mode 100644 (file)
index 0000000..b680390
--- /dev/null
@@ -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);
+}
index 7ca390c..a22ee23 100644 (file)
@@ -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 @@ typedef struct
 
   guint32 size;
   guint32 namespace;
+  guint32 shared_library;
 
   guint16 entry_blob_size;
   guint16 function_blob_size;
@@ -77,7 +81,7 @@ typedef struct
   guint16 interface_blob_size;
   guint16 union_blob_size;
   
-  guint16 padding;
+  guint16 padding[7];
 } Header;
 
 typedef struct
@@ -506,13 +510,20 @@ typedef struct
 } 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 @@ typedef enum
 
 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
diff --git a/gobject-introspection/scanner.c b/gobject-introspection/scanner.c
new file mode 100644 (file)
index 0000000..5888579
--- /dev/null
@@ -0,0 +1,1824 @@
+/* GObject introspection: scanner
+ *
+ * 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
+ * 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 <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 "scanner.h"
+#include "gidlparser.h"
+#include "gidlmodule.h"
+#include "gidlnode.h"
+#include "gidlwriter.h"
+
+typedef GType (*TypeFunction) (void);
+
+static void g_igenerator_parse_macros (GIGenerator * igenerator);
+
+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);
+    }
+}
+
+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;
+                   }
+               }
+             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);
+       }
+      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;
+}
+
diff --git a/gobject-introspection/scanner.h b/gobject-introspection/scanner.h
new file mode 100644 (file)
index 0000000..b214075
--- /dev/null
@@ -0,0 +1,167 @@
+/* GObject introspection: gen-introspect
+ *
+ * Copyright (C) 2007  Jürg Billeter
+ *
+ * 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>
+ */
+
+#ifndef __GEN_INTROSPECT_H__
+#define __GEN_INTROSPECT_H__
+
+#include <glib.h>
+#include "gidlmodule.h"
+
+G_BEGIN_DECLS typedef struct _GIGenerator GIGenerator;
+typedef struct _CSymbol CSymbol;
+typedef struct _CType CType;
+typedef struct _CDirective CDirective;
+
+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 */
+};
+
+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;
+  GSList *directives; /* list of CDirective */
+};
+
+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
+} StorageClassSpecifier;
+
+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
+} FunctionSpecifier;
+
+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 _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
similarity index 72%
rename from gobject-introspection/clexer.l
rename to gobject-introspection/scannerlexer.l
index b0c9cd6..255f7dc 100644 (file)
@@ -1,3 +1,4 @@
+/* -*- Mode: C -*-
 /* GObject introspection: C lexer
  *
  * Copyright (c) 1997 Sandro Sigala  <ssigala@globalnet.it>
 #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 @@ stringtext                          ([^"])|(\\.)
 ","                                    { 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 @@ stringtext                          ([^"])|(\\.)
 "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                                ([^"])|(\\.)
 "\""{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;
-
-       c1 = input();
-       c2 = input();
+  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);
+
+  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 @@ static int check_identifier (const char *s)
        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 @@ static void process_directive (void)
 
        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);
similarity index 86%
rename from gobject-introspection/cparser.y
rename to gobject-introspection/scannerparser.y
index c29ca8f..fae5067 100644 (file)
 #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 @@ declaration
                        } 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 @@ struct_or_union_specifier
                }
                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 @@ enumerator
                $$->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 @@ enumerator
                $$->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 @@ object_macro_define
          {
                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 @@ macro
 %%
 
 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);
-
-       lineno = 1;
-       yyparse();
-
-       g_hash_table_unref (const_table);
-       const_table = NULL;
-
-       fclose (yyin);
-       yyin = NULL;
+  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;
+
+  return TRUE;
 }
 
+
index c461293..d8c829b 100755 (executable)
@@ -29,5 +29,5 @@ then
        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