[gobject-introspection] [girwriter] Refactor out of generate.c



commit 0c550391b29da17446e22cebb1ccbacf8561983d
Author: Johan Dahlin <johan gnome org>
Date:   Mon Jun 7 10:52:43 2010 -0300

    [girwriter] Refactor out of generate.c
    
    Move out the girwriter out of generate.c. Still a private API,
    but that will probably change in the future.

 girepository/Makefile.am |    4 +-
 girepository/girwriter.c | 1402 ++++++++++++++++++++++++++++++++++++++++++++++
 girepository/girwriter.h |   11 +-
 tools/Makefile.am        |    1 +
 tools/generate.c         | 1369 +--------------------------------------------
 5 files changed, 1418 insertions(+), 1369 deletions(-)
---
diff --git a/girepository/Makefile.am b/girepository/Makefile.am
index f85b5be..f76e6c3 100644
--- a/girepository/Makefile.am
+++ b/girepository/Makefile.am
@@ -64,6 +64,8 @@ libgirepository_parser_la_SOURCES =		\
 	girnode.h				\
 	giroffsets.c				\
 	girparser.c				\
-	girparser.h
+	girparser.h				\
+	girwriter.c				\
+	girwriter.h
 libgirepository_parser_la_CFLAGS = $(GIREPO_CFLAGS)
 
diff --git a/girepository/girwriter.c b/girepository/girwriter.c
new file mode 100644
index 0000000..6fa892d
--- /dev/null
+++ b/girepository/girwriter.c
@@ -0,0 +1,1402 @@
+
+/* -*- Mode: C; c-file-style: "gnu"; -*- */
+/* GObject introspection: IDL generator
+ *
+ * Copyright (C) 2005 Matthias Clasen
+ * Copyright (C) 2008,2009 Red Hat, Inc.
+ *
+ * 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 <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gstdio.h>
+
+#include "girwriter.h"
+#include "girepository.h"
+#include "gitypelib-internal.h"
+
+typedef struct {
+  FILE *file;
+  GSList *stack;
+  gboolean show_all;
+} Xml;
+
+typedef struct {
+  char *name;
+  guint has_children : 1;
+} XmlElement;
+
+static XmlElement *
+xml_element_new (const char *name)
+{
+  XmlElement *elem;
+
+  elem = g_new (XmlElement, 1);
+  elem->name = g_strdup (name);
+  elem->has_children = FALSE;
+  return elem;
+}
+
+static void
+xml_element_free (XmlElement *elem)
+{
+  g_free (elem->name);
+  g_free (elem);
+}
+
+static void
+xml_printf (Xml *xml, const char *fmt, ...)
+{
+  va_list ap;
+  char *s;
+
+  va_start (ap, fmt);
+  s = g_markup_vprintf_escaped (fmt, ap);
+  fputs (s, xml->file);
+  g_free (s);
+  va_end (ap);
+}
+
+static void
+xml_start_element (Xml *xml, const char *element_name)
+{
+  XmlElement *parent = NULL;
+
+  if (xml->stack)
+    {
+      parent = xml->stack->data;
+
+      if (!parent->has_children)
+        xml_printf (xml, ">\n");
+
+      parent->has_children = TRUE;
+    }
+
+  xml_printf (xml, "%*s<%s", g_slist_length(xml->stack)*2, "", element_name);
+
+  xml->stack = g_slist_prepend (xml->stack, xml_element_new (element_name));
+}
+
+static void
+xml_end_element (Xml *xml, const char *name)
+{
+  XmlElement *elem;
+
+  g_assert (xml->stack != NULL);
+
+  elem = xml->stack->data;
+  xml->stack = g_slist_delete_link (xml->stack, xml->stack);
+
+  if (name != NULL)
+    g_assert_cmpstr (name, ==, elem->name);
+
+  if (elem->has_children)
+    xml_printf (xml, "%*s</%s>\n", g_slist_length (xml->stack)*2, "", elem->name);
+  else
+    xml_printf (xml, "/>\n");
+
+  xml_element_free (elem);
+}
+
+static void
+xml_end_element_unchecked (Xml *xml)
+{
+  xml_end_element (xml, NULL);
+}
+
+static Xml *
+xml_open (FILE *file)
+{
+  Xml *xml;
+
+  xml = g_new (Xml, 1);
+  xml->file = file;
+  xml->stack = NULL;
+
+  return xml;
+}
+
+static void
+xml_close (Xml *xml)
+{
+  g_assert (xml->stack == NULL);
+  if (xml->file != NULL)
+    {
+      fflush (xml->file);
+      if (xml->file != stdout)
+        fclose (xml->file);
+      xml->file = NULL;
+    }
+}
+
+static void
+xml_free (Xml *xml)
+{
+  xml_close (xml);
+  g_free (xml);
+}
+
+
+static void
+check_unresolved (GIBaseInfo *info)
+{
+  if (g_base_info_get_type (info) != GI_INFO_TYPE_UNRESOLVED)
+    return;
+
+  g_critical ("Found unresolved type '%s' '%s'\n",
+	      g_base_info_get_name (info), g_base_info_get_namespace (info));
+}
+
+static void
+write_type_name (const gchar *namespace,
+		 GIBaseInfo  *info,
+		 Xml         *file)
+{
+  if (strcmp (namespace, g_base_info_get_namespace (info)) != 0)
+    xml_printf (file, "%s.", g_base_info_get_namespace (info));
+
+  xml_printf (file, "%s", g_base_info_get_name (info));
+}
+
+static void
+write_type_name_attribute (const gchar *namespace,
+			   GIBaseInfo  *info,
+			   const char  *attr_name,
+			   Xml         *file)
+{
+  xml_printf (file, " %s=\"", attr_name);
+  write_type_name (namespace, info, file);
+  xml_printf (file, "\"");
+}
+
+static void
+write_type_info (const gchar *namespace,
+		 GITypeInfo  *info,
+		 Xml         *file)
+{
+  gint tag;
+  gint i;
+  GITypeInfo *type;
+  gboolean is_pointer;
+
+  check_unresolved ((GIBaseInfo*)info);
+
+  tag = g_type_info_get_tag (info);
+  is_pointer = g_type_info_is_pointer (info);
+
+  if (tag == GI_TYPE_TAG_VOID)
+    {
+      xml_start_element (file, "type");
+
+      xml_printf (file, " name=\"%s\"", is_pointer ? "any" : "none");
+
+      xml_end_element (file, "type");
+    }
+  else if (G_TYPE_TAG_IS_BASIC (tag))
+    {
+      xml_start_element (file, "type");
+      xml_printf (file, " name=\"%s\"", g_type_tag_to_string (tag));
+      xml_end_element (file, "type");
+    }
+  else if (tag == GI_TYPE_TAG_ARRAY)
+    {
+      gint length, size;
+      char *name = NULL;
+
+      xml_start_element (file, "array");
+
+      switch (g_type_info_get_array_type (info)) {
+        case GI_ARRAY_TYPE_C:
+            break;
+        case GI_ARRAY_TYPE_ARRAY:
+            name = "GLib.Array";
+            break;
+        case GI_ARRAY_TYPE_PTR_ARRAY:
+            name = "GLib.PtrArray";
+            break;
+        case GI_ARRAY_TYPE_BYTE_ARRAY:
+            name = "GLib.ByteArray";
+            break;
+        default:
+            break;
+      }
+
+      if (name)
+        xml_printf (file, " name=\"%s\"", name);
+
+      type = g_type_info_get_param_type (info, 0);
+
+      length = g_type_info_get_array_length (info);
+      if (length >= 0)
+        xml_printf (file, " length=\"%d\"", length);
+
+      size = g_type_info_get_array_fixed_size (info);
+      if (size >= 0)
+        xml_printf (file, " fixed-size=\"%d\"", size);
+
+      if (g_type_info_is_zero_terminated (info))
+	xml_printf (file, " zero-terminated=\"1\"");
+
+      write_type_info (namespace, type, file);
+
+      g_base_info_unref ((GIBaseInfo *)type);
+
+      xml_end_element (file, "array");
+    }
+  else if (tag == GI_TYPE_TAG_INTERFACE)
+    {
+      GIBaseInfo *iface = g_type_info_get_interface (info);
+      xml_start_element (file, "type");
+      write_type_name_attribute (namespace, iface, "name", file);
+      xml_end_element (file, "type");
+      g_base_info_unref (iface);
+    }
+  else if (tag == GI_TYPE_TAG_GLIST)
+    {
+      xml_start_element (file, "type");
+      xml_printf (file, " name=\"GLib.List\"");
+      type = g_type_info_get_param_type (info, 0);
+      if (type)
+	{
+	  write_type_info (namespace, type, file);
+	  g_base_info_unref ((GIBaseInfo *)type);
+	}
+      xml_end_element (file, "type");
+    }
+  else if (tag == GI_TYPE_TAG_GSLIST)
+    {
+      xml_start_element (file, "type");
+      xml_printf (file, " name=\"GLib.SList\"");
+      type = g_type_info_get_param_type (info, 0);
+      if (type)
+	{
+	  write_type_info (namespace, type, file);
+	  g_base_info_unref ((GIBaseInfo *)type);
+	}
+      xml_end_element (file, "type");
+    }
+  else if (tag == GI_TYPE_TAG_GHASH)
+    {
+      xml_start_element (file, "type");
+      xml_printf (file, " name=\"GLib.HashTable\"");
+      type = g_type_info_get_param_type (info, 0);
+      if (type)
+	{
+	  write_type_info (namespace, type, file);
+	  g_base_info_unref ((GIBaseInfo *)type);
+	  type = g_type_info_get_param_type (info, 1);
+	  write_type_info (namespace, type, file);
+	  g_base_info_unref ((GIBaseInfo *)type);
+	}
+      xml_end_element (file, "type");
+    }
+  else if (tag == GI_TYPE_TAG_ERROR)
+    {
+      gint n;
+
+      xml_start_element (file, "type");
+      xml_printf (file, " name=\"GLib.Error\"");
+
+      n = g_type_info_get_n_error_domains (info);
+      if (n > 0)
+	{
+	  for (i = 0; i < n; i++)
+	    {
+	      GIErrorDomainInfo *ed = g_type_info_get_error_domain (info, i);
+	      xml_start_element (file, "type");
+	      write_type_name_attribute (namespace, (GIBaseInfo *)ed, "name", file);
+	      xml_end_element (file, "type");
+	      g_base_info_unref ((GIBaseInfo *)ed);
+	    }
+	}
+
+      xml_end_element (file, "type");
+    }
+  else
+    {
+      g_printerr ("Unhandled type tag %d\n", tag);
+      g_assert_not_reached ();
+    }
+}
+
+static void
+write_attributes (Xml *file,
+                   GIBaseInfo *info)
+{
+  GIAttributeIter iter = { 0, };
+  char *name, *value;
+
+  while (g_base_info_iterate_attributes (info, &iter, &name, &value))
+    {
+      xml_start_element (file, "attribute");
+      xml_printf (file, " name=\"%s\" value=\"%s\"", name, value);
+      xml_end_element (file, "attribute");
+    }
+}
+
+static void
+write_constant_value (const gchar *namespace,
+		      GITypeInfo *info,
+		      GArgument *argument,
+		      Xml *file);
+
+static void
+write_callback_info (const gchar    *namespace,
+		     GICallbackInfo *info,
+		     Xml            *file);
+
+static void
+write_field_info (const gchar *namespace,
+		  GIFieldInfo *info,
+		  GIConstantInfo *branch,
+		  Xml         *file)
+{
+  const gchar *name;
+  GIFieldInfoFlags flags;
+  gint size;
+  gint offset;
+  GITypeInfo *type;
+  GIBaseInfo *interface;
+  GArgument value;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  flags = g_field_info_get_flags (info);
+  size = g_field_info_get_size (info);
+  offset = g_field_info_get_offset (info);
+
+  xml_start_element (file, "field");
+  xml_printf (file, " name=\"%s\"", name);
+
+  /* Fields are assumed to be read-only
+   * (see also girwriter.py and girparser.c)
+   */
+  if (!(flags & GI_FIELD_IS_READABLE))
+    xml_printf (file, " readable=\"0\"");
+  if (flags & GI_FIELD_IS_WRITABLE)
+    xml_printf (file, " writable=\"1\"");
+
+  if (size)
+    xml_printf (file, " bits=\"%d\"", size);
+
+  write_attributes (file, (GIBaseInfo*) info);
+
+  type = g_field_info_get_type (info);
+
+  if (branch)
+    {
+      xml_printf (file, " branch=\"");
+      type = g_constant_info_get_type (branch);
+      g_constant_info_get_value (branch, &value);
+      write_constant_value (namespace, type, &value, file);
+      xml_printf (file, "\"");
+    }
+
+  if (file->show_all)
+    {
+      if (offset >= 0)
+        xml_printf (file, "offset=\"%d\"", offset);
+    }
+
+  interface = g_type_info_get_interface (type);
+  if (interface && g_base_info_get_type(interface) == GI_INFO_TYPE_CALLBACK)
+    write_callback_info (namespace, (GICallbackInfo *)interface, file);
+  else
+    write_type_info (namespace, type, file);
+
+  if (interface)
+    g_base_info_unref (interface);
+
+  g_base_info_unref ((GIBaseInfo *)type);
+
+  xml_end_element (file, "field");
+}
+
+static void
+write_callable_info (const gchar    *namespace,
+		     GICallableInfo *info,
+		     Xml            *file)
+{
+  GITypeInfo *type;
+  gint i;
+
+  write_attributes (file, (GIBaseInfo*) info);
+
+  type = g_callable_info_get_return_type (info);
+
+  xml_start_element (file, "return-value");
+
+  switch (g_callable_info_get_caller_owns (info))
+    {
+    case GI_TRANSFER_NOTHING:
+      xml_printf (file, " transfer-ownership=\"none\"");
+      break;
+    case GI_TRANSFER_CONTAINER:
+      xml_printf (file, " transfer-ownership=\"container\"");
+      break;
+    case GI_TRANSFER_EVERYTHING:
+      xml_printf (file, " transfer-ownership=\"full\"");
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+
+  if (g_callable_info_may_return_null (info))
+    xml_printf (file, " allow-none=\"1\"");
+
+  write_type_info (namespace, type, file);
+
+  xml_end_element (file, "return-value");
+
+  if (g_callable_info_get_n_args (info) <= 0)
+    return;
+
+  xml_start_element (file, "parameters");
+  for (i = 0; i < g_callable_info_get_n_args (info); i++)
+    {
+      GIArgInfo *arg = g_callable_info_get_arg (info, i);
+
+      xml_start_element (file, "parameter");
+      xml_printf (file, " name=\"%s\"",
+                  g_base_info_get_name ((GIBaseInfo *) arg));
+
+      switch (g_arg_info_get_ownership_transfer (arg))
+	{
+	case GI_TRANSFER_NOTHING:
+	  xml_printf (file, " transfer-ownership=\"none\"");
+	  break;
+	case GI_TRANSFER_CONTAINER:
+	  xml_printf (file, " transfer-ownership=\"container\"");
+	  break;
+	case GI_TRANSFER_EVERYTHING:
+	  xml_printf (file, " transfer-ownership=\"full\"");
+	  break;
+	default:
+	  g_assert_not_reached ();
+	}
+
+      switch (g_arg_info_get_direction (arg))
+	{
+	case GI_DIRECTION_IN:
+	  break;
+	case GI_DIRECTION_OUT:
+	  xml_printf (file, " direction=\"out\" caller-allocates=\"%s\"",
+	              g_arg_info_is_caller_allocates (arg) ? "1" : "0");
+	  break;
+	case GI_DIRECTION_INOUT:
+	  xml_printf (file, " direction=\"inout\"");
+	  break;
+	}
+
+      if (g_arg_info_may_be_null (arg))
+	xml_printf (file, " allow-none=\"1\"");
+
+      if (g_arg_info_is_return_value (arg))
+	xml_printf (file, " retval=\"1\"");
+
+      if (g_arg_info_is_optional (arg))
+	xml_printf (file, " optional=\"1\"");
+
+      switch (g_arg_info_get_scope (arg))
+        {
+        case GI_SCOPE_TYPE_INVALID:
+          break;
+        case GI_SCOPE_TYPE_CALL:
+          xml_printf (file, " scope=\"call\"");
+          break;
+        case GI_SCOPE_TYPE_ASYNC:
+          xml_printf (file, " scope=\"async\"");
+          break;
+        case GI_SCOPE_TYPE_NOTIFIED:
+          xml_printf (file, " scope=\"notified\"");
+          break;
+        }
+
+      if (g_arg_info_get_closure (arg) >= 0)
+        xml_printf (file, " closure=\"%d\"", g_arg_info_get_closure (arg));
+
+      if (g_arg_info_get_destroy (arg) >= 0)
+        xml_printf (file, " destroy=\"%d\"", g_arg_info_get_destroy (arg));
+
+      type = g_arg_info_get_type (arg);
+      write_type_info (namespace, type, file);
+
+      xml_end_element (file, "parameter");
+
+      g_base_info_unref ((GIBaseInfo *)arg);
+    }
+
+  xml_end_element (file, "parameters");
+  g_base_info_unref ((GIBaseInfo *)type);
+}
+
+static void
+write_function_info (const gchar    *namespace,
+		     GIFunctionInfo *info,
+		     Xml            *file)
+{
+  GIFunctionInfoFlags flags;
+  const gchar *tag;
+  const gchar *name;
+  const gchar *symbol;
+  gboolean deprecated;
+  gboolean throws;
+
+  flags = g_function_info_get_flags (info);
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  symbol = g_function_info_get_symbol (info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+  throws = flags & GI_FUNCTION_THROWS;
+
+  if (flags & GI_FUNCTION_IS_CONSTRUCTOR)
+    tag = "constructor";
+  else if (flags & GI_FUNCTION_IS_METHOD)
+    tag = "method";
+  else
+    tag = "function";
+
+  xml_start_element (file, tag);
+  xml_printf (file, " name=\"%s\" c:identifier=\"%s\"",
+              name, symbol);
+
+  if (flags & GI_FUNCTION_IS_SETTER)
+    xml_printf (file, " type=\"setter\"");
+  else if (flags & GI_FUNCTION_IS_GETTER)
+    xml_printf (file, " type=\"getter\"");
+
+  if (deprecated)
+    xml_printf (file, " deprecated=\"1\"");
+
+  if (throws)
+    xml_printf (file, " throws=\"1\"");
+
+  write_callable_info (namespace, (GICallableInfo*)info, file);
+  xml_end_element (file, tag);
+}
+
+static void
+write_callback_info (const gchar    *namespace,
+		     GICallbackInfo *info,
+		     Xml            *file)
+{
+  const gchar *name;
+  gboolean deprecated;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+  xml_start_element (file, "callback");
+  xml_printf (file, " name=\"%s\"", name);
+
+  if (deprecated)
+    xml_printf (file, " deprecated=\"1\"");
+
+  write_callable_info (namespace, (GICallableInfo*)info, file);
+  xml_end_element (file, "callback");
+}
+
+static void
+write_struct_info (const gchar  *namespace,
+		   GIStructInfo *info,
+		   Xml          *file)
+{
+  const gchar *name;
+  const gchar *type_name;
+  const gchar *type_init;
+  gboolean deprecated;
+  gboolean is_gtype_struct;
+  gboolean foreign;
+  gint i;
+  gint size;
+  int n_elts;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+  type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+  type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+
+  if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_BOXED)
+    {
+      xml_start_element (file, "glib:boxed");
+      xml_printf (file, " glib:name=\"%s\"", name);
+    }
+  else
+    {
+      xml_start_element (file, "record");
+      xml_printf (file, " name=\"%s\"", name);
+    }
+
+  if (type_name != NULL)
+    xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
+
+  if (deprecated)
+    xml_printf (file, " deprecated=\"1\"");
+
+  is_gtype_struct = g_struct_info_is_gtype_struct (info);
+  if (is_gtype_struct)
+    xml_printf (file, " glib:is-gtype-struct=\"1\"");
+
+  write_attributes (file, (GIBaseInfo*) info);
+
+  size = g_struct_info_get_size (info);
+  if (file->show_all && size >= 0)
+    xml_printf (file, " size=\"%d\"", size);
+
+  foreign = g_struct_info_is_foreign (info);
+  if (foreign)
+    xml_printf (file, " foreign=\"1\"");
+
+  n_elts = g_struct_info_get_n_fields (info) + g_struct_info_get_n_methods (info);
+  if (n_elts > 0)
+    {
+      for (i = 0; i < g_struct_info_get_n_fields (info); i++)
+	{
+	  GIFieldInfo *field = g_struct_info_get_field (info, i);
+	  write_field_info (namespace, field, NULL, file);
+	  g_base_info_unref ((GIBaseInfo *)field);
+	}
+
+      for (i = 0; i < g_struct_info_get_n_methods (info); i++)
+	{
+	  GIFunctionInfo *function = g_struct_info_get_method (info, i);
+	  write_function_info (namespace, function, file);
+	  g_base_info_unref ((GIBaseInfo *)function);
+	}
+
+    }
+
+  xml_end_element_unchecked (file);
+}
+
+static void
+write_value_info (const gchar *namespace,
+		  GIValueInfo *info,
+		  Xml         *file)
+{
+  const gchar *name;
+  glong value;
+  gboolean deprecated;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  value = g_value_info_get_value (info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+  xml_start_element (file, "member");
+  xml_printf (file, " name=\"%s\" value=\"%ld\"", name, value);
+
+  if (deprecated)
+    xml_printf (file, " deprecated=\"1\"");
+
+  write_attributes (file, (GIBaseInfo*) info);
+
+  xml_end_element (file, "member");
+}
+
+static void
+write_constant_value (const gchar *namespace,
+		      GITypeInfo *type,
+		      GArgument  *value,
+		      Xml        *file)
+{
+  switch (g_type_info_get_tag (type))
+    {
+    case GI_TYPE_TAG_BOOLEAN:
+      xml_printf (file, "%d", value->v_boolean);
+      break;
+    case GI_TYPE_TAG_INT8:
+      xml_printf (file, "%d", value->v_int8);
+      break;
+    case GI_TYPE_TAG_UINT8:
+      xml_printf (file, "%d", value->v_uint8);
+      break;
+    case GI_TYPE_TAG_INT16:
+      xml_printf (file, "%" G_GINT16_FORMAT, value->v_int16);
+      break;
+    case GI_TYPE_TAG_UINT16:
+      xml_printf (file, "%" G_GUINT16_FORMAT, value->v_uint16);
+      break;
+    case GI_TYPE_TAG_INT32:
+      xml_printf (file, "%" G_GINT32_FORMAT, value->v_int32);
+      break;
+    case GI_TYPE_TAG_UINT32:
+      xml_printf (file, "%" G_GUINT32_FORMAT, value->v_uint32);
+      break;
+    case GI_TYPE_TAG_INT64:
+      xml_printf (file, "%" G_GINT64_FORMAT, value->v_int64);
+      break;
+    case GI_TYPE_TAG_UINT64:
+      xml_printf (file, "%" G_GUINT64_FORMAT, value->v_uint64);
+      break;
+    case GI_TYPE_TAG_INT:
+      xml_printf (file, "%d", value->v_int);
+      break;
+    case GI_TYPE_TAG_UINT:
+      xml_printf (file, "%d", value->v_uint);
+      break;
+    case GI_TYPE_TAG_LONG:
+      xml_printf (file, "%ld", value->v_long);
+      break;
+    case GI_TYPE_TAG_ULONG:
+      xml_printf (file, "%ld", value->v_ulong);
+      break;
+    case GI_TYPE_TAG_SSIZE:
+      xml_printf (file, "%zd", value->v_ssize);
+      break;
+    case GI_TYPE_TAG_SIZE:
+      xml_printf (file, "%zd", value->v_size);
+      break;
+    case GI_TYPE_TAG_FLOAT:
+      xml_printf (file, "%f", value->v_float);
+      break;
+    case GI_TYPE_TAG_DOUBLE:
+      xml_printf (file, "%f", value->v_double);
+      break;
+    case GI_TYPE_TAG_UTF8:
+    case GI_TYPE_TAG_FILENAME:
+      xml_printf (file, "%s", value->v_string);
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+write_constant_info (const gchar    *namespace,
+		     GIConstantInfo *info,
+		     Xml            *file)
+{
+  GITypeInfo *type;
+  const gchar *name;
+  gboolean deprecated;
+  GArgument value;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+  xml_start_element (file, "constant");
+  xml_printf (file, " name=\"%s\"", name);
+
+  type = g_constant_info_get_type (info);
+  xml_printf (file, " value=\"");
+
+  g_constant_info_get_value (info, &value);
+  write_constant_value (namespace, type, &value, file);
+  xml_printf (file, "\"");
+
+  write_type_info (namespace, type, file);
+
+  write_attributes (file, (GIBaseInfo*) info);
+
+  xml_end_element (file, "constant");
+
+  g_base_info_unref ((GIBaseInfo *)type);
+}
+
+
+static void
+write_enum_info (const gchar *namespace,
+		 GIEnumInfo *info,
+		 Xml         *file)
+{
+  const gchar *name;
+  const gchar *type_name;
+  const gchar *type_init;
+  gboolean deprecated;
+  gint i;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+  type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+  type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+
+  if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM)
+    xml_start_element (file, "enumeration");
+  else
+    xml_start_element (file, "bitfield");
+  xml_printf (file, " name=\"%s\"", name);
+
+  if (type_init)
+    xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
+
+  if (deprecated)
+    xml_printf (file, " deprecated=\"1\"");
+
+  write_attributes (file, (GIBaseInfo*) info);
+
+  for (i = 0; i < g_enum_info_get_n_values (info); i++)
+    {
+      GIValueInfo *value = g_enum_info_get_value (info, i);
+      write_value_info (namespace, value, file);
+      g_base_info_unref ((GIBaseInfo *)value);
+    }
+
+  xml_end_element_unchecked (file);
+}
+
+static void
+write_signal_info (const gchar  *namespace,
+		   GISignalInfo *info,
+		   Xml          *file)
+{
+  GSignalFlags flags;
+  const gchar *name;
+  gboolean deprecated;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  flags = g_signal_info_get_flags (info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+  xml_start_element (file, "glib:signal");
+  xml_printf (file, " name=\"%s\"", name);
+
+  if (deprecated)
+    xml_printf (file, " deprecated=\"1\"");
+
+  if (flags & G_SIGNAL_RUN_FIRST)
+    xml_printf (file, " when=\"FIRST\"");
+  else if (flags & G_SIGNAL_RUN_LAST)
+    xml_printf (file, " when=\"LAST\"");
+  else if (flags & G_SIGNAL_RUN_CLEANUP)
+    xml_printf (file, " when=\"CLEANUP\"");
+
+  if (flags & G_SIGNAL_NO_RECURSE)
+    xml_printf (file, " no-recurse=\"1\"");
+
+  if (flags & G_SIGNAL_DETAILED)
+    xml_printf (file, " detailed=\"1\"");
+
+  if (flags & G_SIGNAL_ACTION)
+    xml_printf (file, " action=\"1\"");
+
+  if (flags & G_SIGNAL_NO_HOOKS)
+    xml_printf (file, " no-hooks=\"1\"");
+
+  write_callable_info (namespace, (GICallableInfo*)info, file);
+
+  xml_end_element (file, "glib:signal");
+}
+
+static void
+write_vfunc_info (const gchar *namespace,
+		  GIVFuncInfo *info,
+		  Xml         *file)
+{
+  GIVFuncInfoFlags flags;
+  const gchar *name;
+  GIFunctionInfo *invoker;
+  gboolean deprecated;
+  gint offset;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  flags = g_vfunc_info_get_flags (info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+  offset = g_vfunc_info_get_offset (info);
+  invoker = g_vfunc_info_get_invoker (info);
+
+  xml_start_element (file, "virtual-method");
+  xml_printf (file, " name=\"%s\"", name);
+
+  if (deprecated)
+    xml_printf (file, " deprecated=\"1\"");
+
+  if (flags & GI_VFUNC_MUST_CHAIN_UP)
+    xml_printf (file, " must-chain-up=\"1\"");
+
+  if (flags & GI_VFUNC_MUST_OVERRIDE)
+    xml_printf (file, " override=\"always\"");
+  else if (flags & GI_VFUNC_MUST_NOT_OVERRIDE)
+    xml_printf (file, " override=\"never\"");
+
+  xml_printf (file, " offset=\"%d\"", offset);
+
+  if (invoker)
+    xml_printf (file, " invoker=\"%s\"", g_base_info_get_name ((GIBaseInfo*)invoker));
+
+  write_callable_info (namespace, (GICallableInfo*)info, file);
+
+  xml_end_element (file, "virtual-method");
+}
+
+static void
+write_property_info (const gchar    *namespace,
+		     GIPropertyInfo *info,
+		     Xml            *file)
+{
+  GParamFlags flags;
+  const gchar *name;
+  gboolean deprecated;
+  GITypeInfo *type;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  flags = g_property_info_get_flags (info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+  xml_start_element (file, "property");
+  xml_printf (file, " name=\"%s\"", name);
+
+  if (deprecated)
+    xml_printf (file, " deprecated=\"1\"");
+
+  /* Properties are assumed to be read-only (see also girwriter.py) */
+  if (!(flags & G_PARAM_READABLE))
+    xml_printf (file, " readable=\"0\"");
+  if (flags & G_PARAM_WRITABLE)
+    xml_printf (file, " writable=\"1\"");
+
+  if (flags & G_PARAM_CONSTRUCT)
+    xml_printf (file, " construct=\"1\"");
+
+  if (flags & G_PARAM_CONSTRUCT_ONLY)
+    xml_printf (file, " construct-only=\"1\"");
+
+  write_attributes (file, (GIBaseInfo*) info);
+
+  type = g_property_info_get_type (info);
+
+  write_type_info (namespace, type, file);
+
+  xml_end_element (file, "property");
+}
+
+static void
+write_object_info (const gchar  *namespace,
+		   GIObjectInfo *info,
+		   Xml          *file)
+{
+  const gchar *name;
+  const gchar *type_name;
+  const gchar *type_init;
+  gboolean deprecated;
+  gboolean is_abstract;
+  GIObjectInfo *pnode;
+  GIStructInfo *class_struct;
+  gint i;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+  is_abstract = g_object_info_get_abstract (info);
+
+  type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+  type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+  xml_start_element (file, "class");
+  xml_printf (file, " name=\"%s\"", name);
+
+  pnode = g_object_info_get_parent (info);
+  if (pnode)
+    {
+      write_type_name_attribute (namespace, (GIBaseInfo *)pnode, "parent", file);
+      g_base_info_unref ((GIBaseInfo *)pnode);
+    }
+
+  class_struct = g_object_info_get_class_struct (info);
+  if (class_struct)
+    {
+      write_type_name_attribute (namespace, (GIBaseInfo*) class_struct, "glib:type-struct", file);
+      g_base_info_unref ((GIBaseInfo*)class_struct);
+    }
+
+  if (is_abstract)
+    xml_printf (file, " abstract=\"1\"");
+
+  xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
+
+  if (deprecated)
+    xml_printf (file, " deprecated=\"1\"");
+
+  write_attributes (file, (GIBaseInfo*) info);
+
+  if (g_object_info_get_n_interfaces (info) > 0)
+    {
+      for (i = 0; i < g_object_info_get_n_interfaces (info); i++)
+	{
+	  GIInterfaceInfo *imp = g_object_info_get_interface (info, i);
+          xml_start_element (file, "implements");
+	  write_type_name_attribute (namespace, (GIBaseInfo *)imp, "name", file);
+          xml_end_element (file, "implements");
+	  g_base_info_unref ((GIBaseInfo*)imp);
+	}
+    }
+
+  for (i = 0; i < g_object_info_get_n_fields (info); i++)
+    {
+      GIFieldInfo *field = g_object_info_get_field (info, i);
+      write_field_info (namespace, field, NULL, file);
+      g_base_info_unref ((GIBaseInfo *)field);
+    }
+
+  for (i = 0; i < g_object_info_get_n_methods (info); i++)
+    {
+      GIFunctionInfo *function = g_object_info_get_method (info, i);
+      write_function_info (namespace, function, file);
+      g_base_info_unref ((GIBaseInfo *)function);
+    }
+
+  for (i = 0; i < g_object_info_get_n_properties (info); i++)
+    {
+      GIPropertyInfo *prop = g_object_info_get_property (info, i);
+      write_property_info (namespace, prop, file);
+      g_base_info_unref ((GIBaseInfo *)prop);
+    }
+
+  for (i = 0; i < g_object_info_get_n_signals (info); i++)
+    {
+      GISignalInfo *signal = g_object_info_get_signal (info, i);
+      write_signal_info (namespace, signal, file);
+      g_base_info_unref ((GIBaseInfo *)signal);
+    }
+
+  for (i = 0; i < g_object_info_get_n_vfuncs (info); i++)
+    {
+      GIVFuncInfo *vfunc = g_object_info_get_vfunc (info, i);
+      write_vfunc_info (namespace, vfunc, file);
+      g_base_info_unref ((GIBaseInfo *)vfunc);
+    }
+
+  for (i = 0; i < g_object_info_get_n_constants (info); i++)
+    {
+      GIConstantInfo *constant = g_object_info_get_constant (info, i);
+      write_constant_info (namespace, constant, file);
+      g_base_info_unref ((GIBaseInfo *)constant);
+    }
+
+  xml_end_element (file, "class");
+}
+
+static void
+write_interface_info (const gchar     *namespace,
+		      GIInterfaceInfo *info,
+		      Xml             *file)
+{
+  const gchar *name;
+  const gchar *type_name;
+  const gchar *type_init;
+  GIStructInfo *class_struct;
+  gboolean deprecated;
+  gint i;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+  type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+  type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+  xml_start_element (file, "interface");
+  xml_printf (file, " name=\"%s\" glib:type-name=\"%s\" glib:get-type=\"%s\"",
+	     name, type_name, type_init);
+
+  class_struct = g_interface_info_get_iface_struct (info);
+  if (class_struct)
+    {
+      write_type_name_attribute (namespace, (GIBaseInfo*) class_struct, "glib:type-struct", file);
+      g_base_info_unref ((GIBaseInfo*)class_struct);
+    }
+
+  if (deprecated)
+    xml_printf (file, " deprecated=\"1\"");
+
+  write_attributes (file, (GIBaseInfo*) info);
+
+  if (g_interface_info_get_n_prerequisites (info) > 0)
+    {
+      for (i = 0; i < g_interface_info_get_n_prerequisites (info); i++)
+	{
+	  GIBaseInfo *req = g_interface_info_get_prerequisite (info, i);
+
+	  xml_start_element (file, "prerequisite");
+	  write_type_name_attribute (namespace, req, "name", file);
+
+          xml_end_element_unchecked (file);
+	  g_base_info_unref (req);
+	}
+    }
+
+  for (i = 0; i < g_interface_info_get_n_methods (info); i++)
+    {
+      GIFunctionInfo *function = g_interface_info_get_method (info, i);
+      write_function_info (namespace, function, file);
+      g_base_info_unref ((GIBaseInfo *)function);
+    }
+
+  for (i = 0; i < g_interface_info_get_n_properties (info); i++)
+    {
+      GIPropertyInfo *prop = g_interface_info_get_property (info, i);
+      write_property_info (namespace, prop, file);
+      g_base_info_unref ((GIBaseInfo *)prop);
+    }
+
+  for (i = 0; i < g_interface_info_get_n_signals (info); i++)
+    {
+      GISignalInfo *signal = g_interface_info_get_signal (info, i);
+      write_signal_info (namespace, signal, file);
+      g_base_info_unref ((GIBaseInfo *)signal);
+    }
+
+  for (i = 0; i < g_interface_info_get_n_vfuncs (info); i++)
+    {
+      GIVFuncInfo *vfunc = g_interface_info_get_vfunc (info, i);
+      write_vfunc_info (namespace, vfunc, file);
+      g_base_info_unref ((GIBaseInfo *)vfunc);
+    }
+
+  for (i = 0; i < g_interface_info_get_n_constants (info); i++)
+    {
+      GIConstantInfo *constant = g_interface_info_get_constant (info, i);
+      write_constant_info (namespace, constant, file);
+      g_base_info_unref ((GIBaseInfo *)constant);
+    }
+
+  xml_end_element (file, "interface");
+}
+
+static void
+write_error_domain_info (const gchar       *namespace,
+			 GIErrorDomainInfo *info,
+			 Xml               *file)
+{
+  GIBaseInfo *enum_;
+  const gchar *name, *quark;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  quark = g_error_domain_info_get_quark (info);
+  enum_ = (GIBaseInfo *)g_error_domain_info_get_codes (info);
+  xml_start_element (file, "errordomain");
+  xml_printf (file, " name=\"%s\" get-quark=\"%s\"",
+              name, quark);
+  write_type_name_attribute (namespace, enum_, "codes", file);
+  xml_end_element (file, "errordomain");
+  g_base_info_unref (enum_);
+}
+
+static void
+write_union_info (const gchar *namespace,
+		  GIUnionInfo *info,
+		  Xml         *file)
+{
+  const gchar *name;
+  const gchar *type_name;
+  const gchar *type_init;
+  gboolean deprecated;
+  gint i;
+  gint size;
+
+  name = g_base_info_get_name ((GIBaseInfo *)info);
+  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
+
+  type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
+  type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
+
+  xml_start_element (file, "union");
+  xml_printf (file, " name=\"%s\"", name);
+
+  if (type_name)
+    xml_printf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
+
+  if (deprecated)
+    xml_printf (file, " deprecated=\"1\"");
+
+  size = g_union_info_get_size (info);
+  if (file->show_all && size >= 0)
+    xml_printf (file, " size=\"%d\"", size);
+
+  write_attributes (file, (GIBaseInfo*) info);
+
+  if (g_union_info_is_discriminated (info))
+    {
+      gint offset;
+      GITypeInfo *type;
+
+      offset = g_union_info_get_discriminator_offset (info);
+      type = g_union_info_get_discriminator_type (info);
+
+      xml_start_element (file, "discriminator");
+      xml_printf (file, " offset=\"%d\" type=\"", offset);
+      write_type_info (namespace, type, file);
+      xml_end_element (file, "discriminator");
+      g_base_info_unref ((GIBaseInfo *)type);
+    }
+
+  for (i = 0; i < g_union_info_get_n_fields (info); i++)
+    {
+      GIFieldInfo *field = g_union_info_get_field (info, i);
+      GIConstantInfo *constant = g_union_info_get_discriminator (info, i);
+      write_field_info (namespace, field, constant, file);
+      g_base_info_unref ((GIBaseInfo *)field);
+      if (constant)
+	g_base_info_unref ((GIBaseInfo *)constant);
+    }
+
+  for (i = 0; i < g_union_info_get_n_methods (info); i++)
+    {
+      GIFunctionInfo *function = g_union_info_get_method (info, i);
+      write_function_info (namespace, function, file);
+      g_base_info_unref ((GIBaseInfo *)function);
+    }
+
+  xml_end_element (file, "union");
+}
+
+
+/**
+ * gir_writer_write:
+ * @filename: filename to write to
+ * @namespace: GIR namespace to write
+ * @needs_prefix:
+ * @show_all:
+ *
+ * Writes the output of a typelib represented by @namespace
+ * into a GIR xml file named @filename.
+ */
+void
+gir_writer_write (const char *filename,
+		  const char *namespace,
+		  gboolean    needs_prefix,
+		  gboolean    show_all)
+{
+  FILE *ofile;
+  gint i, j;
+  char **dependencies;
+  GIRepository *repository;
+  Xml *xml;
+
+  repository = g_irepository_get_default ();
+
+  if (filename == NULL)
+    ofile = stdout;
+  else
+    {
+      gchar *full_filename;
+
+      if (needs_prefix)
+	full_filename = g_strdup_printf ("%s-%s", namespace, filename);
+      else
+	full_filename = g_strdup (filename);
+      ofile = g_fopen (filename, "w");
+
+      if (ofile == NULL)
+	{
+	  g_fprintf (stderr, "failed to open '%s': %s\n",
+		     full_filename, g_strerror (errno));
+	  g_free (full_filename);
+
+	  return;
+	}
+
+      g_free (full_filename);
+    }
+
+  xml = xml_open (ofile);
+  xml->show_all = show_all;
+  xml_printf (xml, "<?xml version=\"1.0\"?>\n");
+  xml_start_element (xml, "repository");
+  xml_printf (xml, " version=\"1.0\"\n"
+	      "            xmlns=\"http://www.gtk.org/introspection/core/1.0\"\n";
+	      "            xmlns:c=\"http://www.gtk.org/introspection/c/1.0\"\n";
+	      "            xmlns:glib=\"http://www.gtk.org/introspection/glib/1.0\"";);
+
+  dependencies = g_irepository_get_dependencies (repository,
+						 namespace);
+  if (dependencies != NULL)
+    {
+      for (i = 0; dependencies[i]; i++)
+	{
+	  char **parts = g_strsplit (dependencies[i], "-", 2);
+	  xml_start_element (xml, "include");
+	  xml_printf (xml, " name=\"%s\" version=\"%s\"", parts[0], parts[1]);
+	  xml_end_element (xml, "include");
+	  g_strfreev (parts);
+	}
+    }
+
+  if (TRUE)
+    {
+      const gchar *shared_library;
+      const gchar *c_prefix;
+      const char *ns = namespace;
+      const char *version;
+
+      version = g_irepository_get_version (repository, ns);
+
+      shared_library = g_irepository_get_shared_library (repository, ns);
+      c_prefix = g_irepository_get_c_prefix (repository, ns);
+      xml_start_element (xml, "namespace");
+      xml_printf (xml, " name=\"%s\" version=\"%s\"", ns, version);
+      if (shared_library)
+        xml_printf (xml, " shared-library=\"%s\"", shared_library);
+      if (c_prefix)
+        xml_printf (xml, " c:prefix=\"%s\"", c_prefix);
+
+      for (j = 0; j < g_irepository_get_n_infos (repository, ns); j++)
+	{
+	  GIBaseInfo *info = g_irepository_get_info (repository, ns, j);
+	  switch (g_base_info_get_type (info))
+	    {
+	    case GI_INFO_TYPE_FUNCTION:
+	      write_function_info (ns, (GIFunctionInfo *)info, xml);
+	      break;
+
+	    case GI_INFO_TYPE_CALLBACK:
+	      write_callback_info (ns, (GICallbackInfo *)info, xml);
+	      break;
+
+	    case GI_INFO_TYPE_STRUCT:
+	    case GI_INFO_TYPE_BOXED:
+	      write_struct_info (ns, (GIStructInfo *)info, xml);
+	      break;
+
+	    case GI_INFO_TYPE_UNION:
+	      write_union_info (ns, (GIUnionInfo *)info, xml);
+	      break;
+
+	    case GI_INFO_TYPE_ENUM:
+	    case GI_INFO_TYPE_FLAGS:
+	      write_enum_info (ns, (GIEnumInfo *)info, xml);
+	      break;
+
+	    case GI_INFO_TYPE_CONSTANT:
+	      write_constant_info (ns, (GIConstantInfo *)info, xml);
+	      break;
+
+	    case GI_INFO_TYPE_OBJECT:
+	      write_object_info (ns, (GIObjectInfo *)info, xml);
+	      break;
+
+	    case GI_INFO_TYPE_INTERFACE:
+	      write_interface_info (ns, (GIInterfaceInfo *)info, xml);
+	      break;
+
+	    case GI_INFO_TYPE_ERROR_DOMAIN:
+	      write_error_domain_info (ns, (GIErrorDomainInfo *)info, xml);
+	      break;
+
+	    default:
+	      g_error ("unknown info type %d\n", g_base_info_get_type (info));
+	    }
+
+	  g_base_info_unref (info);
+	}
+
+      xml_end_element (xml, "namespace");
+    }
+
+  xml_end_element (xml, "repository");
+
+  xml_free (xml);
+}
diff --git a/girepository/girwriter.h b/girepository/girwriter.h
index 5d41a0c..3ca7418 100644
--- a/girepository/girwriter.h
+++ b/girepository/girwriter.h
@@ -18,9 +18,12 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#ifndef __G_IDL_WRITER_H__
-#define __G_IDL_WRITER_H__
+#ifndef __GIRWRITER_H__
+#define __GIRWRITER_H__
 
-void g_idl_writer_save_file (GIdlModule *module, const gchar *filename);
+void gir_writer_write (const char *filename,
+		       const char *namespace,
+		       gboolean    needs_prefix,
+		       gboolean    show_all);
 
-#endif  /* __G_IDL_WRITER_H__ */
+#endif  /* __GIRWRITER_H__ */
diff --git a/tools/Makefile.am b/tools/Makefile.am
index ba0fa9f..31acd02 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -20,6 +20,7 @@ g_ir_compiler_LDADD = \
 g_ir_generate_SOURCES = generate.c
 g_ir_generate_CFLAGS = $(GIREPO_CFLAGS)
 g_ir_generate_LDADD = \
+	$(top_builddir)/girepository/libgirepository-parser.la \
 	$(top_builddir)/girepository/libgirepository-1.0.la \
 	$(GIREPO_LIBS)
 
diff --git a/tools/generate.c b/tools/generate.c
index 3937f40..cd1fedc 100644
--- a/tools/generate.c
+++ b/tools/generate.c
@@ -21,1377 +21,18 @@
  * Boston, MA 02111-1307, USA.
  */
 
-#include <errno.h>
-#include <string.h>
-
 #include <glib.h>
-#include <glib-object.h>
 #include <glib/gstdio.h>
+#include <gmodule.h>
 
+#include "girwriter.h"
 #include "girepository.h"
 #include "gitypelib-internal.h"
 
-typedef struct {
-  FILE *file;
-  GSList *stack;
-  gboolean show_all;
-} Xml;
-
-typedef struct {
-  char *name;
-  guint has_children : 1;
-} XmlElement;
-
-static XmlElement *
-xml_element_new (const char *name)
-{
-  XmlElement *elem;
-
-  elem = g_new (XmlElement, 1);
-  elem->name = g_strdup (name);
-  elem->has_children = FALSE;
-  return elem;
-}
-
-static void
-xml_element_free (XmlElement *elem)
-{
-  g_free (elem->name);
-  g_free (elem);
-}
-
-static void
-xml_printf (Xml *xml, const char *fmt, ...)
-{
-  va_list ap;
-  char *s;
-
-  va_start (ap, fmt);
-  s = g_markup_vprintf_escaped (fmt, ap);
-  fputs (s, xml->file);
-  g_free (s);
-  va_end (ap);
-}
-
-static void
-xml_start_element (Xml *xml, const char *element_name)
-{
-  XmlElement *parent = NULL;
-
-  if (xml->stack)
-    {
-      parent = xml->stack->data;
-
-      if (!parent->has_children)
-        xml_printf (xml, ">\n");
-
-      parent->has_children = TRUE;
-    }
-
-  xml_printf (xml, "%*s<%s", g_slist_length(xml->stack)*2, "", element_name);
-
-  xml->stack = g_slist_prepend (xml->stack, xml_element_new (element_name));
-}
-
-static void
-xml_end_element (Xml *xml, const char *name)
-{
-  XmlElement *elem;
-
-  g_assert (xml->stack != NULL);
-
-  elem = xml->stack->data;
-  xml->stack = g_slist_delete_link (xml->stack, xml->stack);
-
-  if (name != NULL)
-    g_assert_cmpstr (name, ==, elem->name);
-
-  if (elem->has_children)
-    xml_printf (xml, "%*s</%s>\n", g_slist_length (xml->stack)*2, "", elem->name);
-  else
-    xml_printf (xml, "/>\n");
-
-  xml_element_free (elem);
-}
-
-static void
-xml_end_element_unchecked (Xml *xml)
-{
-  xml_end_element (xml, NULL);
-}
-
-static Xml *
-xml_open (FILE *file)
-{
-  Xml *xml;
-
-  xml = g_new (Xml, 1);
-  xml->file = file;
-  xml->stack = NULL;
-
-  return xml;
-}
-
-static void
-xml_close (Xml *xml)
-{
-  g_assert (xml->stack == NULL);
-  if (xml->file != NULL)
-    {
-      fflush (xml->file);
-      if (xml->file != stdout)
-        fclose (xml->file);
-      xml->file = NULL;
-    }
-}
-
-static void
-xml_free (Xml *xml)
-{
-  xml_close (xml);
-  g_free (xml);
-}
-
-
-static void
-check_unresolved (GIBaseInfo *info)
-{
-  if (g_base_info_get_type (info) != GI_INFO_TYPE_UNRESOLVED)
-    return;
-
-  g_critical ("Found unresolved type '%s' '%s'\n",
-	      g_base_info_get_name (info), g_base_info_get_namespace (info));
-}
-
-static void
-write_type_name (const gchar *namespace,
-		 GIBaseInfo  *info,
-		 Xml         *file)
-{
-  if (strcmp (namespace, g_base_info_get_namespace (info)) != 0)
-    xml_printf (file, "%s.", g_base_info_get_namespace (info));
-
-  xml_printf (file, "%s", g_base_info_get_name (info));
-}
-
-static void
-write_type_name_attribute (const gchar *namespace,
-			   GIBaseInfo  *info,
-			   const char  *attr_name,
-			   Xml         *file)
-{
-  xml_printf (file, " %s=\"", attr_name);
-  write_type_name (namespace, info, file);
-  xml_printf (file, "\"");
-}
-
-static void
-write_type_info (const gchar *namespace,
-		 GITypeInfo  *info,
-		 Xml         *file)
-{
-  gint tag;
-  gint i;
-  GITypeInfo *type;
-  gboolean is_pointer;
-
-  check_unresolved ((GIBaseInfo*)info);
-
-  tag = g_type_info_get_tag (info);
-  is_pointer = g_type_info_is_pointer (info);
-
-  if (tag == GI_TYPE_TAG_VOID)
-    {
-      xml_start_element (file, "type");
-
-      xml_printf (file, " name=\"%s\"", is_pointer ? "any" : "none");
-
-      xml_end_element (file, "type");
-    }
-  else if (G_TYPE_TAG_IS_BASIC (tag))
-    {
-      xml_start_element (file, "type");
-      xml_printf (file, " name=\"%s\"", g_type_tag_to_string (tag));
-      xml_end_element (file, "type");
-    }
-  else if (tag == GI_TYPE_TAG_ARRAY)
-    {
-      gint length, size;
-      char *name = NULL;
-
-      xml_start_element (file, "array");
-
-      switch (g_type_info_get_array_type (info)) {
-        case GI_ARRAY_TYPE_C:
-            break;
-        case GI_ARRAY_TYPE_ARRAY:
-            name = "GLib.Array";
-            break;
-        case GI_ARRAY_TYPE_PTR_ARRAY:
-            name = "GLib.PtrArray";
-            break;
-        case GI_ARRAY_TYPE_BYTE_ARRAY:
-            name = "GLib.ByteArray";
-            break;
-        default:
-            break;
-      }
-
-      if (name)
-        xml_printf (file, " name=\"%s\"", name);
-
-      type = g_type_info_get_param_type (info, 0);
-
-      length = g_type_info_get_array_length (info);
-      if (length >= 0)
-        xml_printf (file, " length=\"%d\"", length);
-
-      size = g_type_info_get_array_fixed_size (info);
-      if (size >= 0)
-        xml_printf (file, " fixed-size=\"%d\"", size);
-
-      if (g_type_info_is_zero_terminated (info))
-	xml_printf (file, " zero-terminated=\"1\"");
-
-      write_type_info (namespace, type, file);
-
-      g_base_info_unref ((GIBaseInfo *)type);
-
-      xml_end_element (file, "array");
-    }
-  else if (tag == GI_TYPE_TAG_INTERFACE)
-    {
-      GIBaseInfo *iface = g_type_info_get_interface (info);
-      xml_start_element (file, "type");
-      write_type_name_attribute (namespace, iface, "name", file);
-      xml_end_element (file, "type");
-      g_base_info_unref (iface);
-    }
-  else if (tag == GI_TYPE_TAG_GLIST)
-    {
-      xml_start_element (file, "type");
-      xml_printf (file, " name=\"GLib.List\"");
-      type = g_type_info_get_param_type (info, 0);
-      if (type)
-	{
-	  write_type_info (namespace, type, file);
-	  g_base_info_unref ((GIBaseInfo *)type);
-	}
-      xml_end_element (file, "type");
-    }
-  else if (tag == GI_TYPE_TAG_GSLIST)
-    {
-      xml_start_element (file, "type");
-      xml_printf (file, " name=\"GLib.SList\"");
-      type = g_type_info_get_param_type (info, 0);
-      if (type)
-	{
-	  write_type_info (namespace, type, file);
-	  g_base_info_unref ((GIBaseInfo *)type);
-	}
-      xml_end_element (file, "type");
-    }
-  else if (tag == GI_TYPE_TAG_GHASH)
-    {
-      xml_start_element (file, "type");
-      xml_printf (file, " name=\"GLib.HashTable\"");
-      type = g_type_info_get_param_type (info, 0);
-      if (type)
-	{
-	  write_type_info (namespace, type, file);
-	  g_base_info_unref ((GIBaseInfo *)type);
-	  type = g_type_info_get_param_type (info, 1);
-	  write_type_info (namespace, type, file);
-	  g_base_info_unref ((GIBaseInfo *)type);
-	}
-      xml_end_element (file, "type");
-    }
-  else if (tag == GI_TYPE_TAG_ERROR)
-    {
-      gint n;
-
-      xml_start_element (file, "type");
-      xml_printf (file, " name=\"GLib.Error\"");
-
-      n = g_type_info_get_n_error_domains (info);
-      if (n > 0)
-	{
-	  for (i = 0; i < n; i++)
-	    {
-	      GIErrorDomainInfo *ed = g_type_info_get_error_domain (info, i);
-	      xml_start_element (file, "type");
-	      write_type_name_attribute (namespace, (GIBaseInfo *)ed, "name", file);
-	      xml_end_element (file, "type");
-	      g_base_info_unref ((GIBaseInfo *)ed);
-	    }
-	}
-
-      xml_end_element (file, "type");
-    }
-  else
-    {
-      g_printerr ("Unhandled type tag %d\n", tag);
-      g_assert_not_reached ();
-    }
-}
-
-static void
-write_attributes (Xml *file,
-                   GIBaseInfo *info)
-{
-  GIAttributeIter iter = { 0, };
-  char *name, *value;
-
-  while (g_base_info_iterate_attributes (info, &iter, &name, &value))
-    {
-      xml_start_element (file, "attribute");
-      xml_printf (file, " name=\"%s\" value=\"%s\"", name, value);
-      xml_end_element (file, "attribute");
-    }
-}
-
-static void
-write_constant_value (const gchar *namespace,
-		      GITypeInfo *info,
-		      GArgument *argument,
-		      Xml *file);
-
-static void
-write_callback_info (const gchar    *namespace,
-		     GICallbackInfo *info,
-		     Xml            *file);
-
-static void
-write_field_info (const gchar *namespace,
-		  GIFieldInfo *info,
-		  GIConstantInfo *branch,
-		  Xml         *file)
-{
-  const gchar *name;
-  GIFieldInfoFlags flags;
-  gint size;
-  gint offset;
-  GITypeInfo *type;
-  GIBaseInfo *interface;
-  GArgument value;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  flags = g_field_info_get_flags (info);
-  size = g_field_info_get_size (info);
-  offset = g_field_info_get_offset (info);
-
-  xml_start_element (file, "field");
-  xml_printf (file, " name=\"%s\"", name);
-
-  /* Fields are assumed to be read-only
-   * (see also girwriter.py and girparser.c)
-   */
-  if (!(flags & GI_FIELD_IS_READABLE))
-    xml_printf (file, " readable=\"0\"");
-  if (flags & GI_FIELD_IS_WRITABLE)
-    xml_printf (file, " writable=\"1\"");
-
-  if (size)
-    xml_printf (file, " bits=\"%d\"", size);
-
-  write_attributes (file, (GIBaseInfo*) info);
-
-  type = g_field_info_get_type (info);
-
-  if (branch)
-    {
-      xml_printf (file, " branch=\"");
-      type = g_constant_info_get_type (branch);
-      g_constant_info_get_value (branch, &value);
-      write_constant_value (namespace, type, &value, file);
-      xml_printf (file, "\"");
-    }
-
-  if (file->show_all)
-    {
-      if (offset >= 0)
-        xml_printf (file, "offset=\"%d\"", offset);
-    }
-
-  interface = g_type_info_get_interface (type);
-  if (interface && g_base_info_get_type(interface) == GI_INFO_TYPE_CALLBACK)
-    write_callback_info (namespace, (GICallbackInfo *)interface, file);
-  else
-    write_type_info (namespace, type, file);
-
-  if (interface)
-    g_base_info_unref (interface);
-
-  g_base_info_unref ((GIBaseInfo *)type);
-
-  xml_end_element (file, "field");
-}
-
-static void
-write_callable_info (const gchar    *namespace,
-		     GICallableInfo *info,
-		     Xml            *file)
-{
-  GITypeInfo *type;
-  gint i;
-
-  write_attributes (file, (GIBaseInfo*) info);
-
-  type = g_callable_info_get_return_type (info);
-
-  xml_start_element (file, "return-value");
-
-  switch (g_callable_info_get_caller_owns (info))
-    {
-    case GI_TRANSFER_NOTHING:
-      xml_printf (file, " transfer-ownership=\"none\"");
-      break;
-    case GI_TRANSFER_CONTAINER:
-      xml_printf (file, " transfer-ownership=\"container\"");
-      break;
-    case GI_TRANSFER_EVERYTHING:
-      xml_printf (file, " transfer-ownership=\"full\"");
-      break;
-    default:
-      g_assert_not_reached ();
-    }
-
-  if (g_callable_info_may_return_null (info))
-    xml_printf (file, " allow-none=\"1\"");
-
-  write_type_info (namespace, type, file);
-
-  xml_end_element (file, "return-value");
-
-  if (g_callable_info_get_n_args (info) <= 0)
-    return;
-
-  xml_start_element (file, "parameters");
-  for (i = 0; i < g_callable_info_get_n_args (info); i++)
-    {
-      GIArgInfo *arg = g_callable_info_get_arg (info, i);
-
-      xml_start_element (file, "parameter");
-      xml_printf (file, " name=\"%s\"",
-                  g_base_info_get_name ((GIBaseInfo *) arg));
-
-      switch (g_arg_info_get_ownership_transfer (arg))
-	{
-	case GI_TRANSFER_NOTHING:
-	  xml_printf (file, " transfer-ownership=\"none\"");
-	  break;
-	case GI_TRANSFER_CONTAINER:
-	  xml_printf (file, " transfer-ownership=\"container\"");
-	  break;
-	case GI_TRANSFER_EVERYTHING:
-	  xml_printf (file, " transfer-ownership=\"full\"");
-	  break;
-	default:
-	  g_assert_not_reached ();
-	}
-
-      switch (g_arg_info_get_direction (arg))
-	{
-	case GI_DIRECTION_IN:
-	  break;
-	case GI_DIRECTION_OUT:
-	  xml_printf (file, " direction=\"out\" caller-allocates=\"%s\"",
-	              g_arg_info_is_caller_allocates (arg) ? "1" : "0");
-	  break;
-	case GI_DIRECTION_INOUT:
-	  xml_printf (file, " direction=\"inout\"");
-	  break;
-	}
-
-      if (g_arg_info_may_be_null (arg))
-	xml_printf (file, " allow-none=\"1\"");
-
-      if (g_arg_info_is_return_value (arg))
-	xml_printf (file, " retval=\"1\"");
-
-      if (g_arg_info_is_optional (arg))
-	xml_printf (file, " optional=\"1\"");
-
-      switch (g_arg_info_get_scope (arg))
-        {
-        case GI_SCOPE_TYPE_INVALID:
-          break;
-        case GI_SCOPE_TYPE_CALL:
-          xml_printf (file, " scope=\"call\"");
-          break;
-        case GI_SCOPE_TYPE_ASYNC:
-          xml_printf (file, " scope=\"async\"");
-          break;
-        case GI_SCOPE_TYPE_NOTIFIED:
-          xml_printf (file, " scope=\"notified\"");
-          break;
-        }
-
-      if (g_arg_info_get_closure (arg) >= 0)
-        xml_printf (file, " closure=\"%d\"", g_arg_info_get_closure (arg));
-
-      if (g_arg_info_get_destroy (arg) >= 0)
-        xml_printf (file, " destroy=\"%d\"", g_arg_info_get_destroy (arg));
-
-      type = g_arg_info_get_type (arg);
-      write_type_info (namespace, type, file);
-
-      xml_end_element (file, "parameter");
-
-      g_base_info_unref ((GIBaseInfo *)arg);
-    }
-
-  xml_end_element (file, "parameters");
-  g_base_info_unref ((GIBaseInfo *)type);
-}
-
-static void
-write_function_info (const gchar    *namespace,
-		     GIFunctionInfo *info,
-		     Xml            *file)
-{
-  GIFunctionInfoFlags flags;
-  const gchar *tag;
-  const gchar *name;
-  const gchar *symbol;
-  gboolean deprecated;
-  gboolean throws;
-
-  flags = g_function_info_get_flags (info);
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  symbol = g_function_info_get_symbol (info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-  throws = flags & GI_FUNCTION_THROWS;
-
-  if (flags & GI_FUNCTION_IS_CONSTRUCTOR)
-    tag = "constructor";
-  else if (flags & GI_FUNCTION_IS_METHOD)
-    tag = "method";
-  else
-    tag = "function";
-
-  xml_start_element (file, tag);
-  xml_printf (file, " name=\"%s\" c:identifier=\"%s\"",
-              name, symbol);
-
-  if (flags & GI_FUNCTION_IS_SETTER)
-    xml_printf (file, " type=\"setter\"");
-  else if (flags & GI_FUNCTION_IS_GETTER)
-    xml_printf (file, " type=\"getter\"");
-
-  if (deprecated)
-    xml_printf (file, " deprecated=\"1\"");
-
-  if (throws)
-    xml_printf (file, " throws=\"1\"");
-
-  write_callable_info (namespace, (GICallableInfo*)info, file);
-  xml_end_element (file, tag);
-}
-
-static void
-write_callback_info (const gchar    *namespace,
-		     GICallbackInfo *info,
-		     Xml            *file)
-{
-  const gchar *name;
-  gboolean deprecated;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-
-  xml_start_element (file, "callback");
-  xml_printf (file, " name=\"%s\"", name);
-
-  if (deprecated)
-    xml_printf (file, " deprecated=\"1\"");
-
-  write_callable_info (namespace, (GICallableInfo*)info, file);
-  xml_end_element (file, "callback");
-}
-
-static void
-write_struct_info (const gchar  *namespace,
-		   GIStructInfo *info,
-		   Xml          *file)
-{
-  const gchar *name;
-  const gchar *type_name;
-  const gchar *type_init;
-  gboolean deprecated;
-  gboolean is_gtype_struct;
-  gboolean foreign;
-  gint i;
-  gint size;
-  int n_elts;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-
-  type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
-  type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
-
-  if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_BOXED)
-    {
-      xml_start_element (file, "glib:boxed");
-      xml_printf (file, " glib:name=\"%s\"", name);
-    }
-  else
-    {
-      xml_start_element (file, "record");
-      xml_printf (file, " name=\"%s\"", name);
-    }
-
-  if (type_name != NULL)
-    xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
-
-  if (deprecated)
-    xml_printf (file, " deprecated=\"1\"");
-
-  is_gtype_struct = g_struct_info_is_gtype_struct (info);
-  if (is_gtype_struct)
-    xml_printf (file, " glib:is-gtype-struct=\"1\"");
-
-  write_attributes (file, (GIBaseInfo*) info);
-
-  size = g_struct_info_get_size (info);
-  if (file->show_all && size >= 0)
-    xml_printf (file, " size=\"%d\"", size);
-
-  foreign = g_struct_info_is_foreign (info);
-  if (foreign)
-    xml_printf (file, " foreign=\"1\"");
-
-  n_elts = g_struct_info_get_n_fields (info) + g_struct_info_get_n_methods (info);
-  if (n_elts > 0)
-    {
-      for (i = 0; i < g_struct_info_get_n_fields (info); i++)
-	{
-	  GIFieldInfo *field = g_struct_info_get_field (info, i);
-	  write_field_info (namespace, field, NULL, file);
-	  g_base_info_unref ((GIBaseInfo *)field);
-	}
-
-      for (i = 0; i < g_struct_info_get_n_methods (info); i++)
-	{
-	  GIFunctionInfo *function = g_struct_info_get_method (info, i);
-	  write_function_info (namespace, function, file);
-	  g_base_info_unref ((GIBaseInfo *)function);
-	}
-
-    }
-
-  xml_end_element_unchecked (file);
-}
-
-static void
-write_value_info (const gchar *namespace,
-		  GIValueInfo *info,
-		  Xml         *file)
-{
-  const gchar *name;
-  glong value;
-  gboolean deprecated;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  value = g_value_info_get_value (info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-
-  xml_start_element (file, "member");
-  xml_printf (file, " name=\"%s\" value=\"%ld\"", name, value);
-
-  if (deprecated)
-    xml_printf (file, " deprecated=\"1\"");
-
-  write_attributes (file, (GIBaseInfo*) info);
-
-  xml_end_element (file, "member");
-}
-
-static void
-write_constant_value (const gchar *namespace,
-		      GITypeInfo *type,
-		      GArgument  *value,
-		      Xml        *file)
-{
-  switch (g_type_info_get_tag (type))
-    {
-    case GI_TYPE_TAG_BOOLEAN:
-      xml_printf (file, "%d", value->v_boolean);
-      break;
-    case GI_TYPE_TAG_INT8:
-      xml_printf (file, "%d", value->v_int8);
-      break;
-    case GI_TYPE_TAG_UINT8:
-      xml_printf (file, "%d", value->v_uint8);
-      break;
-    case GI_TYPE_TAG_INT16:
-      xml_printf (file, "%" G_GINT16_FORMAT, value->v_int16);
-      break;
-    case GI_TYPE_TAG_UINT16:
-      xml_printf (file, "%" G_GUINT16_FORMAT, value->v_uint16);
-      break;
-    case GI_TYPE_TAG_INT32:
-      xml_printf (file, "%" G_GINT32_FORMAT, value->v_int32);
-      break;
-    case GI_TYPE_TAG_UINT32:
-      xml_printf (file, "%" G_GUINT32_FORMAT, value->v_uint32);
-      break;
-    case GI_TYPE_TAG_INT64:
-      xml_printf (file, "%" G_GINT64_FORMAT, value->v_int64);
-      break;
-    case GI_TYPE_TAG_UINT64:
-      xml_printf (file, "%" G_GUINT64_FORMAT, value->v_uint64);
-      break;
-    case GI_TYPE_TAG_INT:
-      xml_printf (file, "%d", value->v_int);
-      break;
-    case GI_TYPE_TAG_UINT:
-      xml_printf (file, "%d", value->v_uint);
-      break;
-    case GI_TYPE_TAG_LONG:
-      xml_printf (file, "%ld", value->v_long);
-      break;
-    case GI_TYPE_TAG_ULONG:
-      xml_printf (file, "%ld", value->v_ulong);
-      break;
-    case GI_TYPE_TAG_SSIZE:
-      xml_printf (file, "%zd", value->v_ssize);
-      break;
-    case GI_TYPE_TAG_SIZE:
-      xml_printf (file, "%zd", value->v_size);
-      break;
-    case GI_TYPE_TAG_FLOAT:
-      xml_printf (file, "%f", value->v_float);
-      break;
-    case GI_TYPE_TAG_DOUBLE:
-      xml_printf (file, "%f", value->v_double);
-      break;
-    case GI_TYPE_TAG_UTF8:
-    case GI_TYPE_TAG_FILENAME:
-      xml_printf (file, "%s", value->v_string);
-      break;
-    default:
-      g_assert_not_reached ();
-    }
-}
-
-static void
-write_constant_info (const gchar    *namespace,
-		     GIConstantInfo *info,
-		     Xml            *file)
-{
-  GITypeInfo *type;
-  const gchar *name;
-  gboolean deprecated;
-  GArgument value;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-
-  xml_start_element (file, "constant");
-  xml_printf (file, " name=\"%s\"", name);
-
-  type = g_constant_info_get_type (info);
-  xml_printf (file, " value=\"");
-
-  g_constant_info_get_value (info, &value);
-  write_constant_value (namespace, type, &value, file);
-  xml_printf (file, "\"");
-
-  write_type_info (namespace, type, file);
-
-  write_attributes (file, (GIBaseInfo*) info);
-
-  xml_end_element (file, "constant");
-
-  g_base_info_unref ((GIBaseInfo *)type);
-}
-
-
-static void
-write_enum_info (const gchar *namespace,
-		 GIEnumInfo *info,
-		 Xml         *file)
-{
-  const gchar *name;
-  const gchar *type_name;
-  const gchar *type_init;
-  gboolean deprecated;
-  gint i;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-
-  type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
-  type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
-
-  if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM)
-    xml_start_element (file, "enumeration");
-  else
-    xml_start_element (file, "bitfield");
-  xml_printf (file, " name=\"%s\"", name);
-
-  if (type_init)
-    xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
-
-  if (deprecated)
-    xml_printf (file, " deprecated=\"1\"");
-
-  write_attributes (file, (GIBaseInfo*) info);
-
-  for (i = 0; i < g_enum_info_get_n_values (info); i++)
-    {
-      GIValueInfo *value = g_enum_info_get_value (info, i);
-      write_value_info (namespace, value, file);
-      g_base_info_unref ((GIBaseInfo *)value);
-    }
-
-  xml_end_element_unchecked (file);
-}
-
-static void
-write_signal_info (const gchar  *namespace,
-		   GISignalInfo *info,
-		   Xml          *file)
-{
-  GSignalFlags flags;
-  const gchar *name;
-  gboolean deprecated;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  flags = g_signal_info_get_flags (info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-
-  xml_start_element (file, "glib:signal");
-  xml_printf (file, " name=\"%s\"", name);
-
-  if (deprecated)
-    xml_printf (file, " deprecated=\"1\"");
-
-  if (flags & G_SIGNAL_RUN_FIRST)
-    xml_printf (file, " when=\"FIRST\"");
-  else if (flags & G_SIGNAL_RUN_LAST)
-    xml_printf (file, " when=\"LAST\"");
-  else if (flags & G_SIGNAL_RUN_CLEANUP)
-    xml_printf (file, " when=\"CLEANUP\"");
-
-  if (flags & G_SIGNAL_NO_RECURSE)
-    xml_printf (file, " no-recurse=\"1\"");
-
-  if (flags & G_SIGNAL_DETAILED)
-    xml_printf (file, " detailed=\"1\"");
-
-  if (flags & G_SIGNAL_ACTION)
-    xml_printf (file, " action=\"1\"");
-
-  if (flags & G_SIGNAL_NO_HOOKS)
-    xml_printf (file, " no-hooks=\"1\"");
-
-  write_callable_info (namespace, (GICallableInfo*)info, file);
-
-  xml_end_element (file, "glib:signal");
-}
-
-static void
-write_vfunc_info (const gchar *namespace,
-		  GIVFuncInfo *info,
-		  Xml         *file)
-{
-  GIVFuncInfoFlags flags;
-  const gchar *name;
-  GIFunctionInfo *invoker;
-  gboolean deprecated;
-  gint offset;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  flags = g_vfunc_info_get_flags (info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-  offset = g_vfunc_info_get_offset (info);
-  invoker = g_vfunc_info_get_invoker (info);
-
-  xml_start_element (file, "virtual-method");
-  xml_printf (file, " name=\"%s\"", name);
-
-  if (deprecated)
-    xml_printf (file, " deprecated=\"1\"");
-
-  if (flags & GI_VFUNC_MUST_CHAIN_UP)
-    xml_printf (file, " must-chain-up=\"1\"");
-
-  if (flags & GI_VFUNC_MUST_OVERRIDE)
-    xml_printf (file, " override=\"always\"");
-  else if (flags & GI_VFUNC_MUST_NOT_OVERRIDE)
-    xml_printf (file, " override=\"never\"");
-
-  xml_printf (file, " offset=\"%d\"", offset);
-
-  if (invoker)
-    xml_printf (file, " invoker=\"%s\"", g_base_info_get_name ((GIBaseInfo*)invoker));
-
-  write_callable_info (namespace, (GICallableInfo*)info, file);
-
-  xml_end_element (file, "virtual-method");
-}
-
-static void
-write_property_info (const gchar    *namespace,
-		     GIPropertyInfo *info,
-		     Xml            *file)
-{
-  GParamFlags flags;
-  const gchar *name;
-  gboolean deprecated;
-  GITypeInfo *type;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  flags = g_property_info_get_flags (info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-
-  xml_start_element (file, "property");
-  xml_printf (file, " name=\"%s\"", name);
-
-  if (deprecated)
-    xml_printf (file, " deprecated=\"1\"");
-
-  /* Properties are assumed to be read-only (see also girwriter.py) */
-  if (!(flags & G_PARAM_READABLE))
-    xml_printf (file, " readable=\"0\"");
-  if (flags & G_PARAM_WRITABLE)
-    xml_printf (file, " writable=\"1\"");
-
-  if (flags & G_PARAM_CONSTRUCT)
-    xml_printf (file, " construct=\"1\"");
-
-  if (flags & G_PARAM_CONSTRUCT_ONLY)
-    xml_printf (file, " construct-only=\"1\"");
-
-  write_attributes (file, (GIBaseInfo*) info);
-
-  type = g_property_info_get_type (info);
-
-  write_type_info (namespace, type, file);
-
-  xml_end_element (file, "property");
-}
-
-static void
-write_object_info (const gchar  *namespace,
-		   GIObjectInfo *info,
-		   Xml          *file)
-{
-  const gchar *name;
-  const gchar *type_name;
-  const gchar *type_init;
-  gboolean deprecated;
-  gboolean is_abstract;
-  GIObjectInfo *pnode;
-  GIStructInfo *class_struct;
-  gint i;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-  is_abstract = g_object_info_get_abstract (info);
-
-  type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
-  type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
-  xml_start_element (file, "class");
-  xml_printf (file, " name=\"%s\"", name);
-
-  pnode = g_object_info_get_parent (info);
-  if (pnode)
-    {
-      write_type_name_attribute (namespace, (GIBaseInfo *)pnode, "parent", file);
-      g_base_info_unref ((GIBaseInfo *)pnode);
-    }
-
-  class_struct = g_object_info_get_class_struct (info);
-  if (class_struct)
-    {
-      write_type_name_attribute (namespace, (GIBaseInfo*) class_struct, "glib:type-struct", file);
-      g_base_info_unref ((GIBaseInfo*)class_struct);
-    }
-
-  if (is_abstract)
-    xml_printf (file, " abstract=\"1\"");
-
-  xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
-
-  if (deprecated)
-    xml_printf (file, " deprecated=\"1\"");
-
-  write_attributes (file, (GIBaseInfo*) info);
-
-  if (g_object_info_get_n_interfaces (info) > 0)
-    {
-      for (i = 0; i < g_object_info_get_n_interfaces (info); i++)
-	{
-	  GIInterfaceInfo *imp = g_object_info_get_interface (info, i);
-          xml_start_element (file, "implements");
-	  write_type_name_attribute (namespace, (GIBaseInfo *)imp, "name", file);
-          xml_end_element (file, "implements");
-	  g_base_info_unref ((GIBaseInfo*)imp);
-	}
-    }
-
-  for (i = 0; i < g_object_info_get_n_fields (info); i++)
-    {
-      GIFieldInfo *field = g_object_info_get_field (info, i);
-      write_field_info (namespace, field, NULL, file);
-      g_base_info_unref ((GIBaseInfo *)field);
-    }
-
-  for (i = 0; i < g_object_info_get_n_methods (info); i++)
-    {
-      GIFunctionInfo *function = g_object_info_get_method (info, i);
-      write_function_info (namespace, function, file);
-      g_base_info_unref ((GIBaseInfo *)function);
-    }
-
-  for (i = 0; i < g_object_info_get_n_properties (info); i++)
-    {
-      GIPropertyInfo *prop = g_object_info_get_property (info, i);
-      write_property_info (namespace, prop, file);
-      g_base_info_unref ((GIBaseInfo *)prop);
-    }
-
-  for (i = 0; i < g_object_info_get_n_signals (info); i++)
-    {
-      GISignalInfo *signal = g_object_info_get_signal (info, i);
-      write_signal_info (namespace, signal, file);
-      g_base_info_unref ((GIBaseInfo *)signal);
-    }
-
-  for (i = 0; i < g_object_info_get_n_vfuncs (info); i++)
-    {
-      GIVFuncInfo *vfunc = g_object_info_get_vfunc (info, i);
-      write_vfunc_info (namespace, vfunc, file);
-      g_base_info_unref ((GIBaseInfo *)vfunc);
-    }
-
-  for (i = 0; i < g_object_info_get_n_constants (info); i++)
-    {
-      GIConstantInfo *constant = g_object_info_get_constant (info, i);
-      write_constant_info (namespace, constant, file);
-      g_base_info_unref ((GIBaseInfo *)constant);
-    }
-
-  xml_end_element (file, "class");
-}
-
-static void
-write_interface_info (const gchar     *namespace,
-		      GIInterfaceInfo *info,
-		      Xml             *file)
-{
-  const gchar *name;
-  const gchar *type_name;
-  const gchar *type_init;
-  GIStructInfo *class_struct;
-  gboolean deprecated;
-  gint i;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-
-  type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
-  type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
-  xml_start_element (file, "interface");
-  xml_printf (file, " name=\"%s\" glib:type-name=\"%s\" glib:get-type=\"%s\"",
-	     name, type_name, type_init);
-
-  class_struct = g_interface_info_get_iface_struct (info);
-  if (class_struct)
-    {
-      write_type_name_attribute (namespace, (GIBaseInfo*) class_struct, "glib:type-struct", file);
-      g_base_info_unref ((GIBaseInfo*)class_struct);
-    }
-
-  if (deprecated)
-    xml_printf (file, " deprecated=\"1\"");
-
-  write_attributes (file, (GIBaseInfo*) info);
-
-  if (g_interface_info_get_n_prerequisites (info) > 0)
-    {
-      for (i = 0; i < g_interface_info_get_n_prerequisites (info); i++)
-	{
-	  GIBaseInfo *req = g_interface_info_get_prerequisite (info, i);
-
-	  xml_start_element (file, "prerequisite");
-	  write_type_name_attribute (namespace, req, "name", file);
-
-          xml_end_element_unchecked (file);
-	  g_base_info_unref (req);
-	}
-    }
-
-  for (i = 0; i < g_interface_info_get_n_methods (info); i++)
-    {
-      GIFunctionInfo *function = g_interface_info_get_method (info, i);
-      write_function_info (namespace, function, file);
-      g_base_info_unref ((GIBaseInfo *)function);
-    }
-
-  for (i = 0; i < g_interface_info_get_n_properties (info); i++)
-    {
-      GIPropertyInfo *prop = g_interface_info_get_property (info, i);
-      write_property_info (namespace, prop, file);
-      g_base_info_unref ((GIBaseInfo *)prop);
-    }
-
-  for (i = 0; i < g_interface_info_get_n_signals (info); i++)
-    {
-      GISignalInfo *signal = g_interface_info_get_signal (info, i);
-      write_signal_info (namespace, signal, file);
-      g_base_info_unref ((GIBaseInfo *)signal);
-    }
-
-  for (i = 0; i < g_interface_info_get_n_vfuncs (info); i++)
-    {
-      GIVFuncInfo *vfunc = g_interface_info_get_vfunc (info, i);
-      write_vfunc_info (namespace, vfunc, file);
-      g_base_info_unref ((GIBaseInfo *)vfunc);
-    }
-
-  for (i = 0; i < g_interface_info_get_n_constants (info); i++)
-    {
-      GIConstantInfo *constant = g_interface_info_get_constant (info, i);
-      write_constant_info (namespace, constant, file);
-      g_base_info_unref ((GIBaseInfo *)constant);
-    }
-
-  xml_end_element (file, "interface");
-}
-
-static void
-write_error_domain_info (const gchar       *namespace,
-			 GIErrorDomainInfo *info,
-			 Xml               *file)
-{
-  GIBaseInfo *enum_;
-  const gchar *name, *quark;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  quark = g_error_domain_info_get_quark (info);
-  enum_ = (GIBaseInfo *)g_error_domain_info_get_codes (info);
-  xml_start_element (file, "errordomain");
-  xml_printf (file, " name=\"%s\" get-quark=\"%s\"",
-              name, quark);
-  write_type_name_attribute (namespace, enum_, "codes", file);
-  xml_end_element (file, "errordomain");
-  g_base_info_unref (enum_);
-}
-
-static void
-write_union_info (const gchar *namespace,
-		  GIUnionInfo *info,
-		  Xml         *file)
-{
-  const gchar *name;
-  const gchar *type_name;
-  const gchar *type_init;
-  gboolean deprecated;
-  gint i;
-  gint size;
-
-  name = g_base_info_get_name ((GIBaseInfo *)info);
-  deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
-
-  type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
-  type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
-
-  xml_start_element (file, "union");
-  xml_printf (file, " name=\"%s\"", name);
-
-  if (type_name)
-    xml_printf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
-
-  if (deprecated)
-    xml_printf (file, " deprecated=\"1\"");
-
-  size = g_union_info_get_size (info);
-  if (file->show_all && size >= 0)
-    xml_printf (file, " size=\"%d\"", size);
-
-  write_attributes (file, (GIBaseInfo*) info);
-
-  if (g_union_info_is_discriminated (info))
-    {
-      gint offset;
-      GITypeInfo *type;
-
-      offset = g_union_info_get_discriminator_offset (info);
-      type = g_union_info_get_discriminator_type (info);
-
-      xml_start_element (file, "discriminator");
-      xml_printf (file, " offset=\"%d\" type=\"", offset);
-      write_type_info (namespace, type, file);
-      xml_end_element (file, "discriminator");
-      g_base_info_unref ((GIBaseInfo *)type);
-    }
-
-  for (i = 0; i < g_union_info_get_n_fields (info); i++)
-    {
-      GIFieldInfo *field = g_union_info_get_field (info, i);
-      GIConstantInfo *constant = g_union_info_get_discriminator (info, i);
-      write_field_info (namespace, field, constant, file);
-      g_base_info_unref ((GIBaseInfo *)field);
-      if (constant)
-	g_base_info_unref ((GIBaseInfo *)constant);
-    }
-
-  for (i = 0; i < g_union_info_get_n_methods (info); i++)
-    {
-      GIFunctionInfo *function = g_union_info_get_method (info, i);
-      write_function_info (namespace, function, file);
-      g_base_info_unref ((GIBaseInfo *)function);
-    }
-
-  xml_end_element (file, "union");
-}
-
-static void
-write_repository (const char *filename,
-		  const char *namespace,
-		  gboolean    needs_prefix,
-		  gboolean    show_all)
-{
-  FILE *ofile;
-  gint i, j;
-  char **dependencies;
-  GIRepository *repository;
-  Xml *xml;
-
-  repository = g_irepository_get_default ();
-
-  if (filename == NULL)
-    ofile = stdout;
-  else
-    {
-      gchar *full_filename;
-
-      if (needs_prefix)
-	full_filename = g_strdup_printf ("%s-%s", namespace, filename);
-      else
-	full_filename = g_strdup (filename);
-      ofile = g_fopen (filename, "w");
-
-      if (ofile == NULL)
-	{
-	  g_fprintf (stderr, "failed to open '%s': %s\n",
-		     full_filename, g_strerror (errno));
-	  g_free (full_filename);
-
-	  return;
-	}
-
-      g_free (full_filename);
-    }
-
-  xml = xml_open (ofile);
-  xml->show_all = show_all;
-  xml_printf (xml, "<?xml version=\"1.0\"?>\n");
-  xml_start_element (xml, "repository");
-  xml_printf (xml, " version=\"1.0\"\n"
-	      "            xmlns=\"http://www.gtk.org/introspection/core/1.0\"\n";
-	      "            xmlns:c=\"http://www.gtk.org/introspection/c/1.0\"\n";
-	      "            xmlns:glib=\"http://www.gtk.org/introspection/glib/1.0\"";);
-
-  dependencies = g_irepository_get_dependencies (repository,
-						 namespace);
-  if (dependencies != NULL)
-    {
-      for (i = 0; dependencies[i]; i++)
-	{
-	  char **parts = g_strsplit (dependencies[i], "-", 2);
-	  xml_start_element (xml, "include");
-	  xml_printf (xml, " name=\"%s\" version=\"%s\"", parts[0], parts[1]);
-	  xml_end_element (xml, "include");
-	  g_strfreev (parts);
-	}
-    }
-
-  if (TRUE)
-    {
-      const gchar *shared_library;
-      const gchar *c_prefix;
-      const char *ns = namespace;
-      const char *version;
-
-      version = g_irepository_get_version (repository, ns);
-
-      shared_library = g_irepository_get_shared_library (repository, ns);
-      c_prefix = g_irepository_get_c_prefix (repository, ns);
-      xml_start_element (xml, "namespace");
-      xml_printf (xml, " name=\"%s\" version=\"%s\"", ns, version);
-      if (shared_library)
-        xml_printf (xml, " shared-library=\"%s\"", shared_library);
-      if (c_prefix)
-        xml_printf (xml, " c:prefix=\"%s\"", c_prefix);
-
-      for (j = 0; j < g_irepository_get_n_infos (repository, ns); j++)
-	{
-	  GIBaseInfo *info = g_irepository_get_info (repository, ns, j);
-	  switch (g_base_info_get_type (info))
-	    {
-	    case GI_INFO_TYPE_FUNCTION:
-	      write_function_info (ns, (GIFunctionInfo *)info, xml);
-	      break;
-
-	    case GI_INFO_TYPE_CALLBACK:
-	      write_callback_info (ns, (GICallbackInfo *)info, xml);
-	      break;
-
-	    case GI_INFO_TYPE_STRUCT:
-	    case GI_INFO_TYPE_BOXED:
-	      write_struct_info (ns, (GIStructInfo *)info, xml);
-	      break;
-
-	    case GI_INFO_TYPE_UNION:
-	      write_union_info (ns, (GIUnionInfo *)info, xml);
-	      break;
-
-	    case GI_INFO_TYPE_ENUM:
-	    case GI_INFO_TYPE_FLAGS:
-	      write_enum_info (ns, (GIEnumInfo *)info, xml);
-	      break;
-
-	    case GI_INFO_TYPE_CONSTANT:
-	      write_constant_info (ns, (GIConstantInfo *)info, xml);
-	      break;
-
-	    case GI_INFO_TYPE_OBJECT:
-	      write_object_info (ns, (GIObjectInfo *)info, xml);
-	      break;
-
-	    case GI_INFO_TYPE_INTERFACE:
-	      write_interface_info (ns, (GIInterfaceInfo *)info, xml);
-	      break;
-
-	    case GI_INFO_TYPE_ERROR_DOMAIN:
-	      write_error_domain_info (ns, (GIErrorDomainInfo *)info, xml);
-	      break;
-
-	    default:
-	      g_error ("unknown info type %d\n", g_base_info_get_type (info));
-	    }
-
-	  g_base_info_unref (info);
-	}
-
-      xml_end_element (xml, "namespace");
-    }
-
-  xml_end_element (xml, "repository");
-
-  xml_free (xml);
-}
-
 static const guchar *
 load_typelib (const gchar  *filename,
-	       GModule     **dlhandle,
-               gsize        *len)
+	      GModule     **dlhandle,
+	      gsize        *len)
 {
   guchar *typelib;
   gsize *typelib_size;
@@ -1521,7 +162,7 @@ main (int argc, char *argv[])
 	  return 1;
 	}
 
-      write_repository (output, namespace, needs_prefix, show_all);
+      gir_writer_write (output, namespace, needs_prefix, show_all);
 
       if (dlhandle)
 	{



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