Remove trailing whitespace
[gnome.gobject-introspection] / tools / generate.c
index 0a3c3a5..2292de0 100644 (file)
@@ -1,7 +1,9 @@
+
 /* -*- 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
@@ -20,7 +22,6 @@
  */
 
 #include <errno.h>
-#include <dlfcn.h>
 #include <string.h>
 
 #include <glib.h>
 #include <glib/gstdio.h>
 
 #include "girepository.h"
-#include "gmetadata.h"
+#include "gtypelib.h"
+
+/* FIXME: Avoid global */
+static gchar *output = NULL;
+gchar **includedirs = NULL;
+static gboolean show_all = FALSE;
+
+typedef struct {
+  FILE *file;
+  GSList *stack;
+} 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);
+}
 
-gboolean raw = FALSE;
-gchar **input = NULL;
-gchar *output = NULL;
+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");
 
-static void 
+      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,
-                FILE        *file)
+                Xml         *file)
 {
   if (strcmp (namespace, g_base_info_get_namespace (info)) != 0)
-    g_fprintf (file, "%s.", g_base_info_get_namespace (info));
+    xml_printf (file, "%s.", g_base_info_get_namespace (info));
 
-  g_fprintf (file, "%s", g_base_info_get_name (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, 
-                FILE        *file)
+                GITypeInfo  *info,
+                Xml         *file)
 {
   gint tag;
   gint i;
   GITypeInfo *type;
-  
-  const gchar* basic[] = {
-    "void", 
-    "gboolean", 
-    "gint8", 
-    "guint8", 
-    "gint16", 
-    "guint16", 
-    "gint32", 
-    "guint32", 
-    "gint64", 
-    "guint64", 
-    "gint",
-    "guint",
-    "glong",
-    "gulong",
-    "gssize",
-    "gsize",
-    "gfloat", 
-    "gdouble", 
-    "utf8",
-    "filename"
-  };
+  gboolean is_pointer;
+
+  check_unresolved ((GIBaseInfo*)info);
 
   tag = g_type_info_get_tag (info);
+  is_pointer = g_type_info_is_pointer (info);
 
-  if (tag < TYPE_TAG_UTF8)
-    g_fprintf (file, "%s%s", basic[tag], g_type_info_is_pointer (info) ? "*" : "");
-  else if (tag <= TYPE_TAG_FILENAME)
-    g_fprintf (file, "%s", basic[tag]);
-  else if (tag == TYPE_TAG_ARRAY)
+  if (tag == GI_TYPE_TAG_VOID)
     {
-      gint length;
+      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;
+
+      xml_start_element (file, "array");
 
       type = g_type_info_get_param_type (info, 0);
-      write_type_info (namespace, type, file);
-      g_fprintf (file, "["); 
 
       length = g_type_info_get_array_length (info);
-      
       if (length >= 0)
-       g_fprintf (file, "length=%d", length);
-      
+        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))
-       g_fprintf (file, "%szero-terminated=1", length >= 0 ? "," : "");
-      
-     g_fprintf (file, "]"); 
+       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 == TYPE_TAG_SYMBOL)
+  else if (tag == GI_TYPE_TAG_INTERFACE)
     {
       GIBaseInfo *iface = g_type_info_get_interface (info);
-      write_type_name (namespace, iface, file);
-      if (g_type_info_is_pointer (info))
-       g_fprintf (file, "*"); 
+      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 == TYPE_TAG_LIST)
+  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);
-      g_fprintf (file, "GList");
       if (type)
        {
-         g_fprintf (file, "<"); 
          write_type_info (namespace, type, file);
-         g_fprintf (file, ">"); 
          g_base_info_unref ((GIBaseInfo *)type);
        }
-      g_fprintf (file, "*");
+      xml_end_element (file, "type");
     }
-  else if (tag == TYPE_TAG_SLIST)
+  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);
-      g_fprintf (file, "GSList");
       if (type)
        {
-         g_fprintf (file, "<"); 
          write_type_info (namespace, type, file);
-         g_fprintf (file, ">"); 
          g_base_info_unref ((GIBaseInfo *)type);
        }
-      g_fprintf (file, "*");
+      xml_end_element (file, "type");
     }
-  else if (tag == TYPE_TAG_HASH)
+  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);
-      g_fprintf (file, "GHashTable");
       if (type)
        {
-         g_fprintf (file, "<"); 
          write_type_info (namespace, type, file);
          g_base_info_unref ((GIBaseInfo *)type);
          type = g_type_info_get_param_type (info, 1);
-         g_fprintf (file, ",");
          write_type_info (namespace, type, file);
-         g_fprintf (file, ">"); 
          g_base_info_unref ((GIBaseInfo *)type);
        }
-      g_fprintf (file, "*");
+      xml_end_element (file, "type");
     }
-  else if (tag == TYPE_TAG_ERROR)
+  else if (tag == GI_TYPE_TAG_ERROR)
     {
       gint n;
 
-      g_fprintf (file, "GError");
+      xml_start_element (file, "type");
+      xml_printf (file, " name=\"GLib.Error\"");
+
       n = g_type_info_get_n_error_domains (info);
       if (n > 0)
        {
-         g_fprintf (file, "<"); 
          for (i = 0; i < n; i++)
            {
              GIErrorDomainInfo *ed = g_type_info_get_error_domain (info, i);
-             if (i > 0)
-               g_fprintf (file, ",");
-             write_type_name (namespace, (GIBaseInfo *)ed, file);
+             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);
            }
-         g_fprintf (file, ">");
        }
-      g_fprintf (file, "*");
+
+      xml_end_element (file, "type");
+    }
+  else
+    {
+      g_printerr ("Unhandled type tag %d\n", tag);
+      g_assert_not_reached ();
     }
 }
 
 static void
-write_constant_value (const gchar *namespace, 
+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,
-                     FILE *file);
+                     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,
-                 FILE        *file)
+                 Xml         *file)
 {
   const gchar *name;
   GIFieldInfoFlags flags;
   gint size;
   gint offset;
   GITypeInfo *type;
-  GArgument value; 
+  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);
 
-  g_fprintf (file, 
-            "      <field name=\"%s\" readable=\"%s\" writable=\"%s\" ",
-            name, 
-            flags & GI_FIELD_IS_READABLE ? "1" : "0", 
-            flags & GI_FIELD_IS_WRITABLE ? "1" : "0");
+  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)
-    g_fprintf (file, "bits=\"%d\" ", size);
-  g_fprintf (file, "offset=\"%d\" ", offset);
+    xml_printf (file, " bits=\"%d\"", size);
 
-  g_fprintf (file, "type=\"");
+  write_attributes (file, (GIBaseInfo*) info);
 
   type = g_field_info_get_type (info);
-  write_type_info (namespace, type, file);
-  g_base_info_unref ((GIBaseInfo *)type);
-
-  g_fprintf (file, "\"");
 
   if (branch)
     {
-      g_fprintf (file, " 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);
-      g_fprintf (file, "\"");
+      xml_printf (file, "\"");
     }
 
-  g_fprintf (file," />\n");
+  if (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 
+static void
 write_callable_info (const gchar    *namespace,
                     GICallableInfo *info,
-                    FILE           *file,
-                    gint            indent)
+                    Xml            *file)
 {
   GITypeInfo *type;
   gint i;
 
-  g_fprintf (file, "%*s  <return-type type=\"", indent, "");
-  
+  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);
 
-  g_fprintf (file, "\"");
+  xml_end_element (file, "return-value");
+
+  if (g_callable_info_get_n_args (info) <= 0)
+    return;
 
-  if (g_type_info_is_pointer (type))
+  xml_start_element (file, "parameters");
+  for (i = 0; i < g_callable_info_get_n_args (info); i++)
     {
-      switch (g_callable_info_get_caller_owns (info))
+      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:
-         g_fprintf (file, " transfer=\"none\"");
+         xml_printf (file, " transfer-ownership=\"none\"");
          break;
        case GI_TRANSFER_CONTAINER:
-         g_fprintf (file, " transfer=\"shallow\"");
+         xml_printf (file, " transfer-ownership=\"container\"");
          break;
        case GI_TRANSFER_EVERYTHING:
-         g_fprintf (file, " transfer=\"full\"");
+         xml_printf (file, " transfer-ownership=\"full\"");
          break;
        default:
          g_assert_not_reached ();
        }
-    }
-  g_base_info_unref ((GIBaseInfo *)type);
-  if (g_callable_info_may_return_null (info))
-    g_fprintf (file, " null-ok=\"1\"");
 
-  g_fprintf (file, " />\n");
-       
-  if (g_callable_info_get_n_args (info) > 0)
-    {
-      g_fprintf (file, "%*s  <parameters>\n", indent, "");
-      for (i = 0; i < g_callable_info_get_n_args (info); i++)
+      switch (g_arg_info_get_direction (arg))
        {
-         GIArgInfo *arg = g_callable_info_get_arg (info, i);
-               
-         g_fprintf (file, "%*s    <parameter name=\"%s\" type=\"",
-                    indent, "", g_base_info_get_name ((GIBaseInfo *) arg));
-               
-         type = g_arg_info_get_type (arg);
-         write_type_info (namespace, type, file);
-         g_fprintf (file, "\"");
+       case GI_DIRECTION_IN:
+         break;
+       case GI_DIRECTION_OUT:
+         xml_printf (file, " direction=\"out\"");
+         break;
+       case GI_DIRECTION_INOUT:
+         xml_printf (file, " direction=\"inout\"");
+         break;
+       }
 
-         if (g_type_info_is_pointer (type))
-           {
-             switch (g_arg_info_get_ownership_transfer (arg))
-               {
-               case GI_TRANSFER_NOTHING:
-                 g_fprintf (file, " transfer=\"none\"");
-                 break;
-               case GI_TRANSFER_CONTAINER:
-                 g_fprintf (file, " transfer=\"shallow\"");
-                 break;
-               case GI_TRANSFER_EVERYTHING:
-                 g_fprintf (file, " transfer=\"full\"");
-                 break;
-               default:
-                 g_assert_not_reached ();
-               }
-           }         
-         g_base_info_unref ((GIBaseInfo *)type);
+      if (g_arg_info_may_be_null (arg))
+       xml_printf (file, " allow-none=\"1\"");
+
+      if (g_arg_info_is_dipper (arg))
+       xml_printf (file, " dipper=\"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;
+        }
 
-         g_fprintf (file, " direction=\"");
-         switch (g_arg_info_get_direction (arg))
-           {
-           case GI_DIRECTION_IN:
-             g_fprintf (file, "in");
-             break;
-           case GI_DIRECTION_OUT:
-             g_fprintf (file, "out");
-             break;
-           case GI_DIRECTION_INOUT:
-             g_fprintf (file, "inout");
-             break;
-           }
-         g_fprintf (file, "\"");
-
-         if (g_arg_info_may_be_null (arg))
-           g_fprintf (file, " null-ok=\"1\"");
-         
-         if (g_arg_info_is_dipper (arg))
-           g_fprintf (file, " dipper=\"1\"");
-         
-         if (g_arg_info_is_return_value (arg))
-           g_fprintf (file, " retval=\"1\"");
-         
-         if (g_arg_info_is_optional (arg))
-           g_fprintf (file, " optional=\"1\"");
-         
-         g_fprintf (file, " />\n");
-                
-         g_base_info_unref ((GIBaseInfo *)arg);
-       }
-           
-      g_fprintf (file, "%*s  </parameters>\n", indent, "");
+      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,
-                    FILE           *file,
-                    gint            indent)
+                    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";
@@ -360,28 +555,30 @@ write_function_info (const gchar    *namespace,
     tag = "method";
   else
     tag = "function";
-       
-  g_fprintf (file, "%*s<%s name=\"%s\" symbol=\"%s\"", 
-            indent, "", tag, name, symbol);
-       
+
+  xml_start_element (file, tag);
+  xml_printf (file, " name=\"%s\" c:identifier=\"%s\"",
+              name, symbol);
+
   if (flags & GI_FUNCTION_IS_SETTER)
-    g_fprintf (file, " type=\"setter\"");
+    xml_printf (file, " type=\"setter\"");
   else if (flags & GI_FUNCTION_IS_GETTER)
-    g_fprintf (file, " type=\"getter\"");
-         
+    xml_printf (file, " type=\"getter\"");
+
   if (deprecated)
-    g_fprintf (file, " deprecated=\"1\"");
-       
-  g_fprintf (file, ">\n");
-  write_callable_info (namespace, (GICallableInfo*)info, file, indent);
-  g_fprintf (file, "%*s</%s>\n", indent, "", tag);
+    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,
-                    FILE           *file,
-                    gint            indent)
+                    Xml            *file)
 {
   const gchar *name;
   gboolean deprecated;
@@ -389,69 +586,89 @@ write_callback_info (const gchar    *namespace,
   name = g_base_info_get_name ((GIBaseInfo *)info);
   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
 
-  g_fprintf (file, "%*s<callback name=\"%s\"", indent, "", name);
-       
+  xml_start_element (file, "callback");
+  xml_printf (file, " name=\"%s\"", name);
+
   if (deprecated)
-    g_fprintf (file, " deprecated=\"1\"");
-       
-  g_fprintf (file, ">\n");
-  write_callable_info (namespace, (GICallableInfo*)info, file, indent);
-  g_fprintf (file, "%*s</callback>\n", indent, "");
+    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,
-                  FILE         *file)
+                  Xml          *file)
 {
   const gchar *name;
   const gchar *type_name;
   const gchar *type_init;
   gboolean deprecated;
+  gboolean is_gtype_struct;
   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)
     {
-      type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
-      type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
-           
-      g_fprintf (file, "    <boxed name=\"%s\" type-name=\"%s\" get-type=\"%s\"", name, type_name, type_init);
+      xml_start_element (file, "glib:boxed");
+      xml_printf (file, " glib:name=\"%s\"", name);
     }
   else
-    g_fprintf (file, "    <struct name=\"%s\"", name);
-         
-  if (deprecated)
-    g_fprintf (file, " deprecated=\"1\"");
-       
-  g_fprintf (file, ">\n");
-
-  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);
+      xml_start_element (file, "record");
+      xml_printf (file, " name=\"%s\"", name);
     }
 
-  for (i = 0; i < g_struct_info_get_n_methods (info); i++)
+  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 (show_all && size >= 0)
+    xml_printf (file, " size=\"%d\"", size);
+
+  n_elts = g_struct_info_get_n_fields (info) + g_struct_info_get_n_methods (info);
+  if (n_elts > 0)
     {
-      GIFunctionInfo *function = g_struct_info_get_method (info, i);
-      write_function_info (namespace, function, file, 6);
-      g_base_info_unref ((GIBaseInfo *)function);
+      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);
+       }
+
     }
 
-  if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_BOXED)
-    g_fprintf (file, "    </boxed>\n");
-  else
-    g_fprintf (file, "    </struct>\n");
+  xml_end_element_unchecked (file);
 }
 
 static void
 write_value_info (const gchar *namespace,
                  GIValueInfo *info,
-                 FILE        *file)
+                 Xml         *file)
 {
   const gchar *name;
   glong value;
@@ -461,90 +678,89 @@ write_value_info (const gchar *namespace,
   value = g_value_info_get_value (info);
   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
 
-  g_fprintf (file, "      <member name=\"%s\" value=\"%ld\"", name, value);
+  xml_start_element (file, "member");
+  xml_printf (file, " name=\"%s\" value=\"%ld\"", name, value);
 
   if (deprecated)
-    g_fprintf (file, " deprecated=\"1\"");
-  
-  g_fprintf (file, " />\n");
+    xml_printf (file, " deprecated=\"1\"");
+
+  write_attributes (file, (GIBaseInfo*) info);
+
+  xml_end_element (file, "member");
 }
 
 static void
-write_constant_value (const gchar *namespace, 
+write_constant_value (const gchar *namespace,
                      GITypeInfo *type,
                      GArgument  *value,
-                     FILE       *file)
+                     Xml        *file)
 {
   switch (g_type_info_get_tag (type))
     {
     case GI_TYPE_TAG_BOOLEAN:
-      g_fprintf (file, "%d", value->v_boolean);
+      xml_printf (file, "%d", value->v_boolean);
       break;
     case GI_TYPE_TAG_INT8:
-      g_fprintf (file, "%d", value->v_int8);
+      xml_printf (file, "%d", value->v_int8);
       break;
     case GI_TYPE_TAG_UINT8:
-      g_fprintf (file, "%d", value->v_uint8);
+      xml_printf (file, "%d", value->v_uint8);
       break;
     case GI_TYPE_TAG_INT16:
-      g_fprintf (file, "%" G_GINT16_FORMAT, value->v_int16);
+      xml_printf (file, "%" G_GINT16_FORMAT, value->v_int16);
       break;
     case GI_TYPE_TAG_UINT16:
-      g_fprintf (file, "%" G_GUINT16_FORMAT, value->v_uint16);
+      xml_printf (file, "%" G_GUINT16_FORMAT, value->v_uint16);
       break;
     case GI_TYPE_TAG_INT32:
-      g_fprintf (file, "%" G_GINT32_FORMAT, value->v_int32);
+      xml_printf (file, "%" G_GINT32_FORMAT, value->v_int32);
       break;
     case GI_TYPE_TAG_UINT32:
-      g_fprintf (file, "%" G_GUINT32_FORMAT, value->v_uint32);
+      xml_printf (file, "%" G_GUINT32_FORMAT, value->v_uint32);
       break;
     case GI_TYPE_TAG_INT64:
-      g_fprintf (file, "%" G_GINT64_FORMAT, value->v_int64);
+      xml_printf (file, "%" G_GINT64_FORMAT, value->v_int64);
       break;
     case GI_TYPE_TAG_UINT64:
-      g_fprintf (file, "%" G_GUINT64_FORMAT, value->v_uint64);
+      xml_printf (file, "%" G_GUINT64_FORMAT, value->v_uint64);
       break;
     case GI_TYPE_TAG_INT:
-      g_fprintf (file, "%d", value->v_int);
+      xml_printf (file, "%d", value->v_int);
       break;
     case GI_TYPE_TAG_UINT:
-      g_fprintf (file, "%d", value->v_uint);
+      xml_printf (file, "%d", value->v_uint);
       break;
     case GI_TYPE_TAG_LONG:
-      g_fprintf (file, "%ld", value->v_long);
+      xml_printf (file, "%ld", value->v_long);
       break;
     case GI_TYPE_TAG_ULONG:
-      g_fprintf (file, "%ld", value->v_ulong);
+      xml_printf (file, "%ld", value->v_ulong);
       break;
     case GI_TYPE_TAG_SSIZE:
-      g_fprintf (file, "%zd", value->v_ssize);
+      xml_printf (file, "%zd", value->v_ssize);
       break;
     case GI_TYPE_TAG_SIZE:
-      g_fprintf (file, "%zd", value->v_size);
+      xml_printf (file, "%zd", value->v_size);
       break;
     case GI_TYPE_TAG_FLOAT:
-      g_fprintf (file, "%f", value->v_float);
+      xml_printf (file, "%f", value->v_float);
       break;
     case GI_TYPE_TAG_DOUBLE:
-      g_fprintf (file, "%f", value->v_double);
+      xml_printf (file, "%f", value->v_double);
       break;
     case GI_TYPE_TAG_UTF8:
     case GI_TYPE_TAG_FILENAME:
-      g_fprintf (file, "%s", value->v_string);
-      break;
-    case GI_TYPE_TAG_SYMBOL:
-      g_fprintf (file, "%s", value->v_string);
+      xml_printf (file, "%s", value->v_string);
       break;
     default:
-      g_warning ("Could not get type tag for constant");
+      g_assert_not_reached ();
     }
 }
 
 static void
 write_constant_info (const gchar    *namespace,
                     GIConstantInfo *info,
-                    FILE           *file,
-                    gint            indent)
+                    Xml            *file)
 {
   GITypeInfo *type;
   const gchar *name;
@@ -554,16 +770,22 @@ write_constant_info (const gchar    *namespace,
   name = g_base_info_get_name ((GIBaseInfo *)info);
   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
 
-  g_fprintf (file, "%*s<constant name=\"%s\" type=\"", indent, "", name);
+  xml_start_element (file, "constant");
+  xml_printf (file, " name=\"%s\"", name);
 
   type = g_constant_info_get_type (info);
-  write_type_info (namespace, type, file);
-  g_fprintf (file, "\" value=\"");
+  xml_printf (file, " value=\"");
 
   g_constant_info_get_value (info, &value);
   write_constant_value (namespace, type, &value, file);
-  g_fprintf (file, "\" />\n");
-  
+  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);
 }
 
@@ -571,7 +793,7 @@ write_constant_info (const gchar    *namespace,
 static void
 write_enum_info (const gchar *namespace,
                 GIEnumInfo *info,
-                FILE        *file)
+                Xml         *file)
 {
   const gchar *name;
   const gchar *type_name;
@@ -586,18 +808,18 @@ write_enum_info (const gchar *namespace,
   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
 
   if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM)
-    g_fprintf (file, "    <enum ");
+    xml_start_element (file, "enumeration");
   else
-    g_fprintf (file, "    <flags ");
-  g_fprintf (file, "name=\"%s\"", name);
+    xml_start_element (file, "bitfield");
+  xml_printf (file, " name=\"%s\"", name);
 
   if (type_init)
-    g_fprintf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
-  
+    xml_printf (file, " glib:type-name=\"%s\" glib:get-type=\"%s\"", type_name, type_init);
+
   if (deprecated)
-    g_fprintf (file, " deprecated=\"1\"");
-       
-  g_fprintf (file, ">\n");
+    xml_printf (file, " deprecated=\"1\"");
+
+  write_attributes (file, (GIBaseInfo*) info);
 
   for (i = 0; i < g_enum_info_get_n_values (info); i++)
     {
@@ -606,16 +828,13 @@ write_enum_info (const gchar *namespace,
       g_base_info_unref ((GIBaseInfo *)value);
     }
 
-  if (g_base_info_get_type ((GIBaseInfo *)info) == GI_INFO_TYPE_ENUM)
-    g_fprintf (file, "    </enum>\n");
-  else
-    g_fprintf (file, "    </flags>\n");
+  xml_end_element_unchecked (file);
 }
 
 static void
 write_signal_info (const gchar  *namespace,
                   GISignalInfo *info,
-                  FILE         *file)
+                  Xml          *file)
 {
   GSignalFlags flags;
   const gchar *name;
@@ -625,43 +844,44 @@ write_signal_info (const gchar  *namespace,
   flags = g_signal_info_get_flags (info);
   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
 
-  g_fprintf (file, "      <signal name=\"%s\"", name);
+  xml_start_element (file, "glib:signal");
+  xml_printf (file, " name=\"%s\"", name);
 
   if (deprecated)
-    g_fprintf (file, " deprecated=\"1\"");
-       
+    xml_printf (file, " deprecated=\"1\"");
+
   if (flags & G_SIGNAL_RUN_FIRST)
-    g_fprintf (file, " when=\"FIRST\"");
+    xml_printf (file, " when=\"FIRST\"");
   else if (flags & G_SIGNAL_RUN_LAST)
-    g_fprintf (file, " when=\"LAST\"");
+    xml_printf (file, " when=\"LAST\"");
   else if (flags & G_SIGNAL_RUN_CLEANUP)
-    g_fprintf (file, " when=\"CLEANUP\"");
+    xml_printf (file, " when=\"CLEANUP\"");
 
   if (flags & G_SIGNAL_NO_RECURSE)
-    g_fprintf (file, " no-recurse=\"1\"");
+    xml_printf (file, " no-recurse=\"1\"");
 
   if (flags & G_SIGNAL_DETAILED)
-    g_fprintf (file, " detailed=\"1\"");
+    xml_printf (file, " detailed=\"1\"");
 
   if (flags & G_SIGNAL_ACTION)
-    g_fprintf (file, " action=\"1\"");
+    xml_printf (file, " action=\"1\"");
 
   if (flags & G_SIGNAL_NO_HOOKS)
-    g_fprintf (file, " no-hooks=\"1\"");
+    xml_printf (file, " no-hooks=\"1\"");
 
-  g_fprintf (file, ">\n");
+  write_callable_info (namespace, (GICallableInfo*)info, file);
 
-  write_callable_info (namespace, (GICallableInfo*)info, file, 6);
-  g_fprintf (file, "      </signal>\n");
+  xml_end_element (file, "glib:signal");
 }
 
 static void
-write_vfunc_info (const gchar *namespace, 
+write_vfunc_info (const gchar *namespace,
                  GIVFuncInfo *info,
-                 FILE        *file)
+                 Xml         *file)
 {
   GIVFuncInfoFlags flags;
   const gchar *name;
+  GIFunctionInfo *invoker;
   gboolean deprecated;
   gint offset;
 
@@ -669,31 +889,36 @@ write_vfunc_info (const gchar *namespace,
   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);
 
-  g_fprintf (file, "      <vfunc name=\"%s\"", name);
+  xml_start_element (file, "virtual-method");
+  xml_printf (file, " name=\"%s\"", name);
 
   if (deprecated)
-    g_fprintf (file, " deprecated=\"1\"");
-       
+    xml_printf (file, " deprecated=\"1\"");
+
   if (flags & GI_VFUNC_MUST_CHAIN_UP)
-    g_fprintf (file, " must-chain-up=\"1\"");
+    xml_printf (file, " must-chain-up=\"1\"");
 
   if (flags & GI_VFUNC_MUST_OVERRIDE)
-    g_fprintf (file, " override=\"always\"");
+    xml_printf (file, " override=\"always\"");
   else if (flags & GI_VFUNC_MUST_NOT_OVERRIDE)
-    g_fprintf (file, " override=\"never\"");
-    
-  g_fprintf (file, " offset=\"%d\"", offset);
-  g_fprintf (file, ">\n");
+    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);
 
-  write_callable_info (namespace, (GICallableInfo*)info, file, 6);
-  g_fprintf (file, "      </vfunc>\n");
+  xml_end_element (file, "virtual-method");
 }
 
 static void
 write_property_info (const gchar    *namespace,
                     GIPropertyInfo *info,
-                    FILE           *file)
+                    Xml            *file)
 {
   GParamFlags flags;
   const gchar *name;
@@ -704,82 +929,90 @@ write_property_info (const gchar    *namespace,
   flags = g_property_info_get_flags (info);
   deprecated = g_base_info_is_deprecated ((GIBaseInfo *)info);
 
-  g_fprintf (file, "      <property name=\"%s\"", name);
+  xml_start_element (file, "property");
+  xml_printf (file, " name=\"%s\"", name);
 
   if (deprecated)
-    g_fprintf (file, " deprecated=\"1\"");
-       
-  if (flags & G_PARAM_READABLE)
-    g_fprintf (file, " readable=\"1\"");
-  else
-    g_fprintf (file, " readable=\"0\"");
+    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)
-    g_fprintf (file, " writable=\"1\"");
-  else
-    g_fprintf (file, " writable=\"0\"");
+    xml_printf (file, " writable=\"1\"");
 
   if (flags & G_PARAM_CONSTRUCT)
-    g_fprintf (file, " construct=\"1\"");
+    xml_printf (file, " construct=\"1\"");
 
   if (flags & G_PARAM_CONSTRUCT_ONLY)
-    g_fprintf (file, " construct-only=\"1\"");
-    
+    xml_printf (file, " construct-only=\"1\"");
+
+  write_attributes (file, (GIBaseInfo*) info);
+
   type = g_property_info_get_type (info);
-  g_fprintf (file, " type=\"");
+
   write_type_info (namespace, type, file);
-  g_fprintf (file, "\"");
 
-  g_fprintf (file, " />\n");
+  xml_end_element (file, "property");
 }
 
 static void
-write_object_info (const gchar  *namespace, 
+write_object_info (const gchar  *namespace,
                   GIObjectInfo *info,
-                  FILE         *file)
+                  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);
-  g_fprintf (file, "    <object name=\"%s\"", name);
+  xml_start_element (file, "class");
+  xml_printf (file, " name=\"%s\"", name);
 
   pnode = g_object_info_get_parent (info);
   if (pnode)
     {
-      g_fprintf (file, " parent=\"");
-      write_type_name (namespace, (GIBaseInfo *)pnode, file);
-      g_fprintf (file, "\""  );
+      write_type_name_attribute (namespace, (GIBaseInfo *)pnode, "parent", file);
       g_base_info_unref ((GIBaseInfo *)pnode);
     }
 
-  g_fprintf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
+  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)
-    g_fprintf (file, " deprecated=\"1\"");
-       
-  g_fprintf (file, ">\n");
+    xml_printf (file, " deprecated=\"1\"");
+
+  write_attributes (file, (GIBaseInfo*) info);
 
   if (g_object_info_get_n_interfaces (info) > 0)
     {
-      g_fprintf (file, "      <implements>\n");
       for (i = 0; i < g_object_info_get_n_interfaces (info); i++)
        {
          GIInterfaceInfo *imp = g_object_info_get_interface (info, i);
-         g_fprintf (file, "        <interface name=\"");
-         write_type_name (namespace, (GIBaseInfo*)imp, file);
-         g_fprintf (file,"\" />\n");
+          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);
        }
-      g_fprintf (file, "      </implements>\n");
     }
 
   for (i = 0; i < g_object_info_get_n_fields (info); i++)
@@ -792,7 +1025,7 @@ write_object_info (const gchar  *namespace,
   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, 6);
+      write_function_info (namespace, function, file);
       g_base_info_unref ((GIBaseInfo *)function);
     }
 
@@ -809,7 +1042,7 @@ write_object_info (const gchar  *namespace,
       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);
@@ -820,21 +1053,22 @@ write_object_info (const gchar  *namespace,
   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, 6);
+      write_constant_info (namespace, constant, file);
       g_base_info_unref ((GIBaseInfo *)constant);
     }
-  
-  g_fprintf (file, "    </object>\n");
+
+  xml_end_element (file, "class");
 }
 
 static void
 write_interface_info (const gchar     *namespace,
                      GIInterfaceInfo *info,
-                     FILE            *file)
+                     Xml             *file)
 {
   const gchar *name;
   const gchar *type_name;
   const gchar *type_init;
+  GIStructInfo *class_struct;
   gboolean deprecated;
   gint i;
 
@@ -843,36 +1077,40 @@ write_interface_info (const gchar     *namespace,
 
   type_name = g_registered_type_info_get_type_name ((GIRegisteredTypeInfo*)info);
   type_init = g_registered_type_info_get_type_init ((GIRegisteredTypeInfo*)info);
-  g_fprintf (file, "    <interface name=\"%s\" type-name=\"%s\" get-type=\"%s\"",
+  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)
-    g_fprintf (file, " deprecated=\"1\"");
-       
-  g_fprintf (file, ">\n");
+    xml_printf (file, " deprecated=\"1\"");
+
+  write_attributes (file, (GIBaseInfo*) info);
 
   if (g_interface_info_get_n_prerequisites (info) > 0)
     {
-      g_fprintf (file, "      <requires>\n");
       for (i = 0; i < g_interface_info_get_n_prerequisites (info); i++)
        {
          GIBaseInfo *req = g_interface_info_get_prerequisite (info, i);
-         
-         if (g_base_info_get_type (req) == GI_INFO_TYPE_INTERFACE)
-           g_fprintf (file, "      <interface name=\"");
-         else
-           g_fprintf (file, "      <object name=\"");
-         write_type_name (namespace, req, file);
-         g_fprintf (file, "\" />\n");
+
+         xml_start_element (file, "prerequisite");
+         write_type_name_attribute (namespace, req, "name", file);
+
+          xml_end_element_unchecked (file);
          g_base_info_unref (req);
        }
-      g_fprintf (file, "      </requires>\n");
     }
 
   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, 6);
+      write_function_info (namespace, function, file);
       g_base_info_unref ((GIBaseInfo *)function);
     }
 
@@ -889,7 +1127,7 @@ write_interface_info (const gchar     *namespace,
       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);
@@ -900,58 +1138,64 @@ write_interface_info (const gchar     *namespace,
   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, 6);
+      write_constant_info (namespace, constant, file);
       g_base_info_unref ((GIBaseInfo *)constant);
     }
-  
-  g_fprintf (file, "    </interface>\n");
+
+  xml_end_element (file, "interface");
 }
 
 static void
 write_error_domain_info (const gchar       *namespace,
                         GIErrorDomainInfo *info,
-                        FILE              *file)
+                        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);
-  g_fprintf (file,
-            "    <errordomain name=\"%s\" get-quark=\"%s\" codes=\"",
-            name, quark);
-  write_type_name (namespace, enum_, file);
-  g_fprintf (file, "\" />\n");
+  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, 
-                 FILE        *file)
+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);
-  
-  g_fprintf (file, "    <union name=\"%s\"", name);
-  
+
+  xml_start_element (file, "union");
+  xml_printf (file, " name=\"%s\"", name);
+
   if (type_name)
-    g_fprintf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
-         
+    xml_printf (file, " type-name=\"%s\" get-type=\"%s\"", type_name, type_init);
+
   if (deprecated)
-    g_fprintf (file, " deprecated=\"1\"");
-       
-  g_fprintf (file, ">\n");
+    xml_printf (file, " deprecated=\"1\"");
+
+  size = g_union_info_get_size (info);
+  if (show_all && size >= 0)
+    xml_printf (file, " size=\"%d\"", size);
+
+  write_attributes (file, (GIBaseInfo*) info);
 
   if (g_union_info_is_discriminated (info))
     {
@@ -960,10 +1204,11 @@ write_union_info (const gchar *namespace,
 
       offset = g_union_info_get_discriminator_offset (info);
       type = g_union_info_get_discriminator_type (info);
-      
-      g_fprintf (file, "      <discriminator offset=\"%d\" type=\"", offset);
+
+      xml_start_element (file, "discriminator");
+      xml_printf (file, " offset=\"%d\" type=\"", offset);
       write_type_info (namespace, type, file);
-      g_fprintf (file, "\" />\n");
+      xml_end_element (file, "discriminator");
       g_base_info_unref ((GIBaseInfo *)type);
     }
 
@@ -980,103 +1225,131 @@ write_union_info (const gchar *namespace,
   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, 6);
+      write_function_info (namespace, function, file);
       g_base_info_unref ((GIBaseInfo *)function);
     }
 
-  g_fprintf (file, "    </union>\n");
+  xml_end_element (file, "union");
 }
 
 static void
-write_repository (GIRepository *repository,
+write_repository (const char   *namespace,
                  gboolean      needs_prefix)
 {
-  FILE *file;
-  gchar **namespaces;
-  gchar *ns;
+  FILE *ofile;
   gint i, j;
+  char **dependencies;
+  GIRepository *repository;
+  Xml *xml;
 
-  namespaces = g_irepository_get_namespaces (repository);
+  repository = g_irepository_get_default ();
 
   if (output == NULL)
-    file = stdout;
+    ofile = stdout;
   else
     {
       gchar *filename;
-      
+
       if (needs_prefix)
-       filename = g_strdup_printf ("%s-%s", namespaces[0], output);  
+       filename = g_strdup_printf ("%s-%s", namespace, output);
       else
        filename = g_strdup (output);
-      file = g_fopen (filename, "w");
-      
-      if (file == NULL)
+      ofile = g_fopen (filename, "w");
+
+      if (ofile == NULL)
        {
          g_fprintf (stderr, "failed to open '%s': %s\n",
                     filename, g_strerror (errno));
          g_free (filename);
-         
+
          return;
        }
-      
+
       g_free (filename);
     }
-  
-  g_fprintf (file, "<?xml version=\"1.0\"?>\n");
-  g_fprintf (file, "<api version=\"1.0\">\n");
 
-  for (i = 0; namespaces[i]; i++)
+  xml = xml_open (ofile);
+
+  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;
-      ns = namespaces[i];
+      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)
-        g_fprintf (file, "  <namespace name=\"%s\" shared-library=\"%s\">\n",
-                   ns, shared_library);
-      else
-        g_fprintf (file, "  <namespace name=\"%s\">\n", ns);
-      
+        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, file, 4);
+             write_function_info (ns, (GIFunctionInfo *)info, xml);
              break;
-             
+
            case GI_INFO_TYPE_CALLBACK:
-             write_callback_info (ns, (GICallbackInfo *)info, file, 4);
+             write_callback_info (ns, (GICallbackInfo *)info, xml);
              break;
 
            case GI_INFO_TYPE_STRUCT:
            case GI_INFO_TYPE_BOXED:
-             write_struct_info (ns, (GIStructInfo *)info, file);
+             write_struct_info (ns, (GIStructInfo *)info, xml);
              break;
 
            case GI_INFO_TYPE_UNION:
-             write_union_info (ns, (GIUnionInfo *)info, file);
+             write_union_info (ns, (GIUnionInfo *)info, xml);
              break;
 
            case GI_INFO_TYPE_ENUM:
            case GI_INFO_TYPE_FLAGS:
-             write_enum_info (ns, (GIEnumInfo *)info, file);
+             write_enum_info (ns, (GIEnumInfo *)info, xml);
              break;
-             
+
            case GI_INFO_TYPE_CONSTANT:
-             write_constant_info (ns, (GIConstantInfo *)info, file, 4);
+             write_constant_info (ns, (GIConstantInfo *)info, xml);
              break;
 
            case GI_INFO_TYPE_OBJECT:
-             write_object_info (ns, (GIObjectInfo *)info, file);
+             write_object_info (ns, (GIObjectInfo *)info, xml);
              break;
 
            case GI_INFO_TYPE_INTERFACE:
-             write_interface_info (ns, (GIInterfaceInfo *)info, file);
+             write_interface_info (ns, (GIInterfaceInfo *)info, xml);
              break;
 
            case GI_INFO_TYPE_ERROR_DOMAIN:
-             write_error_domain_info (ns, (GIErrorDomainInfo *)info, file);
+             write_error_domain_info (ns, (GIErrorDomainInfo *)info, xml);
              break;
 
            default:
@@ -1086,92 +1359,106 @@ write_repository (GIRepository *repository,
          g_base_info_unref (info);
        }
 
-      g_fprintf (file, "  </namespace>\n");
+      xml_end_element (xml, "namespace");
     }
 
-  g_fprintf (file, "</api>\n");
-      
-  if (output != NULL)
-    fclose (file);        
+  xml_end_element (xml, "repository");
 
-  g_strfreev (namespaces);
+  xml_free (xml);
 }
 
-static GOptionEntry options[] = 
-{
-  { "raw", 0, 0, G_OPTION_ARG_NONE, &raw, "handle raw metadata", NULL },
-  { "output", 'o', 0, G_OPTION_ARG_FILENAME, &output, "output file", "FILE" }, 
-  { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &input, NULL, NULL },
-  { NULL, }
-};
-
 static const guchar *
-load_metadata (const gchar  *filename,
+load_typelib (const gchar  *filename,
               GModule     **dlhandle,
                gsize        *len)
 {
-  guchar *metadata;
-  gsize *metadata_size;
-  GModule *handle; 
+  guchar *typelib;
+  gsize *typelib_size;
+  GModule *handle;
 
   handle = g_module_open (filename, G_MODULE_BIND_LOCAL|G_MODULE_BIND_LAZY);
-  if (!g_module_symbol (handle, "_G_METADATA", (gpointer *) &metadata))
+  if (handle == NULL)
     {
-      g_printerr ("Could not load metadata from '%s': %s\n", 
+      g_printerr ("Could not load typelib from '%s': %s\n",
                  filename, g_module_error ());
       return NULL;
     }
-  
-  if (!g_module_symbol (handle, "_G_METADATA_SIZE", (gpointer *) &metadata_size))
+
+  if (!g_module_symbol (handle, "_G_TYPELIB", (gpointer *) &typelib))
     {
-      g_printerr ("Could not load metadata from '%s': %s\n", 
+      g_printerr ("Could not load typelib from '%s': %s\n",
                  filename, g_module_error ());
       return NULL;
     }
 
-  *len = *metadata_size;
-  
+  if (!g_module_symbol (handle, "_G_TYPELIB_SIZE", (gpointer *) &typelib_size))
+    {
+      g_printerr ("Could not load typelib from '%s': %s\n",
+                 filename, g_module_error ());
+      return NULL;
+    }
+
+  *len = *typelib_size;
+
   if (dlhandle)
     *dlhandle = handle;
 
-  return metadata;
+  return typelib;
 }
 
-int 
+int
 main (int argc, char *argv[])
-{  
+{
+  gboolean shlib = FALSE;
+  gchar **input = NULL;
   GOptionContext *context;
   GError *error = NULL;
   gboolean needs_prefix;
   gint i;
-  GMetadata *data;
+  GTypelib *data;
+  GOptionEntry options[] =
+    {
+      { "shlib", 0, 0, G_OPTION_ARG_NONE, &shlib, "handle typelib embedded in shlib", NULL },
+      { "output", 'o', 0, G_OPTION_ARG_FILENAME, &output, "output file", "FILE" },
+      { "includedir", 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &includedirs, "include directories in GIR search path", NULL },
+      { "all", 0, 0, G_OPTION_ARG_NONE, &show_all, "show all available information", NULL, },
+      { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &input, NULL, NULL },
+      { NULL, }
+    };
+
+  g_log_set_always_fatal (G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
 
   g_type_init ();
 
-  g_metadata_check_sanity ();
+  g_typelib_check_sanity ();
 
   context = g_option_context_new ("");
   g_option_context_add_main_entries (context, options, NULL);
   g_option_context_parse (context, &argc, &argv, &error);
 
-  if (!input) 
-    { 
-      g_fprintf (stderr, "no input files\n"); 
-      
+  if (!input)
+    {
+      g_fprintf (stderr, "no input files\n");
+
       return 1;
     }
 
+  if (includedirs != NULL)
+    for (i = 0; includedirs[i]; i++)
+      g_irepository_prepend_search_path (includedirs[i]);
+
   for (i = 0; input[i]; i++)
     {
       GModule *dlhandle = NULL;
-      const guchar *metadata;
+      const guchar *typelib;
       gsize len;
+      const char *namespace;
 
-      if (raw)
+      if (!shlib)
        {
-         if (!g_file_get_contents (input[i], (gchar **)&metadata, &len, &error))
+         if (!g_file_get_contents (input[i], (gchar **)&typelib, &len, &error))
            {
-             g_fprintf (stderr, "failed to read '%s': %s\n", 
+             g_fprintf (stderr, "failed to read '%s': %s\n",
                         input[i], error->message);
              g_clear_error (&error);
              continue;
@@ -1179,10 +1466,10 @@ main (int argc, char *argv[])
        }
       else
        {
-         metadata = load_metadata (input[i], &dlhandle, &len);
-         if (!metadata)
+         typelib = load_typelib (input[i], &dlhandle, &len);
+         if (!typelib)
            {
-             g_fprintf (stderr, "failed to load metadata from '%s'\n", 
+             g_fprintf (stderr, "failed to load typelib from '%s'\n",
                         input[i]);
              continue;
            }
@@ -1193,18 +1480,24 @@ main (int argc, char *argv[])
       else
        needs_prefix = FALSE;
 
-      data = g_metadata_new_from_const_memory (metadata, len);
+      data = g_typelib_new_from_const_memory (typelib, len);
       {
         GError *error = NULL;
-        if (!g_metadata_validate (data, &error)) {
-          g_printerr ("metadata not valid: %s\n", error->message);
+        if (!g_typelib_validate (data, &error)) {
+          g_printerr ("typelib not valid: %s\n", error->message);
           g_clear_error (&error);
+         return 1;
         }
       }
-      g_irepository_register (g_irepository_get_default (), data);
-      write_repository (g_irepository_get_default (), needs_prefix);
-      g_irepository_unregister (g_irepository_get_default (),
-                                g_metadata_get_namespace (data));
+      namespace = g_irepository_load_typelib (g_irepository_get_default (), data, 0,
+                                             &error);
+      if (namespace == NULL)
+       {
+         g_printerr ("failed to load typelib: %s\n", error->message);
+         return 1;
+       }
+
+      write_repository (namespace, needs_prefix);
 
       if (dlhandle)
        {
@@ -1221,6 +1514,6 @@ main (int argc, char *argv[])
          break;
        }
     }
-      
+
   return 0;
 }