Radix cross Linux

The main Radix cross Linux repository contains the build scripts of packages, which have the most complete and common functionality for desktop machines

452 Commits   2 Branches   1 Tag
Index: create.patch.sh
===================================================================
--- create.patch.sh	(nonexistent)
+++ create.patch.sh	(revision 5)
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+VERSION=0.112
+
+tar --files-from=file.list -xzvf ../dbus-glib-$VERSION.tar.gz
+mv dbus-glib-$VERSION dbus-glib-$VERSION-orig
+
+cp -rf ./dbus-glib-$VERSION-new ./dbus-glib-$VERSION
+
+diff --unified -Nr  dbus-glib-$VERSION-orig  dbus-glib-$VERSION > dbus-glib-$VERSION-deprecated-array.patch
+
+mv dbus-glib-$VERSION-deprecated-array.patch ../patches
+
+rm -rf ./dbus-glib-$VERSION
+rm -rf ./dbus-glib-$VERSION-orig

Property changes on: create.patch.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: dbus-glib-0.112-new/dbus/dbus-binding-tool-glib.c
===================================================================
--- dbus-glib-0.112-new/dbus/dbus-binding-tool-glib.c	(nonexistent)
+++ dbus-glib-0.112-new/dbus/dbus-binding-tool-glib.c	(revision 5)
@@ -0,0 +1,1705 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-binding-tool-glib.c: Output C glue
+ *
+ * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
+ * Copyright (C) 2005 Nokia
+ *
+ * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <config.h>
+#include "dbus/dbus-glib.h"
+#include "dbus-gidl.h"
+#include "dbus-gparser.h"
+#include "dbus-gutils.h"
+#include "dbus-gtype-specialized.h"
+#include "dbus-gsignature.h"
+#include "dbus-gvalue-utils.h"
+#include "dbus-glib-tool.h"
+#include "dbus-binding-tool-glib.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Remember to grep for ->format_version in the code if you change this,
+ * most changes should be in dbus-gobject.c. */
+#define FORMAT_VERSION 1
+
+#define MARSHAL_PREFIX "dbus_glib_marshal_"
+
+typedef struct
+{
+  gboolean ignore_unsupported;
+  const char* prefix;
+  GIOChannel *channel;
+  
+  GError **error;
+  
+  GHashTable *generated;
+  GString *blob;
+  GString *signal_blob;
+  GString *property_blob;
+  guint count;
+} DBusBindingToolCData;
+
+static gboolean gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error);
+static gboolean generate_glue_toplevel (BaseInfo *base, DBusBindingToolCData *data, GError **error);
+static gboolean generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error);
+static gboolean generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error);
+
+static const char *
+dbus_g_type_get_marshal_name (GType gtype)
+{
+  switch (G_TYPE_FUNDAMENTAL (gtype))
+    {
+    case G_TYPE_NONE:
+      return "NONE";
+    case G_TYPE_BOOLEAN:
+      return "BOOLEAN";
+    case G_TYPE_UCHAR:
+      return "UCHAR";
+    case G_TYPE_INT:
+      return "INT";
+    case G_TYPE_UINT:
+      return "UINT";
+    case G_TYPE_INT64:
+      return "INT64";
+    case G_TYPE_UINT64:
+      return "UINT64";
+    case G_TYPE_DOUBLE:
+      return "DOUBLE";
+    case G_TYPE_STRING:
+      return "STRING";
+    case G_TYPE_POINTER:
+      return "POINTER";
+    case G_TYPE_BOXED:
+      return "BOXED";
+    case G_TYPE_OBJECT:
+      return "OBJECT";
+    default:
+      return NULL;
+    }
+}
+
+/* This entire function is kind of...ugh. */
+static const char *
+dbus_g_type_get_c_name (GType gtype)
+{
+  GType subtype;
+  if (dbus_g_type_is_struct (gtype))
+    {
+      return "GValueArray";
+    }
+  if (dbus_g_type_is_collection (gtype))
+    {
+      subtype = dbus_g_type_get_collection_specialization(gtype);
+      if (_dbus_g_type_is_fixed (subtype))
+        return "GArray";
+      else
+        return "GPtrArray";
+    }
+
+  if (dbus_g_type_is_map (gtype))
+    return "GHashTable";
+
+  if (g_type_is_a (gtype, G_TYPE_STRING))
+    return "char *";
+
+  /* This one is even more hacky...we get an extra *
+   * because G_TYPE_STRV is a G_TYPE_BOXED
+   */
+  if (g_type_is_a (gtype, G_TYPE_STRV))
+    return "char *";
+
+  if (g_type_is_a (gtype, DBUS_TYPE_G_OBJECT_PATH))
+    return "char";
+
+  if (g_type_is_a (gtype, DBUS_TYPE_G_SIGNATURE))
+    return "char";
+
+  return g_type_name (gtype);
+}
+
+static gboolean
+compute_gsignature (MethodInfo *method, GType *rettype, GArray **params, GError **error)
+{
+  GSList *elt;
+  GType retval_type;
+  GArray *ret;
+  gboolean is_async;
+  const char *arg_type;
+  gboolean retval_signals_error;
+  
+  is_async = method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL;
+  retval_signals_error = FALSE;
+
+  ret = g_array_new (TRUE, TRUE, sizeof (GType));
+
+  if (is_async)
+    retval_type = G_TYPE_NONE;
+  else
+    {
+      gboolean found_retval;
+
+      /* Look for return value */
+      found_retval = FALSE;
+      for (elt = method_info_get_args (method); elt; elt = elt->next)
+	{
+	  ArgInfo *arg = elt->data;
+	  const char *returnval_annotation;
+      
+	  returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL);
+	  if (returnval_annotation != NULL)
+	    {
+	      arg_type = arg_info_get_type (arg);
+	      retval_type = _dbus_gtype_from_signature (arg_type, FALSE);
+	      if (retval_type == G_TYPE_INVALID)
+		goto invalid_type;
+	      found_retval = TRUE;
+	      if (!strcmp (returnval_annotation, "error"))
+		retval_signals_error = TRUE;
+	      break;
+	    }
+	}
+      if (!found_retval)
+	{
+	  retval_type = G_TYPE_BOOLEAN;
+	  retval_signals_error = TRUE;
+	}
+    }
+
+  *rettype = retval_type;
+
+  /* Handle all input arguments */
+  for (elt = method_info_get_args (method); elt; elt = elt->next)
+    {
+      ArgInfo *arg = elt->data;
+      if (arg_info_get_direction (arg) == ARG_IN)
+	{
+	  GType gtype;
+	  
+	  arg_type = arg_info_get_type (arg);
+	  gtype = _dbus_gtype_from_signature (arg_type, FALSE);
+	  if (gtype == G_TYPE_INVALID)
+	    goto invalid_type;
+	  
+	  g_array_append_val (ret, gtype);
+	}
+    }
+
+  if (!is_async)
+    {
+      /* Append pointer for each out arg storage */
+      for (elt = method_info_get_args (method); elt; elt = elt->next)
+	{
+	  ArgInfo *arg = elt->data;
+
+	  /* Skip return value */
+	  if (arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL) != NULL)
+	    continue;
+      
+	  if (arg_info_get_direction (arg) == ARG_OUT)
+	    {
+	      GType gtype;
+	      arg_type = arg_info_get_type (arg);
+	      gtype = _dbus_gtype_from_signature (arg_type, FALSE);
+	      if (gtype == G_TYPE_INVALID)
+		goto invalid_type;
+	      /* We actually just need a pointer for the return value
+		 storage */
+	      gtype = G_TYPE_POINTER;
+	      g_array_append_val (ret, gtype);
+	    }
+	}
+
+      if (retval_signals_error)
+	{
+	  /* Final GError parameter */
+	  GType gtype = G_TYPE_POINTER;
+	  g_array_append_val (ret, gtype);
+	}
+    }
+  else
+    {
+      /* Context pointer */
+      GType gtype = G_TYPE_POINTER;
+      g_array_append_val (ret, gtype);
+    }
+
+  *params = ret;
+  return TRUE;
+
+ invalid_type:
+  g_set_error (error,
+	       DBUS_BINDING_TOOL_ERROR,
+	       DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
+	       "Unsupported conversion from D-BUS type %s to glib-genmarshal type",
+	       arg_type);
+  return FALSE;
+}
+  
+
+static char *
+compute_marshaller (MethodInfo *method, GError **error)
+{
+  GArray *signature;
+  GType rettype;
+  const char *marshal_name;
+  GString *ret;
+  guint i;
+
+  if (!compute_gsignature (method, &rettype, &signature, error))
+    return NULL;
+
+  ret = g_string_new ("");
+  marshal_name = dbus_g_type_get_marshal_name (rettype);
+  g_assert (marshal_name != NULL);
+  g_string_append (ret, marshal_name);
+  g_string_append_c (ret, ':');
+  for (i = 0; i < signature->len; i++)
+    {
+      marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i));
+      g_assert (marshal_name != NULL);
+      g_string_append (ret, marshal_name);
+      if (i < signature->len - 1)
+	g_string_append_c (ret, ',');
+    }
+  if (signature->len == 0)
+    {
+      marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE);
+      g_assert (marshal_name != NULL);
+      g_string_append (ret, marshal_name);
+    }
+  g_array_free (signature, TRUE);
+  return g_string_free (ret, FALSE);
+}
+
+static char *
+compute_marshaller_name (MethodInfo *method, const char *prefix, GError **error)
+{
+  GString *ret;
+  GArray *signature;
+  GType rettype;
+  const char *marshal_name;
+  guint i;
+
+  if (!compute_gsignature (method, &rettype, &signature, error))
+    return NULL;
+
+  ret = g_string_new (MARSHAL_PREFIX);
+  g_string_append (ret, prefix);
+  g_string_append_c (ret, '_');
+
+  marshal_name = dbus_g_type_get_marshal_name (rettype);
+  g_assert (marshal_name != NULL);
+  g_string_append (ret, marshal_name);
+  g_string_append (ret, "__");
+  for (i = 0; i < signature->len; i++)
+    {
+      marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i));
+      g_assert (marshal_name != NULL);
+      g_string_append (ret, marshal_name);
+      if (i < signature->len - 1)
+	g_string_append_c (ret, '_');
+    }
+  if (signature->len == 0)
+    {
+      marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE);
+      g_assert (marshal_name != NULL);
+      g_string_append (ret, marshal_name);
+    }
+  g_array_free (signature, TRUE);
+  return g_string_free (ret, FALSE);
+}
+
+static gboolean
+gather_marshallers_list (GSList *list, DBusBindingToolCData *data, GError **error)
+{
+  GSList *tmp;
+
+  tmp = list;
+  while (tmp != NULL)
+    {
+      if (!gather_marshallers (tmp->data, data, error))
+	return FALSE;
+      tmp = tmp->next;
+    }
+  return TRUE;
+}
+
+static gboolean
+gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error)
+{
+  if (base_info_get_type (base) == INFO_TYPE_NODE)
+    {
+      if (!gather_marshallers_list (node_info_get_nodes ((NodeInfo *) base),
+				    data, error))
+	return FALSE;
+      if (!gather_marshallers_list (node_info_get_interfaces ((NodeInfo *) base),
+				    data, error))
+	return FALSE;
+    }
+  else
+    {
+      InterfaceInfo *interface;
+      GSList *methods;
+      GSList *tmp;
+      const char *interface_c_name;
+
+      interface = (InterfaceInfo *) base;
+      interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_C_SYMBOL);
+      if (interface_c_name == NULL)
+        {
+	  if (!data->prefix)
+	    return TRUE;
+        }
+
+      methods = interface_info_get_methods (interface);
+
+      /* Generate the necessary marshallers for the methods. */
+
+      for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
+        {
+          MethodInfo *method;
+          char *marshaller_name;
+
+          method = (MethodInfo *) tmp->data;
+
+          marshaller_name = compute_marshaller (method, error);
+	  if (!marshaller_name)
+	    return FALSE;
+
+	  if (g_hash_table_lookup (data->generated, marshaller_name))
+	    {
+	      g_free (marshaller_name);
+	      continue;
+	    }
+
+	  g_hash_table_insert (data->generated, marshaller_name, NULL);
+        }
+
+    }
+  return TRUE;
+}
+
+static gboolean
+generate_glue_list (GSList *list, DBusBindingToolCData *data, GError **error)
+{
+  GSList *tmp;
+
+  tmp = list;
+  while (tmp != NULL)
+    {
+      if (!generate_glue (tmp->data, data, error))
+	return FALSE;
+      tmp = tmp->next;
+    }
+  return TRUE;
+}
+
+#define WRITE_OR_LOSE(x) do { gsize bytes_written; if (!g_io_channel_write_chars (channel, x, -1, &bytes_written, error)) goto io_lose; } while (0)
+
+static gboolean
+write_printf_to_iochannel (const char *fmt, GIOChannel *channel, GError **error, ...)
+{
+  char *str;
+  va_list args;
+  GIOStatus status;
+  gsize written;
+  gboolean ret;
+
+  va_start (args, error);
+
+  str = g_strdup_vprintf (fmt, args);
+  if ((status = g_io_channel_write_chars (channel, str, -1, &written, error)) == G_IO_STATUS_NORMAL)
+    ret = TRUE;
+  else
+    ret = FALSE;
+
+  g_free (str);
+
+  va_end (args);
+
+  return ret;
+}
+
+static gboolean
+write_quoted_string (GIOChannel *channel, GString *string, GError **error)
+{
+  guint i;
+
+  WRITE_OR_LOSE ("\"");
+  for (i = 0; i < string->len; i++)
+    {
+      if (string->str[i] != '\0')
+	{
+	  if (!g_io_channel_write_chars (channel, string->str + i, 1, NULL, error))
+	    return FALSE;
+	}
+      else
+	{
+	  if (!g_io_channel_write_chars (channel, "\\0", -1, NULL, error))
+	    return FALSE;
+	}
+    }
+  WRITE_OR_LOSE ("\\0\"");
+  return TRUE;
+ io_lose:
+  return FALSE;
+}
+
+static gboolean
+generate_glue_toplevel (BaseInfo *base, DBusBindingToolCData *data, GError **error)
+{
+  GString *object_introspection_data_blob;
+  GIOChannel *channel;
+
+  channel = data->channel;
+
+  object_introspection_data_blob = g_string_new_len ("", 0);
+  data->blob = object_introspection_data_blob;
+  data->count = 0;
+
+  data->signal_blob = g_string_new_len ("", 0);
+  data->property_blob = g_string_new_len ("", 0);
+
+  if (!write_printf_to_iochannel ("static const DBusGMethodInfo dbus_glib_%s_methods[] = {\n", channel, error, data->prefix))
+    goto io_lose;
+  
+  if (!generate_glue_list (node_info_get_nodes ((NodeInfo *) base),
+                           data, error))
+    return FALSE;
+  if (!generate_glue_list (node_info_get_interfaces ((NodeInfo *) base),
+                             data, error))
+    return FALSE;
+
+  WRITE_OR_LOSE ("};\n\n");
+  /* Information about the object. */
+
+  if (!write_printf_to_iochannel ("const DBusGObjectInfo dbus_glib_%s_object_info = {  %d,\n",
+                                  channel, error, data->prefix, FORMAT_VERSION))
+    goto io_lose;
+  if (!write_printf_to_iochannel ("  dbus_glib_%s_methods,\n", channel, error, data->prefix))
+    goto io_lose;
+  if (!write_printf_to_iochannel ("  %d,\n", channel, error, data->count))
+    goto io_lose;
+  if (!write_quoted_string (channel, object_introspection_data_blob, error))
+    goto io_lose;
+  WRITE_OR_LOSE (",\n");
+  if (!write_quoted_string (channel, data->signal_blob, error))
+    goto io_lose;
+  WRITE_OR_LOSE (",\n");
+  if (!write_quoted_string (channel, data->property_blob, error))
+    goto io_lose;
+  WRITE_OR_LOSE ("\n};\n\n");
+  g_string_free (object_introspection_data_blob, TRUE);
+  g_string_free (data->signal_blob, TRUE);
+  g_string_free (data->property_blob, TRUE);
+  data->signal_blob = NULL;
+  data->property_blob = NULL;
+  return TRUE;
+io_lose:
+ return FALSE;  
+}
+
+static gboolean
+generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
+{
+  if (base_info_get_type (base) == INFO_TYPE_NODE)
+    {
+      if (!generate_glue_list (node_info_get_nodes ((NodeInfo *) base),
+	                       data, error))
+        return FALSE;
+      if (!generate_glue_list (node_info_get_interfaces ((NodeInfo *) base),
+	                       data, error))
+	return FALSE;
+    }
+  else
+    {
+      GIOChannel *channel;
+      InterfaceInfo *interface;
+      GSList *methods;
+      GSList *signals;
+      GSList *properties;
+      GSList *tmp;
+      const char *interface_c_name;
+      GString *object_introspection_data_blob;
+
+      channel = data->channel;
+      object_introspection_data_blob = data->blob;
+
+      interface = (InterfaceInfo *) base;
+      interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_C_SYMBOL);
+      if (interface_c_name == NULL)
+        {
+	  if (data->prefix == NULL)
+	    return TRUE;
+	  interface_c_name = data->prefix;
+        }
+
+      methods = interface_info_get_methods (interface);
+
+      /* Table of marshalled methods. */
+
+      for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
+        {
+          MethodInfo *method;
+          char *marshaller_name;
+	  char *method_c_name;
+          gboolean async = FALSE;
+	  GSList *args;
+	  gboolean found_retval = FALSE;
+          guint found_out_args = 0;
+
+          method = (MethodInfo *) tmp->data;
+	  method_c_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_C_SYMBOL));
+          if (method_c_name == NULL)
+	    {
+	      char *method_name_uscored;
+	      method_name_uscored = _dbus_gutils_wincaps_to_uscore (method_info_get_name (method));
+              method_c_name = g_strdup_printf ("%s_%s",
+					       interface_c_name,
+					       method_name_uscored);
+	      g_free (method_name_uscored);
+            }
+
+          if (!write_printf_to_iochannel ("  { (GCallback) %s, ", channel, error,
+					  method_c_name))
+            {
+	      g_free (method_c_name);
+              goto io_lose;
+            }
+          g_free (method_c_name);
+
+          marshaller_name = compute_marshaller_name (method, data->prefix, error);
+	  if (!marshaller_name)
+	    goto io_lose;
+
+          if (!write_printf_to_iochannel ("%s, %d },\n", channel, error,
+					  marshaller_name,
+					  object_introspection_data_blob->len))
+	    {
+	      g_free (marshaller_name);
+	      goto io_lose;
+	    }
+
+          if (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL)
+            async = TRUE;
+
+	  /* Object method data blob format:
+	   * <iface>\0<name>\0(<argname>\0<argdirection>\0<argtype>\0)*\0
+	   */
+
+	  g_string_append (object_introspection_data_blob, interface_info_get_name (interface));
+	  g_string_append_c (object_introspection_data_blob, '\0');
+
+	  g_string_append (object_introspection_data_blob, method_info_get_name (method));
+	  g_string_append_c (object_introspection_data_blob, '\0');
+
+	  g_string_append_c (object_introspection_data_blob, async ? 'A' : 'S');
+	  g_string_append_c (object_introspection_data_blob, '\0');
+
+	  for (args = method_info_get_args (method); args; args = args->next)
+	    {
+	      ArgInfo *arg;
+	      char direction;
+	      const char *returnval_annotation;
+
+	      arg = args->data;
+
+	      g_string_append (object_introspection_data_blob, arg_info_get_name (arg));
+	      g_string_append_c (object_introspection_data_blob, '\0');
+
+	      switch (arg_info_get_direction (arg))
+		{
+		case ARG_IN:
+		  direction = 'I';
+		  break;
+		case ARG_OUT:
+		  direction = 'O';
+                  found_out_args++;
+		  break;
+		case ARG_INVALID:
+                default:
+                  g_assert_not_reached ();
+                  direction = 0; /* silence gcc */
+		  break;
+		}
+	      g_string_append_c (object_introspection_data_blob, direction);
+	      g_string_append_c (object_introspection_data_blob, '\0');
+
+	      if (arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_CONST) != NULL)
+		{
+		  if (arg_info_get_direction (arg) == ARG_IN)
+		    {
+		      g_set_error (error,
+				   DBUS_BINDING_TOOL_ERROR,
+				   DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+				   "Input argument \"%s\" cannot have const annotation in method \"%s\" of interface \"%s\"\n",
+				   arg_info_get_name (arg),
+				   method_info_get_name (method),
+				   interface_info_get_name (interface));
+		      return FALSE;
+		    }
+		  g_string_append_c (object_introspection_data_blob, 'C');
+		  g_string_append_c (object_introspection_data_blob, '\0');
+		}
+	      else if (arg_info_get_direction (arg) == ARG_OUT)
+		{
+		  g_string_append_c (object_introspection_data_blob, 'F');
+		  g_string_append_c (object_introspection_data_blob, '\0');
+		}
+
+	      returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL);
+	      if (returnval_annotation != NULL)
+		{
+		  GType gtype;
+
+		  if (found_retval)
+		    {
+		      g_set_error (error,
+				   DBUS_BINDING_TOOL_ERROR,
+				   DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+				   "Multiple arguments with return value annotation in method \"%s\" of interface \"%s\"\n",
+				   method_info_get_name (method),
+				   interface_info_get_name (interface));
+		      return FALSE;
+		    }
+		  found_retval = TRUE;
+		  if (arg_info_get_direction (arg) == ARG_IN)
+		    {
+		      g_set_error (error,
+				   DBUS_BINDING_TOOL_ERROR,
+				   DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+				   "Input argument \"%s\" cannot have return value annotation in method \"%s\" of interface \"%s\"\n",
+				   arg_info_get_name (arg),
+				   method_info_get_name (method),
+				   interface_info_get_name (interface));
+		      return FALSE;
+		    }
+
+                  if (found_out_args != 1)
+                    {
+                      g_set_error (error,
+                          DBUS_BINDING_TOOL_ERROR,
+                          DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+                          "An output <arg> after the first cannot have the ReturnVal annotation, in argument \"%s\" of method \"%s\" of interface \"%s\"\n",
+                          arg_info_get_name (arg),
+                          method_info_get_name (method),
+                          interface_info_get_name (interface));
+                      return FALSE;
+                    }
+
+		  if (!strcmp ("", returnval_annotation))
+		    g_string_append_c (object_introspection_data_blob, 'R');
+		  else if (!strcmp ("error", returnval_annotation))
+		    {
+		      gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+		      if (!_dbus_gtype_can_signal_error (gtype))
+			{
+			  g_set_error (error,
+				       DBUS_BINDING_TOOL_ERROR,
+				       DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+				       "Output argument \"%s\" cannot signal error with type \"%s\" in method \"%s\" of interface \"%s\"\n",
+				       arg_info_get_name (arg),
+				       g_type_name (gtype),
+				       method_info_get_name (method),
+				       interface_info_get_name (interface));
+			  return FALSE;
+			}
+		      g_string_append_c (object_introspection_data_blob, 'E');
+		    }
+		  else
+		    {
+		      g_set_error (error,
+				   DBUS_BINDING_TOOL_ERROR,
+				   DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
+				   "Invalid ReturnVal annotation for argument \"%s\" in method \"%s\" of interface \"%s\"\n",
+				   arg_info_get_name (arg),
+				   method_info_get_name (method),
+				   interface_info_get_name (interface));
+		      return FALSE;
+		    }
+		      
+		  g_string_append_c (object_introspection_data_blob, '\0');
+		}
+	      else if (arg_info_get_direction (arg) == ARG_OUT)
+		{
+		  g_string_append_c (object_introspection_data_blob, 'N');
+		  g_string_append_c (object_introspection_data_blob, '\0');
+		}
+
+	      g_string_append (object_introspection_data_blob, arg_info_get_type (arg));
+	      g_string_append_c (object_introspection_data_blob, '\0');
+	    }
+
+	  g_string_append_c (object_introspection_data_blob, '\0');
+
+          data->count++;
+        }
+
+      signals = interface_info_get_signals (interface);
+
+      for (tmp = signals; tmp != NULL; tmp = g_slist_next (tmp))
+        {
+          SignalInfo *sig;
+	  
+	  sig = tmp->data;
+
+	  g_string_append (data->signal_blob, interface_info_get_name (interface));
+	  g_string_append_c (data->signal_blob, '\0');
+	  g_string_append (data->signal_blob, signal_info_get_name (sig));
+	  g_string_append_c (data->signal_blob, '\0');
+	}
+
+      properties = interface_info_get_properties (interface);
+
+      for (tmp = properties; tmp != NULL; tmp = g_slist_next (tmp))
+        {
+          PropertyInfo *prop;
+          PropertyAccessFlags access_flags;
+          const char *access_string;
+          char *uscored;
+
+          prop = tmp->data;
+
+          access_flags = property_info_get_access (prop);
+          if ((access_flags & PROPERTY_READ) && (access_flags & PROPERTY_WRITE))
+            access_string = "readwrite";
+          else if (access_flags & PROPERTY_READ)
+            access_string = "read";
+          else if (access_flags & PROPERTY_WRITE)
+            access_string = "write";
+          else
+            continue;
+
+          /* We append both in the blob so we have to malloc() less when processing
+           * properties */
+          uscored = _dbus_gutils_wincaps_to_uscore (property_info_get_name (prop));
+
+          g_string_append (data->property_blob, interface_info_get_name (interface));
+          g_string_append_c (data->property_blob, '\0');
+          g_string_append (data->property_blob, property_info_get_name (prop));
+          g_string_append_c (data->property_blob, '\0');
+          g_string_append (data->property_blob, uscored);
+          g_string_append_c (data->property_blob, '\0');
+          g_string_append (data->property_blob, access_string);
+          g_string_append_c (data->property_blob, '\0');
+
+          g_free (uscored);
+	}
+    }
+  return TRUE;
+ io_lose:
+  return FALSE;
+}
+
+static void
+write_marshaller (gpointer key, gpointer value, gpointer user_data)
+{
+  DBusBindingToolCData *data;
+  const char *marshaller;
+  gsize bytes_written;
+
+  data = user_data;
+  marshaller = key;
+
+  if (data->error && *data->error)
+    return;
+
+  if (g_io_channel_write_chars (data->channel, marshaller, -1, &bytes_written, data->error) == G_IO_STATUS_NORMAL)
+    g_io_channel_write_chars (data->channel, "\n", -1, &bytes_written, data->error);
+}
+
+gboolean
+dbus_binding_tool_output_glib_server (BaseInfo *info, GIOChannel *channel, const char *prefix, GError **error)
+{
+  gboolean ret;
+  GPtrArray *argv;
+  gint child_stdout;
+  GIOChannel *genmarshal_stdout;
+  GPid child_pid;
+  DBusBindingToolCData data;
+  char *tempfile_name;
+  gint tempfile_fd;
+  GIOStatus iostatus;
+  char buf[4096];
+  gsize bytes_read, bytes_written;
+
+  memset (&data, 0, sizeof (data));
+
+  dbus_g_type_specialized_init ();
+  _dbus_g_type_specialized_builtins_init ();
+
+  data.prefix = prefix;
+  data.generated = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
+  data.error = error;
+  genmarshal_stdout = NULL;
+  tempfile_name = NULL;
+
+  if (!gather_marshallers (info, &data, error))
+    goto io_lose;
+
+  tempfile_fd = g_file_open_tmp ("dbus-binding-tool-c-marshallers.XXXXXX",
+				 &tempfile_name, error);
+  if (tempfile_fd < 0)
+    goto io_lose;
+
+  data.channel = g_io_channel_unix_new (tempfile_fd);
+  if (!g_io_channel_set_encoding (data.channel, NULL, error))
+    goto io_lose;
+  g_hash_table_foreach (data.generated, write_marshaller, &data); 
+  if (error && *error != NULL)
+    {
+      ret = FALSE;
+      g_io_channel_shutdown (data.channel, TRUE, error);
+      g_io_channel_unref (data.channel);
+      data.channel = NULL;
+      goto io_lose;
+    }
+
+  g_io_channel_shutdown (data.channel, TRUE, error);
+  g_io_channel_unref (data.channel);
+  data.channel = NULL;
+  
+  /* Now spawn glib-genmarshal to insert all our required marshallers */
+  argv = g_ptr_array_new ();
+  g_ptr_array_add (argv, "glib-genmarshal");
+  g_ptr_array_add (argv, "--header");
+  g_ptr_array_add (argv, "--body");
+  g_ptr_array_add (argv, "--skip-source");
+  g_ptr_array_add (argv, g_strdup_printf ("--prefix=%s%s", MARSHAL_PREFIX, prefix));
+  g_ptr_array_add (argv, tempfile_name);
+  g_ptr_array_add (argv, NULL);
+  if (!g_spawn_async_with_pipes (NULL, (char**)argv->pdata, NULL,
+				 G_SPAWN_SEARCH_PATH,
+				 NULL, NULL,
+				 &child_pid,
+				 NULL,
+				 &child_stdout, NULL, error))
+    {
+      g_ptr_array_free (argv, TRUE);
+      goto io_lose;
+    }
+  g_ptr_array_free (argv, TRUE);
+
+  genmarshal_stdout = g_io_channel_unix_new (child_stdout);
+  if (!g_io_channel_set_encoding (genmarshal_stdout, NULL, error))
+    goto io_lose;
+
+  WRITE_OR_LOSE ("/* Generated by dbus-binding-tool; do not edit! */\n\n");
+
+  while ((iostatus = g_io_channel_read_chars (genmarshal_stdout, buf, sizeof (buf),
+					      &bytes_read, error)) == G_IO_STATUS_NORMAL)
+    if (g_io_channel_write_chars (channel, buf, bytes_read, &bytes_written, error) != G_IO_STATUS_NORMAL)
+      goto io_lose;
+  if (iostatus != G_IO_STATUS_EOF)
+    goto io_lose;
+
+  g_io_channel_shutdown (genmarshal_stdout, TRUE, error);
+
+  WRITE_OR_LOSE ("#include <dbus/dbus-glib.h>\n");
+
+  data.channel = channel;
+  g_io_channel_ref (data.channel);
+  if (!generate_glue_toplevel (info, &data, error))
+    goto io_lose;
+  
+  ret = TRUE;
+ cleanup:
+  if (tempfile_name)
+    unlink (tempfile_name);
+  g_free (tempfile_name);
+  if (genmarshal_stdout)
+    g_io_channel_unref (genmarshal_stdout);
+  if (data.channel)
+    g_io_channel_unref (data.channel);
+  g_hash_table_destroy (data.generated);
+
+  return ret;
+ io_lose:
+  ret = FALSE;
+  goto cleanup;
+}
+
+static char *
+iface_to_c_prefix (const char *iface)
+{
+  char **components;
+  char **component;
+  GString *ret;
+  gboolean first;
+  
+  components = g_strsplit (iface, ".", 0);
+
+  first = TRUE;
+  ret = g_string_new ("");
+  for (component = components; *component; component++)
+    {
+      if (!first)
+	g_string_append_c (ret, '_');
+      else
+	first = FALSE;
+      g_string_append (ret, *component);
+    }
+  g_strfreev (components);
+  return g_string_free (ret, FALSE);
+}
+
+static char *
+compute_client_method_name (const char *iface_prefix, MethodInfo *method)
+{
+  char *method_name_uscored, *ret;
+
+  method_name_uscored = _dbus_gutils_wincaps_to_uscore (method_info_get_name (method));
+  ret = g_strdup_printf ("%s_%s", iface_prefix, method_name_uscored);
+  g_free (method_name_uscored);
+
+  return ret;
+}
+
+static gboolean
+write_formal_parameters (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, GError **error)
+{
+  GSList *args;
+
+  for (args = method_info_get_args (method); args; args = args->next)
+    {
+      ArgInfo *arg;
+      const char *type_str;
+      const char *type_suffix;
+      GType gtype;
+      int direction;
+
+      arg = args->data;
+
+      WRITE_OR_LOSE (", ");
+
+      direction = arg_info_get_direction (arg);
+
+      gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+      if (gtype == G_TYPE_INVALID)
+	{
+	  g_set_error (error,
+		       DBUS_BINDING_TOOL_ERROR,
+		       DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
+		       "Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\"",
+		       arg_info_get_type (arg),
+		       method_info_get_name (method),
+		       interface_info_get_name (iface));
+	  return FALSE;
+	}
+      type_str = dbus_g_type_get_c_name (gtype);
+      g_assert (type_str);
+      /* Variants are special...*/
+      if (gtype == G_TYPE_VALUE)
+	{
+	  if (direction == ARG_IN)
+	    type_suffix = "*";
+	  else
+	    type_suffix = "";
+	}
+      else if ((g_type_is_a (gtype, G_TYPE_BOXED)
+	      || g_type_is_a (gtype, G_TYPE_OBJECT)
+	   || g_type_is_a (gtype, G_TYPE_POINTER)))
+	type_suffix = "*";
+      else
+	type_suffix = "";
+
+
+      switch (direction)
+	{
+	case ARG_IN:
+	  if (!write_printf_to_iochannel ("const %s%s IN_%s", channel, error,
+					  type_str,
+					  type_suffix,
+					  arg_info_get_name (arg)))
+	    goto io_lose;
+	  break;
+	case ARG_OUT:
+	  if (!write_printf_to_iochannel ("%s%s* OUT_%s", channel, error,
+					  type_str,
+					  type_suffix,
+					  arg_info_get_name (arg)))
+	    goto io_lose;
+	  break;
+	case ARG_INVALID:
+	  break;
+	}
+    }
+
+  return TRUE;
+ io_lose:
+  return FALSE;
+}
+
+#define MAP_FUNDAMENTAL(NAME) \
+   case G_TYPE_ ## NAME: \
+     return g_strdup ("G_TYPE_" #NAME);
+#define MAP_KNOWN(NAME) \
+    if (gtype == NAME) \
+      return g_strdup (#NAME)
+static char *
+dbus_g_type_get_lookup_function (GType gtype)
+{
+  char *type_lookup;
+  switch (gtype)
+    {
+      MAP_FUNDAMENTAL(CHAR);
+      MAP_FUNDAMENTAL(UCHAR);
+      MAP_FUNDAMENTAL(BOOLEAN);
+      MAP_FUNDAMENTAL(LONG);
+      MAP_FUNDAMENTAL(ULONG);
+      MAP_FUNDAMENTAL(INT);
+      MAP_FUNDAMENTAL(UINT);
+      MAP_FUNDAMENTAL(INT64);
+      MAP_FUNDAMENTAL(UINT64);
+      MAP_FUNDAMENTAL(FLOAT);
+      MAP_FUNDAMENTAL(DOUBLE);
+      MAP_FUNDAMENTAL(STRING);
+    }
+  if (dbus_g_type_is_collection (gtype))
+    {
+      GType elt_gtype;
+      char *sublookup;
+
+      elt_gtype = dbus_g_type_get_collection_specialization (gtype);
+      sublookup = dbus_g_type_get_lookup_function (elt_gtype);
+      g_assert (sublookup);
+
+      if (_dbus_g_type_is_fixed (elt_gtype))
+        {
+          type_lookup = g_strdup_printf ("dbus_g_type_get_collection "
+              "(\"GArray\", %s)", sublookup);
+        }
+      else
+        {
+          type_lookup = g_strdup_printf ("dbus_g_type_get_collection "
+              "(\"GPtrArray\", %s)", sublookup);
+        }
+
+      g_free (sublookup);
+
+      return type_lookup;
+    }
+  else if (dbus_g_type_is_map (gtype))
+    {
+      GType key_gtype;
+      char *key_lookup;
+      GType value_gtype;
+      char *value_lookup;
+      
+      key_gtype = dbus_g_type_get_map_key_specialization (gtype);
+      value_gtype = dbus_g_type_get_map_value_specialization (gtype);
+      key_lookup = dbus_g_type_get_lookup_function (key_gtype);
+      g_assert (key_lookup);
+      value_lookup = dbus_g_type_get_lookup_function (value_gtype);
+      g_assert (value_lookup);
+      type_lookup = g_strdup_printf ("dbus_g_type_get_map (\"GHashTable\", %s, %s)",
+				     key_lookup, value_lookup);
+      g_free (key_lookup);
+      g_free (value_lookup);
+      return type_lookup;
+    }
+  else if (dbus_g_type_is_struct (gtype))
+    {
+      GType value_gtype;
+      GString *string;
+      char *value_lookup = NULL;
+      guint size, i;
+
+      string = g_string_new ("dbus_g_type_get_struct (\"GValueArray\"");
+
+      size = dbus_g_type_get_struct_size (gtype);
+      for (i=0; i < size; i++)
+        {
+          value_gtype = dbus_g_type_get_struct_member_type(gtype, i);
+          value_lookup = dbus_g_type_get_lookup_function (value_gtype);
+          g_assert (value_lookup);
+          g_string_append_printf (string, ", %s", value_lookup);
+          g_free (value_lookup);
+        }
+      g_string_append (string, ", G_TYPE_INVALID)");
+      return g_string_free (string, FALSE);
+    }
+
+  MAP_KNOWN(G_TYPE_VALUE);
+  MAP_KNOWN(G_TYPE_STRV);
+  MAP_KNOWN(G_TYPE_ARRAY);
+  MAP_KNOWN(DBUS_TYPE_G_PROXY);
+  MAP_KNOWN(DBUS_TYPE_G_OBJECT_PATH);
+  MAP_KNOWN(DBUS_TYPE_G_SIGNATURE);
+  return NULL;
+}
+#undef MAP_FUNDAMENTAL
+#undef MAP_KNOWN
+
+static gboolean
+write_args_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, int direction, GError **error)
+{
+  GSList *args;
+  char *type_lookup = NULL;
+
+  for (args = method_info_get_args (method); args; args = args->next)
+    {
+      ArgInfo *arg;
+      GType gtype;
+
+      arg = args->data;
+
+      if (direction != arg_info_get_direction (arg))
+	continue;
+
+      gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+      g_assert (gtype != G_TYPE_INVALID);
+      type_lookup = dbus_g_type_get_lookup_function (gtype);
+      g_assert (type_lookup != NULL);
+
+      switch (direction)
+	{
+
+	case ARG_IN:
+	  if (!write_printf_to_iochannel ("%s, IN_%s, ", channel, error,
+					  type_lookup,
+					  arg_info_get_name (arg)))
+	    goto io_lose;
+	  break;
+	case ARG_OUT:
+	  if (!write_printf_to_iochannel ("%s, OUT_%s, ", channel, error,
+					  type_lookup,
+					  arg_info_get_name (arg)))
+	    goto io_lose;
+	  break;
+	case ARG_INVALID:
+	  break;
+	}
+      g_free (type_lookup);
+    }
+
+  return TRUE;
+ io_lose:
+  g_free (type_lookup);
+  return FALSE;
+}
+
+static gboolean
+check_supported_parameters (MethodInfo *method)
+{
+  GSList *args;
+
+  for (args = method_info_get_args (method); args; args = args->next)
+    {
+      ArgInfo *arg;
+      GType gtype;
+
+      arg = args->data;
+      gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+      if (gtype == G_TYPE_INVALID)
+	return FALSE;
+    }
+  return TRUE;
+}
+
+static gboolean
+write_untyped_out_args (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, GError **error)
+{
+  GSList *args;
+
+  for (args = method_info_get_args (method); args; args = args->next)
+    {
+      ArgInfo *arg;
+
+      arg = args->data;
+      if (arg_info_get_direction (arg) != ARG_OUT)
+        continue;
+            
+      if (!write_printf_to_iochannel ("OUT_%s, ", channel, error,
+                                      arg_info_get_name (arg)))
+        goto io_lose;
+     }
+
+   return TRUE;
+ io_lose:
+  return FALSE;
+}
+
+static gboolean
+write_formal_declarations_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, const int direction, GError **error)
+ {
+   GSList *args;
+ 
+   for (args = method_info_get_args (method); args; args = args->next)
+     {
+       ArgInfo *arg;
+      GType gtype;
+      const char *type_str, *type_suffix, *type_initializer = "";
+      int dir;
+
+       arg = args->data;
+
+      dir = arg_info_get_direction (arg);
+
+      gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+      type_str = dbus_g_type_get_c_name (gtype);
+
+      if (!type_str)
+       {
+         g_set_error (error,
+                      DBUS_BINDING_TOOL_ERROR,
+                      DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
+                      "Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\"",
+                      arg_info_get_type (arg),
+                      method_info_get_name (method),
+                      interface_info_get_name (iface));
+         return FALSE;
+       }
+
+      /* Variants are special...*/
+      if (gtype == G_TYPE_VALUE)
+	{
+	  if (direction == ARG_IN)
+	    type_suffix = "*";
+	  else
+	    {
+	      type_suffix = "";
+	      type_initializer = " = { 0, }";
+	    }
+	}
+      else if ((g_type_is_a (gtype, G_TYPE_BOXED)
+	      || g_type_is_a (gtype, G_TYPE_OBJECT)
+	   || g_type_is_a (gtype, G_TYPE_POINTER)))
+	type_suffix = "*";
+      else
+	type_suffix = "";
+
+      if (direction != dir)
+        continue;
+
+          switch (dir)
+       {
+       case ARG_IN:
+         if (!write_printf_to_iochannel ("  %s%s IN_%s;\n", channel, error,
+                                         type_str, type_suffix,
+                                         arg_info_get_name (arg)))
+           goto io_lose;
+         break;
+       case ARG_OUT:
+         if (!write_printf_to_iochannel ("  %s%s OUT_%s%s;\n", channel, error,
+                                         type_str, type_suffix,
+                                         arg_info_get_name (arg),
+                                         type_initializer))
+           goto io_lose;
+         break;
+       case ARG_INVALID:
+         break;
+       }
+     }
+   return TRUE;
+ io_lose:
+  return FALSE;
+ }
+
+static gboolean
+write_formal_parameters_for_direction (InterfaceInfo *iface, MethodInfo *method, int dir, GIOChannel *channel, GError **error)
+{
+  GSList *args;
+
+  for (args = method_info_get_args (method); args; args = args->next)
+    {
+      ArgInfo *arg;
+      const char *type_str;
+      const char *type_suffix;
+      GType gtype;
+      int direction;
+
+      arg = args->data;
+
+      direction = arg_info_get_direction (arg);
+      if (dir != direction) continue;
+      
+      WRITE_OR_LOSE (", ");
+
+      gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+      type_str = dbus_g_type_get_c_name (gtype);
+      /* Variants are special...*/
+      if (gtype == G_TYPE_VALUE)
+	{
+	  if (direction == ARG_IN)
+	    type_suffix = "*";
+	  else
+	    type_suffix = "";
+	}
+      else if ((g_type_is_a (gtype, G_TYPE_BOXED)
+	      || g_type_is_a (gtype, G_TYPE_OBJECT)
+	   || g_type_is_a (gtype, G_TYPE_POINTER)))
+	type_suffix = "*";
+      else
+	type_suffix = "";
+
+      if (!type_str)
+	{
+	  g_set_error (error,
+		       DBUS_BINDING_TOOL_ERROR,
+		       DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
+		       "Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\"",
+		       arg_info_get_type (arg),
+		       method_info_get_name (method),
+		       interface_info_get_name (iface));
+	  return FALSE;
+	}
+ 
+       switch (direction)
+ 	{
+ 	case ARG_IN:
+	  if (!write_printf_to_iochannel ("const %s%s IN_%s", channel, error,
+					  type_str,
+					  type_suffix,
+					  arg_info_get_name (arg)))
+ 	    goto io_lose;
+ 	  break;
+ 	case ARG_OUT:
+	  if (!write_printf_to_iochannel ("%s%s* OUT_%s", channel, error,
+					  type_str,
+					  type_suffix,
+					  arg_info_get_name (arg)))
+ 	    goto io_lose;
+ 	  break;
+ 	case ARG_INVALID:
+	  break;
+	}
+    }
+  return TRUE;
+ io_lose:
+  return FALSE;
+}
+
+static gboolean
+write_typed_args_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, const int direction, GError **error)
+{
+  GSList *args;
+  char *type_lookup = NULL;
+  
+  for (args = method_info_get_args (method); args; args = args->next)
+    {
+      ArgInfo *arg;
+      int dir;
+      GType gtype;
+      
+      arg = args->data;
+
+      dir = arg_info_get_direction (arg);
+
+      if (dir != direction)
+        continue;
+
+      gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+      type_lookup = dbus_g_type_get_lookup_function (gtype);
+
+      if (!write_printf_to_iochannel ("%s, &%s_%s, ", channel, error, type_lookup, direction == ARG_IN ? "IN" : "OUT", arg_info_get_name (arg)))
+        goto io_lose;
+      g_free (type_lookup);
+    }
+  return TRUE;
+ io_lose:
+  g_free (type_lookup);
+  return FALSE;
+}
+
+static gboolean
+write_async_method_client (GIOChannel *channel, InterfaceInfo *interface, MethodInfo *method, GError **error)
+{
+  char *method_name, *iface_prefix;
+  const char *interface_c_name;
+
+  iface_prefix = iface_to_c_prefix (interface_info_get_name (interface));
+  interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL);
+  if (interface_c_name == NULL)
+    {
+      interface_c_name = (const char *) iface_prefix;
+    }
+
+  method_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL));
+  if (method_name == NULL)
+    {
+      method_name = compute_client_method_name (interface_c_name, method);
+    }
+  g_free(iface_prefix);
+
+  /* Write the typedef for the client callback */
+  if (!write_printf_to_iochannel ("typedef void (*%s_reply) (DBusGProxy *proxy, ", channel, error, method_name))
+    goto io_lose;
+  {
+    GSList *args;
+    for (args = method_info_get_args (method); args; args = args->next)
+      {
+	ArgInfo *arg;
+	const char *type_suffix, *type_str;
+	GType gtype;
+	
+	arg = args->data;
+	
+	if (arg_info_get_direction (arg) != ARG_OUT)
+	  continue;
+	gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
+	if (gtype != G_TYPE_VALUE && (g_type_is_a (gtype, G_TYPE_BOXED)
+	     || g_type_is_a (gtype, G_TYPE_OBJECT)
+	     || g_type_is_a (gtype, G_TYPE_POINTER)))
+	  type_suffix = "*";
+	else
+	  type_suffix = "";
+	type_str = dbus_g_type_get_c_name (_dbus_gtype_from_signature (arg_info_get_type (arg), TRUE));
+	if (!write_printf_to_iochannel ("%s %sOUT_%s, ", channel, error, type_str, type_suffix, arg_info_get_name (arg)))
+	  goto io_lose;
+      }
+  }
+  WRITE_OR_LOSE ("GError *error, gpointer userdata);\n\n");
+  
+  
+  /* Write the callback when the call returns */
+  WRITE_OR_LOSE ("static void\n");
+  if (!write_printf_to_iochannel ("%s_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)\n", channel, error, method_name))
+    goto io_lose;
+  WRITE_OR_LOSE ("{\n");
+  WRITE_OR_LOSE ("  DBusGAsyncData *data = (DBusGAsyncData*) user_data;\n  GError *error = NULL;\n");
+  if (!write_formal_declarations_for_direction (interface, method, channel, ARG_OUT, error))
+    goto io_lose;
+  /* TODO: handle return boolean of end_call */
+  WRITE_OR_LOSE ("  dbus_g_proxy_end_call (proxy, call, &error, ");
+  if (!write_typed_args_for_direction (interface, method, channel, ARG_OUT, error))
+    goto io_lose;
+  WRITE_OR_LOSE("G_TYPE_INVALID);\n");
+  if (!write_printf_to_iochannel ("  (*(%s_reply)data->cb) (proxy, ", channel, error, method_name))
+    goto io_lose;
+  if (!write_untyped_out_args (interface, method, channel, error))
+    goto io_lose;
+  WRITE_OR_LOSE ("error, data->userdata);\n");
+  WRITE_OR_LOSE ("  return;\n}\n\n");
+  
+
+  /* Write the main wrapper function */
+  WRITE_OR_LOSE ("static inline DBusGProxyCall*\n");
+  if (!write_printf_to_iochannel ("%s_async (DBusGProxy *proxy", channel, error,
+                                  method_name))
+    goto io_lose;
+  if (!write_formal_parameters_for_direction (interface, method, ARG_IN, channel, error))
+    goto io_lose;
+  
+  if (!write_printf_to_iochannel (", %s_reply callback, gpointer userdata)\n\n", channel, error, method_name))
+    goto io_lose;
+  
+  WRITE_OR_LOSE ("{\n");
+  WRITE_OR_LOSE ("  DBusGAsyncData *stuff;\n  stuff = g_slice_new (DBusGAsyncData);\n  stuff->cb = G_CALLBACK (callback);\n  stuff->userdata = userdata;\n");
+  if (!write_printf_to_iochannel ("  return dbus_g_proxy_begin_call (proxy, \"%s\", %s_async_callback, stuff, _dbus_glib_async_data_free, ", channel, error, method_info_get_name (method), method_name))
+    goto io_lose;
+  if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
+    goto io_lose;
+  WRITE_OR_LOSE ("G_TYPE_INVALID);\n}\n");
+
+  g_free (method_name);
+  return TRUE;
+ io_lose:
+  g_free (method_name);
+  return FALSE;
+ }
+
+static gboolean
+generate_client_glue_list (GSList *list, DBusBindingToolCData *data, GError **error)
+{
+  GSList *tmp;
+
+  tmp = list;
+  while (tmp != NULL)
+    {
+      if (!generate_client_glue (tmp->data, data, error))
+	return FALSE;
+      tmp = tmp->next;
+    }
+  return TRUE;
+}
+
+static gboolean
+generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
+{
+  char *iface_prefix;
+  char *method_c_name;
+  iface_prefix = NULL;
+  method_c_name = NULL;
+
+  if (base_info_get_type (base) == INFO_TYPE_NODE)
+    {
+      if (!generate_client_glue_list (node_info_get_nodes ((NodeInfo *) base),
+              data, error))
+        return FALSE;
+      if (!generate_client_glue_list (node_info_get_interfaces ((NodeInfo *) base),
+              data, error))
+        return FALSE;
+    }
+  else
+    {
+      GIOChannel *channel;
+      InterfaceInfo *interface;
+      GSList *methods;
+      GSList *tmp;
+      const char *interface_c_name;
+
+      channel = data->channel;
+
+      interface = (InterfaceInfo *) base;
+
+      methods = interface_info_get_methods (interface);
+
+      iface_prefix = iface_to_c_prefix (interface_info_get_name (interface));
+      interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL);
+      if (interface_c_name == NULL)
+      {
+          interface_c_name = (const char *) iface_prefix;
+      }
+
+      if (!write_printf_to_iochannel ("#ifndef DBUS_GLIB_CLIENT_WRAPPERS_%s\n"
+              "#define DBUS_GLIB_CLIENT_WRAPPERS_%s\n\n",
+              channel, error,
+              iface_prefix, iface_prefix))
+        goto io_lose;
+
+      for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
+        {
+          MethodInfo *method;
+          gboolean is_noreply;
+
+          method = (MethodInfo *) tmp->data;
+          method_c_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL));
+          if (method_c_name == NULL)
+            {
+              method_c_name = compute_client_method_name (interface_c_name, method);
+            }
+
+          is_noreply = method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_NOREPLY) != NULL;
+
+          if (data->ignore_unsupported && !check_supported_parameters (method))
+            {
+              g_warning ("Ignoring unsupported signature in method \"%s\" of interface \"%s\"\n",
+              method_info_get_name (method),
+              interface_info_get_name (interface));
+              g_free (method_c_name);
+              method_c_name = NULL;
+              continue;
+            }
+
+
+          WRITE_OR_LOSE ("static inline gboolean\n");
+          if (!write_printf_to_iochannel ("%s (DBusGProxy *proxy", channel, error,
+                  method_c_name))
+            goto io_lose;
+          g_free (method_c_name);
+          method_c_name = NULL;
+
+          if (!write_formal_parameters (interface, method, channel, error))
+            goto io_lose;
+
+          WRITE_OR_LOSE (", GError **error)\n\n");
+
+          WRITE_OR_LOSE ("{\n");
+
+          if (is_noreply) {
+            if (!write_printf_to_iochannel ("  dbus_g_proxy_call_no_reply (proxy, \"%s\", ", channel, error,
+                    method_info_get_name (method)))
+              goto io_lose;
+
+            if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
+              goto io_lose;
+
+            WRITE_OR_LOSE ("G_TYPE_INVALID, ");
+
+            if (!write_args_for_direction (interface, method, channel, ARG_OUT, error))
+              goto io_lose;
+
+            WRITE_OR_LOSE ("G_TYPE_INVALID);\n");
+
+            WRITE_OR_LOSE ("  return TRUE;\n}\n\n");
+          } else {
+            if (!write_printf_to_iochannel ("  return dbus_g_proxy_call (proxy, \"%s\", ", channel, error,
+                    method_info_get_name (method)))
+              goto io_lose;
+
+            WRITE_OR_LOSE ("error, ");
+
+            if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
+              goto io_lose;
+
+            WRITE_OR_LOSE ("G_TYPE_INVALID, ");
+
+            if (!write_args_for_direction (interface, method, channel, ARG_OUT, error))
+              goto io_lose;
+
+            WRITE_OR_LOSE ("G_TYPE_INVALID);\n}\n\n");
+          }
+
+          write_async_method_client (channel, interface, method, error);
+        }
+
+      if (!write_printf_to_iochannel ("#endif /* defined DBUS_GLIB_CLIENT_WRAPPERS_%s */\n\n", channel, error, iface_prefix))
+        goto io_lose;
+
+      g_free (iface_prefix);
+    }
+  return TRUE;
+ io_lose:
+  g_free (method_c_name);
+  g_free (iface_prefix);
+  return FALSE;
+}
+
+
+gboolean
+dbus_binding_tool_output_glib_client (BaseInfo *info, GIOChannel *channel, gboolean ignore_unsupported, GError **error)
+{
+  DBusBindingToolCData data;
+  gboolean ret;
+
+  memset (&data, 0, sizeof (data));
+  
+  data.channel = channel;
+  data.ignore_unsupported = ignore_unsupported;
+
+  dbus_g_type_specialized_init ();
+  _dbus_g_type_specialized_builtins_init ();
+
+  WRITE_OR_LOSE ("/* Generated by dbus-binding-tool; do not edit! */\n\n");
+  WRITE_OR_LOSE ("#include <glib.h>\n");
+  WRITE_OR_LOSE ("#include <dbus/dbus-glib.h>\n\n");
+  WRITE_OR_LOSE ("G_BEGIN_DECLS\n\n");
+
+  WRITE_OR_LOSE ("#ifndef _DBUS_GLIB_ASYNC_DATA_FREE\n");
+  WRITE_OR_LOSE ("#define _DBUS_GLIB_ASYNC_DATA_FREE\n");
+  WRITE_OR_LOSE ("static inline void\n");
+  WRITE_OR_LOSE ("_dbus_glib_async_data_free (gpointer stuff)\n{\n\tg_slice_free (DBusGAsyncData, stuff);\n}\n");
+  WRITE_OR_LOSE ("#endif\n\n");
+
+  ret = generate_client_glue (info, &data, error);
+  if (!ret)
+    goto io_lose;
+  
+  WRITE_OR_LOSE ("G_END_DECLS\n");
+
+  return ret;
+ io_lose:
+  return FALSE;
+}
Index: dbus-glib-0.112-new/dbus/dbus-gvalue-utils.c
===================================================================
--- dbus-glib-0.112-new/dbus/dbus-gvalue-utils.c	(nonexistent)
+++ dbus-glib-0.112-new/dbus/dbus-gvalue-utils.c	(revision 5)
@@ -0,0 +1,1372 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-gvalue-utils.c: Non-DBus-specific functions related to GType/GValue 
+ *
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <config.h>
+#include "dbus/dbus-glib.h"
+#include "dbus-gtype-specialized-priv.h"
+#include "dbus-gvalue-utils.h"
+#include "dbus-gtest.h"
+#include <glib.h>
+#include <string.h>
+#include <gobject/gvaluecollector.h>
+
+
+static guint
+fixed_type_get_size (GType type)
+{
+  switch (type)
+    {
+    case G_TYPE_CHAR:
+    case G_TYPE_UCHAR:
+      return sizeof (gchar);
+    case G_TYPE_BOOLEAN:
+      return sizeof (gboolean);
+    case G_TYPE_LONG:
+    case G_TYPE_ULONG:
+      return sizeof (glong);
+    case G_TYPE_INT:
+    case G_TYPE_UINT:
+      return sizeof (gint);
+    case G_TYPE_INT64:
+    case G_TYPE_UINT64:
+      return sizeof (gint64);
+    case G_TYPE_FLOAT:
+      return sizeof (gfloat);
+    case G_TYPE_DOUBLE:
+      return sizeof (gdouble);
+    default:
+      return 0;
+    }
+}
+
+gboolean
+_dbus_g_type_is_fixed (GType type)
+{
+  return fixed_type_get_size (type) > 0;
+}
+
+guint
+_dbus_g_type_fixed_get_size (GType type)
+{
+  g_assert (_dbus_g_type_is_fixed (type));
+  return fixed_type_get_size (type);
+}
+
+gboolean
+_dbus_gvalue_store (GValue          *value,
+		   gpointer        storage)
+{
+  /* FIXME - can we use the GValue lcopy_value method
+   * to do this in a cleaner way?
+   */
+  switch (g_type_fundamental (G_VALUE_TYPE (value)))
+    {
+    case G_TYPE_CHAR:
+      *((gchar *) storage) = g_value_get_char (value);
+      return TRUE;
+    case G_TYPE_UCHAR:
+      *((guchar *) storage) = g_value_get_uchar (value);
+      return TRUE;
+    case G_TYPE_BOOLEAN:
+      *((gboolean *) storage) = g_value_get_boolean (value);
+      return TRUE;
+    case G_TYPE_LONG:
+      *((glong *) storage) = g_value_get_long (value);
+      return TRUE;
+    case G_TYPE_ULONG:
+      *((gulong *) storage) = g_value_get_ulong (value);
+      return TRUE;
+    case G_TYPE_INT:
+      *((gint *) storage) = g_value_get_int (value);
+      return TRUE;
+    case G_TYPE_UINT:
+      *((guint *) storage) = g_value_get_uint (value);
+      return TRUE;
+    case G_TYPE_INT64:
+      *((gint64 *) storage) = g_value_get_int64 (value);
+      return TRUE;
+    case G_TYPE_UINT64:
+      *((guint64 *) storage) = g_value_get_uint64 (value);
+      return TRUE;
+    case G_TYPE_DOUBLE:
+      *((gdouble *) storage) = g_value_get_double (value);
+      return TRUE;
+    case G_TYPE_STRING:
+      *((gchar **) storage) = (char*) g_value_get_string (value);
+      return TRUE;
+    case G_TYPE_OBJECT:
+      *((gpointer *) storage) = g_value_get_object (value);
+      return TRUE;
+    case G_TYPE_BOXED:
+      *((gpointer *) storage) = g_value_get_boxed (value);
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
+
+gboolean
+_dbus_gvalue_set_from_pointer (GValue          *value,
+			      gconstpointer    storage)
+{
+  /* FIXME - is there a better way to do this? */
+  switch (g_type_fundamental (G_VALUE_TYPE (value)))
+    {
+    case G_TYPE_CHAR:
+      g_value_set_char (value, *((gchar *) storage));
+      return TRUE;
+    case G_TYPE_UCHAR:
+      g_value_set_uchar (value, *((guchar *) storage));
+      return TRUE;
+    case G_TYPE_BOOLEAN:
+      g_value_set_boolean (value, *((gboolean *) storage));
+      return TRUE;
+    case G_TYPE_LONG:
+      g_value_set_long (value, *((glong *) storage));
+      return TRUE;
+    case G_TYPE_ULONG:
+      g_value_set_ulong (value, *((gulong *) storage));
+      return TRUE;
+    case G_TYPE_INT:
+      g_value_set_int (value, *((gint *) storage));
+      return TRUE;
+    case G_TYPE_UINT:
+      g_value_set_uint (value, *((guint *) storage));
+      return TRUE;
+    case G_TYPE_INT64:
+      g_value_set_int64 (value, *((gint64 *) storage));
+      return TRUE;
+    case G_TYPE_UINT64:
+      g_value_set_uint64 (value, *((guint64 *) storage));
+      return TRUE;
+    case G_TYPE_DOUBLE:
+      g_value_set_double (value, *((gdouble *) storage));
+      return TRUE;
+    case G_TYPE_STRING:
+      g_value_set_string (value, *((gchar **) storage));
+      return TRUE;
+    case G_TYPE_OBJECT:
+      g_value_set_object (value, *((gpointer *) storage));
+      return TRUE;
+    case G_TYPE_BOXED:
+      g_value_set_boxed (value, *((gpointer *) storage));
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
+
+gboolean
+_dbus_gvalue_take (GValue          *value,
+		  GTypeCValue     *cvalue)
+{
+  GType g_type;
+  GTypeValueTable *value_table;
+  char *error_msg;
+
+  g_type = G_VALUE_TYPE (value);
+  value_table = g_type_value_table_peek (g_type);
+
+  error_msg = value_table->collect_value (value, 1, cvalue, G_VALUE_NOCOPY_CONTENTS);
+  if (error_msg)
+    {
+      g_warning ("%s: %s", G_STRLOC, error_msg);
+      g_free (error_msg);
+      return FALSE;
+    }
+  /* Clear the NOCOPY_CONTENTS flag; we want to take ownership
+   * of the value.
+   */
+  value->data[1].v_uint &= ~(G_VALUE_NOCOPY_CONTENTS);
+  return TRUE;
+}
+
+gboolean
+_dbus_gtype_can_signal_error (GType gtype)
+{
+  switch (gtype)
+    {
+    case G_TYPE_BOOLEAN:
+    case G_TYPE_INT:
+    case G_TYPE_UINT:
+    case G_TYPE_STRING:
+    case G_TYPE_BOXED:
+    case G_TYPE_OBJECT:
+      return TRUE;
+    default:
+      return FALSE;
+    }
+}
+
+gboolean
+_dbus_gvalue_signals_error (const GValue *value)
+{
+  /* Hardcoded rules for return value semantics for certain
+   * types.  Perhaps in the future we'd want an annotation
+   * specifying which return values are errors, but in
+   * reality people will probably just use boolean and
+   * boxed, and there the semantics are pretty standard.
+   */
+  switch (G_TYPE_FUNDAMENTAL (G_VALUE_TYPE (value)))
+    {
+    case G_TYPE_BOOLEAN:
+      return (g_value_get_boolean (value) == FALSE);
+      break;
+    case G_TYPE_INT:
+      return (g_value_get_int (value) < 0);
+      break;
+    case G_TYPE_UINT:
+      return (g_value_get_uint (value) == 0);
+      break;
+    case G_TYPE_STRING:
+      return (g_value_get_string (value) == NULL);
+      break;
+    case G_TYPE_BOXED:
+      return (g_value_get_boxed (value) == NULL);
+      break;
+    case G_TYPE_OBJECT:
+      return (g_value_get_object (value) == NULL);
+      break;
+    default:
+      g_assert_not_reached ();
+      return FALSE;
+    }
+}
+
+
+static gboolean
+hash_func_from_gtype (GType gtype, GHashFunc *func)
+{
+  switch (gtype)
+    {
+    case G_TYPE_CHAR:
+    case G_TYPE_UCHAR:
+    case G_TYPE_BOOLEAN:
+    case G_TYPE_INT:
+    case G_TYPE_UINT:
+      *func = NULL;
+      return TRUE;
+    case G_TYPE_STRING:
+      *func = g_str_hash;
+      return TRUE;
+    default:
+      if (gtype == DBUS_TYPE_G_OBJECT_PATH)
+        {
+          *func = g_str_hash;
+          return TRUE;
+        }
+      else if (gtype == DBUS_TYPE_G_SIGNATURE)
+        {
+          *func = g_str_hash;
+          return TRUE;
+        }
+      return FALSE;
+    }
+}
+
+static void
+unset_and_free_g_value (gpointer val)
+{
+  GValue *value = val;
+
+  g_value_unset (value);
+  g_free (value);
+}
+
+static gboolean
+gtype_can_simple_free (GType type);
+
+static gboolean
+hash_simple_free_from_gtype (GType gtype, GDestroyNotify *func)
+{
+  switch (gtype)
+    {
+    case G_TYPE_CHAR:
+    case G_TYPE_UCHAR:
+    case G_TYPE_BOOLEAN:
+    case G_TYPE_INT:
+    case G_TYPE_UINT:
+      *func = NULL;
+      return TRUE;
+    case G_TYPE_DOUBLE:
+    case G_TYPE_STRING:
+      *func = g_free;
+      return TRUE;
+    default:
+      if (gtype == G_TYPE_VALUE)
+	{
+	  *func = unset_and_free_g_value;
+	  return TRUE;
+	}
+      else if (gtype == G_TYPE_ARRAY)
+        {
+          *func = (GDestroyNotify) g_value_array_free;
+          return TRUE;
+        }
+      else if (gtype == G_TYPE_STRV)
+        {
+          *func = (GDestroyNotify) g_strfreev;
+          return TRUE;
+        }
+      else if (gtype == DBUS_TYPE_G_OBJECT_PATH)
+        {
+          *func = g_free;
+          return TRUE;
+        }
+      else if (gtype == DBUS_TYPE_G_SIGNATURE)
+        {
+          *func = g_free;
+          return TRUE;
+        }
+      else if (dbus_g_type_is_collection (gtype))
+        {
+          const DBusGTypeSpecializedCollectionVtable* vtable;
+          vtable = dbus_g_type_collection_peek_vtable (gtype);
+          if (vtable->base_vtable.simple_free_func)
+            {
+              *func = vtable->base_vtable.simple_free_func;
+              return TRUE;
+            }
+        }
+      else if (dbus_g_type_is_map (gtype))
+        {
+          const DBusGTypeSpecializedMapVtable* vtable;
+          GType key_gtype, value_gtype;
+
+          key_gtype = dbus_g_type_get_map_key_specialization (gtype);
+          value_gtype = dbus_g_type_get_map_value_specialization (gtype);
+
+          /* if either the key or the value don't have "simple" (without a
+           * GType) free functions, then the hashtable's contents must be freed
+           * with hashtable_free, so the hashtable itself can't have a simple
+           * free function. */
+          if (!gtype_can_simple_free (key_gtype) ||
+              !gtype_can_simple_free (value_gtype))
+            return FALSE;
+
+          vtable = dbus_g_type_map_peek_vtable (gtype);
+          if (vtable->base_vtable.simple_free_func)
+            {
+              *func = vtable->base_vtable.simple_free_func;
+              return TRUE;
+            }
+        }
+      else if (dbus_g_type_is_struct (gtype))
+        {
+          const DBusGTypeSpecializedStructVtable *vtable;
+          vtable = dbus_g_type_struct_peek_vtable (gtype);
+          if (vtable->base_vtable.simple_free_func)
+            {
+              *func = vtable->base_vtable.simple_free_func;
+              return TRUE;
+            }
+        }
+      return FALSE;
+    }
+}
+
+static gboolean
+gtype_can_simple_free (GType type)
+{
+  GDestroyNotify func;
+  return hash_simple_free_from_gtype (type, &func);
+}
+
+gboolean
+_dbus_gtype_is_valid_hash_key (GType type)
+{
+  GHashFunc func;
+  return hash_func_from_gtype (type, &func);
+}
+
+gboolean
+_dbus_gtype_is_valid_hash_value (GType gtype)
+{
+  /* anything we can take into a GValue using gvalue_take_hash_value is fine */
+  switch (g_type_fundamental (gtype))
+    {
+    case G_TYPE_CHAR:
+    case G_TYPE_UCHAR:
+    case G_TYPE_BOOLEAN:
+    case G_TYPE_INT:
+    case G_TYPE_UINT:
+    case G_TYPE_DOUBLE:
+    case G_TYPE_STRING:
+    case G_TYPE_BOXED:
+    case G_TYPE_OBJECT:
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+GHashFunc
+_dbus_g_hash_func_from_gtype (GType gtype)
+{
+  GHashFunc func;
+  gboolean ret;
+  ret = hash_func_from_gtype (gtype, &func);
+  g_assert (ret != FALSE);
+  return func;
+}
+
+GEqualFunc
+_dbus_g_hash_equal_from_gtype (GType gtype)
+{
+  g_assert (_dbus_gtype_is_valid_hash_key (gtype));
+
+  switch (gtype)
+    {
+    case G_TYPE_CHAR:
+    case G_TYPE_UCHAR:
+    case G_TYPE_BOOLEAN:
+    case G_TYPE_INT:
+    case G_TYPE_UINT:
+      return NULL;
+    case G_TYPE_STRING:
+      return g_str_equal;
+    default:
+      if (gtype == DBUS_TYPE_G_OBJECT_PATH)
+        return g_str_equal;
+      else if (gtype == DBUS_TYPE_G_SIGNATURE)
+        return g_str_equal;
+      g_assert_not_reached ();
+      return NULL;
+    }
+}
+
+static void
+hash_fake_simple_free_func (gpointer val)
+{
+  /* Havoc would be proud... :P */
+  g_critical ("If you see this message then the author of this application or "
+      "one of its libraries has tried to remove or replace the value %p in a "
+      "hash table which was constructed by the D-Bus Glib bindings.\n\n"
+
+      "However, it was not possible for the bindings to provide a destroy "
+      "function to g_hash_table_new_full which is able to free this value, as "
+      "its GType must be known in order to free it. This means the memory "
+      "allocated to store the value has most likely just been leaked.\n\n"
+
+      "To avoid this error, the GHashTable (or keys/values \"stolen\" from "
+      "it) should be freed by using g_boxed_free as follows:\n"
+      "  g_boxed_free (dbus_g_type_get_map (\"GHashTable\", key_gtype, "
+      "value_gtype), hash_table);\n", val);
+}
+
+GDestroyNotify
+_dbus_g_hash_free_from_gtype (GType gtype)
+{
+  GDestroyNotify func;
+  gboolean ret;
+
+  ret = hash_simple_free_from_gtype (gtype, &func);
+
+  /* if the value doesn't have a simple free function, we cannot define a
+   * meaningful free function here. instead, this hash table must be freed
+   * using g_boxed_free so that the hash_free function gets invoked. if the
+   * user does not do so, we provide a fake free function to provide a warning
+   * in this case. */
+  if (ret == FALSE)
+    {
+      g_assert (_dbus_gtype_is_valid_hash_value (gtype));
+
+      func = hash_fake_simple_free_func;
+    }
+
+  return func;
+}
+
+static void gvalue_take_ptrarray_value (GValue *value, gpointer instance);
+
+static void
+gvalue_take_hash_value (GValue *value, gpointer instance)
+{
+  switch (g_type_fundamental (G_VALUE_TYPE (value)))
+    {
+    case G_TYPE_CHAR:
+      g_value_set_char (value, (gchar) GPOINTER_TO_INT (instance));
+      break;
+    case G_TYPE_UCHAR:
+      g_value_set_uchar (value, (guchar) GPOINTER_TO_UINT (instance));
+      break;
+    case G_TYPE_BOOLEAN:
+      g_value_set_boolean (value, (gboolean) GPOINTER_TO_UINT (instance));
+      break;
+    case G_TYPE_INT:
+      g_value_set_int (value, GPOINTER_TO_INT (instance));
+      break;
+    case G_TYPE_UINT:
+      g_value_set_uint (value, GPOINTER_TO_UINT (instance));
+      break;
+    case G_TYPE_DOUBLE:
+      g_value_set_double (value, *(gdouble *) instance);
+      break;
+    default:
+      gvalue_take_ptrarray_value (value, instance);
+      break;
+    }
+}
+
+static gpointer ptrarray_value_from_gvalue (const GValue *value);
+
+static gpointer
+hash_value_from_gvalue (GValue *value)
+{
+  switch (g_type_fundamental (G_VALUE_TYPE (value)))
+    {
+    case G_TYPE_CHAR:
+      return GINT_TO_POINTER ((int) g_value_get_char (value));
+      break;
+    case G_TYPE_UCHAR:
+      return GUINT_TO_POINTER ((guint) g_value_get_uchar (value));
+      break;
+    case G_TYPE_BOOLEAN:
+      return GUINT_TO_POINTER ((guint) g_value_get_boolean (value));
+      break;
+    case G_TYPE_INT:
+      return GINT_TO_POINTER (g_value_get_int (value));
+      break;
+    case G_TYPE_UINT:
+      return GUINT_TO_POINTER (g_value_get_uint (value));
+      break;
+    case G_TYPE_DOUBLE:
+      {
+        gdouble *p = (gdouble *) g_malloc0 (sizeof (gdouble));
+        *p = g_value_get_double (value);
+        return (gpointer) p;
+      }
+      break;
+    default:
+      return ptrarray_value_from_gvalue (value);
+      break;
+    }
+}
+
+struct DBusGHashTableValueForeachData
+{
+  DBusGTypeSpecializedMapIterator func;
+  GType key_type;
+  GType value_type;
+  gpointer data;
+};
+
+static void
+hashtable_foreach_with_values (gpointer key, gpointer value, gpointer user_data)
+{
+  GValue key_val = {0, };
+  GValue value_val = {0, };
+  struct DBusGHashTableValueForeachData *data = user_data;
+  
+  g_value_init (&key_val, data->key_type);
+  g_value_init (&value_val, data->value_type);
+  gvalue_take_hash_value (&key_val, key);
+  gvalue_take_hash_value (&value_val, value);
+
+  data->func (&key_val, &value_val, data->data);
+}
+
+
+static void
+hashtable_iterator (GType                           hash_type,
+		    gpointer                        instance,
+		    DBusGTypeSpecializedMapIterator iterator,
+		    gpointer                        user_data)
+{
+  struct DBusGHashTableValueForeachData data;
+  GType key_gtype;
+  GType value_gtype;
+
+  key_gtype = dbus_g_type_get_map_key_specialization (hash_type);
+  value_gtype = dbus_g_type_get_map_value_specialization (hash_type);
+
+  data.func = iterator;
+  data.key_type = key_gtype;
+  data.value_type = value_gtype;
+  data.data = user_data;
+
+  g_hash_table_foreach (instance, hashtable_foreach_with_values, &data);
+}
+
+void
+_dbus_g_hash_table_insert_steal_values (GHashTable *table,
+				       GValue     *key_val,
+				       GValue     *value_val)
+{
+  gpointer key, val;
+  
+  key = hash_value_from_gvalue (key_val);
+  val = hash_value_from_gvalue (value_val);
+
+  g_hash_table_insert (table, key, val);
+}
+
+static void
+hashtable_append (DBusGTypeSpecializedAppendContext *ctx,
+		  GValue                            *key,
+		  GValue                            *val)
+{
+  GHashTable *table;
+
+  table = g_value_get_boxed (ctx->val);
+  _dbus_g_hash_table_insert_steal_values (table, key, val);
+}
+
+static gpointer
+hashtable_constructor (GType type)
+{
+  GHashTable *ret;
+  GType key_gtype;
+  GType value_gtype;
+
+  key_gtype = dbus_g_type_get_map_key_specialization (type);
+  value_gtype = dbus_g_type_get_map_value_specialization (type);
+
+  ret = g_hash_table_new_full (_dbus_g_hash_func_from_gtype (key_gtype),
+			       _dbus_g_hash_equal_from_gtype (key_gtype),
+			       _dbus_g_hash_free_from_gtype (key_gtype),
+			       _dbus_g_hash_free_from_gtype (value_gtype));
+  return ret;
+}
+
+static void
+hashtable_insert_values (GHashTable       *table,
+			 const GValue     *key_val,
+			 const GValue     *value_val)
+{
+  GValue key_copy = {0, };
+  GValue value_copy = {0, };
+
+  g_value_init (&key_copy, G_VALUE_TYPE (key_val));
+  g_value_copy (key_val, &key_copy);
+  g_value_init (&value_copy, G_VALUE_TYPE (value_val));
+  g_value_copy (value_val, &value_copy);
+  
+  _dbus_g_hash_table_insert_steal_values (table, &key_copy, &value_copy);
+}
+
+static void
+hashtable_foreach_copy (const GValue *key, const GValue *val, gpointer data)
+{
+  hashtable_insert_values ((GHashTable *) data, key, val);
+}
+
+static gpointer
+hashtable_copy (GType type, gpointer src)
+{
+  GHashTable *ghash;
+  GHashTable *ret;
+  GValue hashval = {0,};
+
+  ghash = src;
+
+  ret = hashtable_constructor (type);
+
+  g_value_init (&hashval, type);
+  g_value_set_static_boxed (&hashval, ghash); 
+  dbus_g_type_map_value_iterate (&hashval, hashtable_foreach_copy, ret);
+  return ret;
+}
+
+/* we leave this here for backwards compatibility - any hash tables nested
+ * inside hash tables will use this as their free function if users were
+ * already relying on it, but dbus-glib itself will never use it directly as
+ * hashtable_free is also defined. */
+static void
+hashtable_simple_free (gpointer val)
+{
+  g_hash_table_unref (val);
+}
+
+struct DBusGHashTableFreeData
+{
+  GType key_gtype;
+  GType value_gtype;
+};
+
+static gboolean
+hashtable_free_foreach_steal (gpointer key,
+                              gpointer value,
+                              gpointer user_data)
+{
+  struct DBusGHashTableFreeData *data = user_data;
+  GValue val = { 0, };
+
+  g_value_init (&val, data->key_gtype);
+  gvalue_take_hash_value (&val, key);
+  g_value_unset (&val);
+
+  g_value_init (&val, data->value_gtype);
+  gvalue_take_hash_value (&val, value);
+  g_value_unset (&val);
+
+  return TRUE;
+}
+
+static void
+hashtable_free (GType type,
+                gpointer val)
+{
+  struct DBusGHashTableFreeData data = { 0, };
+  GHashTable *hash = val;
+
+  data.key_gtype = dbus_g_type_get_map_key_specialization (type);
+  data.value_gtype = dbus_g_type_get_map_value_specialization (type);
+
+  /* wheee, fun. two cases here. either:
+   *
+   * a) the keys and value types both have simple (ie, no * GType parameter is
+   * needed to know how to free them) free functions, in which case they were
+   * set as the hash free functions when the hash table was constructed.  in
+   * this case, it's sufficient for us to unref the hash table as before. we
+   * have to keep doing this in order to maintain compatibility with the ABI
+   * which was around before hash tables could contain types which don't have
+   * simple free functions (such as GPtrArrays of other stuff). for these
+   * tables, users were able to ref the hash tables and add/remove values, and
+   * rely on meaningful free functions.
+   *
+   * b) for any other key or value types where /do/ need to know the GType in
+   * order to free it, this function is the only "right" way to free the hash
+   * table. both the key and value free functions were set to print a big nasty
+   * warning, and we free the contents of the hashtable with foreach_steal.
+   */
+  if (gtype_can_simple_free (data.key_gtype) &&
+      gtype_can_simple_free (data.value_gtype))
+    {
+      g_hash_table_unref (hash);
+    }
+  else
+    {
+      g_hash_table_foreach_steal (hash, hashtable_free_foreach_steal, &data);
+      g_hash_table_unref (hash);
+    }
+}
+
+static gpointer
+valuearray_constructor (GType type)
+{
+  GValueArray *ret;
+  guint size = dbus_g_type_get_struct_size (type);
+  guint i;
+  ret = g_value_array_new (size);
+  for (i=0; i < size; i++)
+    {
+      GValue val = {0,};
+      g_value_init (&val, dbus_g_type_get_struct_member_type (type, i));
+      g_value_array_append(ret, &val);
+    }
+  return (gpointer)ret;
+}
+
+static gpointer
+valuearray_copy (GType type, gpointer src)
+{
+  return g_value_array_copy ((GValueArray*) src);
+}
+
+static void
+valuearray_simple_free (gpointer val)
+{
+  g_value_array_free (val);
+}
+
+static gboolean
+valuearray_get_member (GType type, gpointer instance,
+                       guint member, GValue *ret)
+{
+  GValueArray *va = (GValueArray*) instance;
+  const GValue *val;
+  if (member < dbus_g_type_get_struct_size (type))
+    {
+      val = g_value_array_get_nth (va, member);
+      g_value_copy (val, ret);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+static gboolean
+valuearray_set_member (GType type, gpointer instance,
+                       guint member, const GValue *member_type)
+{
+  GValueArray *va = (GValueArray*) instance;
+  GValue *vp;
+  if (member < dbus_g_type_get_struct_size (type))
+    {
+      vp = g_value_array_get_nth (va, member);
+      g_value_copy (member_type, vp);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+
+static gpointer
+array_constructor (GType type)
+{
+  GArray *array;
+  guint elt_size;
+  GType elt_type;
+  gboolean zero_terminated;
+  gboolean clear;
+
+  elt_type = dbus_g_type_get_collection_specialization (type);
+  g_assert (elt_type != G_TYPE_INVALID);
+
+  elt_size = _dbus_g_type_fixed_get_size (elt_type);
+
+  /* These are "safe" defaults */ 
+  zero_terminated = TRUE; /* ((struct _DBusGRealArray*) garray)->zero_terminated; */
+  clear = TRUE; /* ((struct _DBusGRealArray*) garray)->clear; */
+
+  array = g_array_new (zero_terminated, clear, elt_size);
+  return array;
+}
+
+static void
+array_iterator (GType garray_type,
+    gpointer instance,
+    DBusGTypeSpecializedCollectionIterator iterator,
+    gpointer user_data)
+{
+  GArray *array;
+  GType elt_gtype;
+  guint i;
+
+  array = instance;
+
+  elt_gtype = dbus_g_type_get_collection_specialization (garray_type);
+
+  for (i = 0; i < array->len; i++)
+    {
+      GValue val = {0, };
+      g_value_init (&val, elt_gtype);
+
+      switch (elt_gtype)
+        {
+          case G_TYPE_BOOLEAN:
+            g_value_set_boolean (&val, !!g_array_index (array, gboolean, i));
+            break;
+
+          case G_TYPE_FLOAT:
+            g_value_set_float (&val, g_array_index (array, gfloat, i));
+            break;
+
+          case G_TYPE_DOUBLE:
+            g_value_set_double (&val, g_array_index (array, gdouble, i));
+            break;
+
+          case G_TYPE_CHAR:
+            g_value_set_char (&val, g_array_index (array, gchar, i));
+            break;
+
+          case G_TYPE_UCHAR:
+            g_value_set_uchar (&val, g_array_index (array, guchar, i));
+            break;
+
+          case G_TYPE_INT:
+            g_value_set_int (&val, g_array_index (array, gint, i));
+            break;
+
+          case G_TYPE_UINT:
+            g_value_set_uint (&val, g_array_index (array, guint, i));
+            break;
+
+          case G_TYPE_LONG:
+            g_value_set_long (&val, g_array_index (array, glong, i));
+            break;
+
+          case G_TYPE_ULONG:
+            g_value_set_ulong (&val, g_array_index (array, gulong, i));
+            break;
+
+          case G_TYPE_INT64:
+            g_value_set_int64 (&val, g_array_index (array, gint64, i));
+            break;
+
+          case G_TYPE_UINT64:
+            g_value_set_uint64 (&val, g_array_index (array, guint64, i));
+            break;
+
+          default:
+            g_assert_not_reached ();
+        }
+
+      iterator (&val, user_data);
+    }
+}
+
+static void
+array_append (DBusGTypeSpecializedAppendContext *ctx,
+    GValue *value)
+{
+  GArray *array = g_value_get_boxed (ctx->val);
+  GType elt_gtype;
+  union {
+      guint64 u64;
+      gint64 i64;
+      gulong ul;
+      glong l;
+      guint u;
+      gint i;
+      guchar uc;
+      gchar c;
+      gboolean b;
+      gfloat f;
+      gdouble d;
+  } tmp;
+
+  elt_gtype = dbus_g_type_get_collection_specialization (
+      G_VALUE_TYPE (ctx->val));
+
+  switch (elt_gtype)
+    {
+      case G_TYPE_BOOLEAN:
+        tmp.b = g_value_get_boolean (value);
+        g_array_append_val (array, tmp.b);
+        break;
+
+      case G_TYPE_FLOAT:
+        tmp.f = g_value_get_float (value);
+        g_array_append_val (array, tmp.f);
+        break;
+
+      case G_TYPE_DOUBLE:
+        tmp.d = g_value_get_double (value);
+        g_array_append_val (array, tmp.d);
+        break;
+
+      case G_TYPE_CHAR:
+        tmp.c = g_value_get_char (value);
+        g_array_append_val (array, tmp.c);
+        break;
+
+      case G_TYPE_UCHAR:
+        tmp.uc = g_value_get_uchar (value);
+        g_array_append_val (array, tmp.uc);
+        break;
+
+      case G_TYPE_INT:
+        tmp.i = g_value_get_int (value);
+        g_array_append_val (array, tmp.i);
+        break;
+
+      case G_TYPE_UINT:
+        tmp.u = g_value_get_uint (value);
+        g_array_append_val (array, tmp.u);
+        break;
+
+      case G_TYPE_LONG:
+        tmp.l = g_value_get_long (value);
+        g_array_append_val (array, tmp.l);
+        break;
+
+      case G_TYPE_ULONG:
+        tmp.ul = g_value_get_ulong (value);
+        g_array_append_val (array, tmp.ul);
+        break;
+
+      case G_TYPE_INT64:
+        tmp.i64 = g_value_get_int64 (value);
+        g_array_append_val (array, tmp.i64);
+        break;
+
+      case G_TYPE_UINT64:
+        tmp.u64 = g_value_get_uint64 (value);
+        g_array_append_val (array, tmp.u64);
+        break;
+
+      default:
+        g_assert_not_reached ();
+    }
+}
+
+static gpointer
+array_copy (GType type, gpointer src)
+{
+  GArray *garray;
+  GArray *new;
+
+  garray = src;
+
+  new = array_constructor (type);
+  g_array_append_vals (new, garray->data, garray->len);
+
+  return new;
+}
+
+static void
+array_simple_free (gpointer val)
+{
+  GArray *array;
+  array = val;
+  g_array_free (array, TRUE);
+}
+
+static gboolean
+array_fixed_accessor (GType type, gpointer instance, gpointer *values, guint *len)
+{
+  GType elt_type;
+  GArray *array = instance;
+
+  elt_type = dbus_g_type_get_collection_specialization (type);
+  if (!_dbus_g_type_is_fixed (elt_type))
+    return FALSE;
+
+  *values = array->data;
+  *len = array->len;
+  return TRUE;
+}
+
+static gpointer
+ptrarray_constructor (GType type)
+{
+  /* Later we should determine a destructor, need g_ptr_array_destroy */
+  return g_ptr_array_new ();
+}
+
+static void
+gvalue_take_ptrarray_value (GValue *value, gpointer instance)
+{
+  switch (g_type_fundamental (G_VALUE_TYPE (value)))
+    {
+    case G_TYPE_STRING:
+      g_value_take_string (value, instance);
+      break;
+    case G_TYPE_BOXED:
+      g_value_take_boxed (value, instance);
+      break;
+    case G_TYPE_OBJECT:
+      g_value_take_object (value, instance);
+      break;
+    default:
+      g_assert_not_reached ();
+      break;
+    }
+}
+
+static gpointer
+ptrarray_value_from_gvalue (const GValue *value)
+{
+  GValue tmp = {0, };
+
+  /* if the NOCOPY flag is set, then value was created via set_static and hence
+   * is not owned by us. in order to preserve the "take" semantics that the API
+   * has in general (which avoids copying in the common case), we must copy any
+   * static values so that we can indiscriminately free the entire collection
+   * later. */
+  if (value->data[1].v_uint & G_VALUE_NOCOPY_CONTENTS)
+    {
+      g_value_init (&tmp, G_VALUE_TYPE (value));
+      g_value_copy (value, &tmp);
+      value = &tmp;
+    }
+
+  switch (g_type_fundamental (G_VALUE_TYPE (value)))
+    {
+    case G_TYPE_STRING:
+      return (gpointer) g_value_get_string (value);
+      break;
+    case G_TYPE_BOXED:
+      return g_value_get_boxed (value);
+      break;
+    case G_TYPE_OBJECT:
+      return g_value_get_object (value);
+      break;
+    default:
+      g_assert_not_reached ();
+      return NULL;
+    }
+}
+
+static void
+ptrarray_iterator (GType                                   ptrarray_type,
+		   gpointer                                instance,
+		   DBusGTypeSpecializedCollectionIterator  iterator,
+		   gpointer                                user_data)
+{
+  GPtrArray *ptrarray;
+  GType elt_gtype;
+  guint i;
+
+  ptrarray = instance;
+
+  elt_gtype = dbus_g_type_get_collection_specialization (ptrarray_type);
+
+  for (i = 0; i < ptrarray->len; i++)
+    {
+      GValue val = {0, };
+      g_value_init (&val, elt_gtype);
+      gvalue_take_ptrarray_value (&val, g_ptr_array_index (ptrarray, i));
+      iterator (&val, user_data);
+    }
+}
+
+static void
+ptrarray_copy_elt (const GValue *val, gpointer user_data)
+{
+  GPtrArray *dest = user_data;
+  GValue val_copy = {0, };
+
+  g_value_init (&val_copy, G_VALUE_TYPE (val));
+  g_value_copy (val, &val_copy);
+
+  g_ptr_array_add (dest, ptrarray_value_from_gvalue (&val_copy));
+}
+
+static gpointer
+ptrarray_copy (GType type, gpointer src)
+{
+  GPtrArray *new;
+  GValue array_val = {0, };
+
+  g_value_init (&array_val, type);
+  g_value_set_static_boxed (&array_val, src);
+
+  new = ptrarray_constructor (type);
+  dbus_g_type_collection_value_iterate (&array_val, ptrarray_copy_elt, new);
+
+  return new;
+}
+
+static void
+ptrarray_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
+{
+  GPtrArray *array;
+
+  array = g_value_get_boxed (ctx->val);
+
+  g_ptr_array_add (array, ptrarray_value_from_gvalue (value));
+}
+
+static void
+ptrarray_free (GType type, gpointer val)
+{
+  GPtrArray *array;
+  GValue elt_val = {0, };
+  GType elt_gtype;
+  unsigned int i;
+
+  array = val;
+
+  elt_gtype = dbus_g_type_get_collection_specialization (type);
+
+  for (i = 0; i < array->len; i++)
+    {
+      g_value_init (&elt_val, elt_gtype);
+      gvalue_take_ptrarray_value (&elt_val, g_ptr_array_index (array, i));
+      g_value_unset (&elt_val);
+    }
+
+  g_ptr_array_free (array, TRUE);
+}
+
+static gpointer
+slist_constructor (GType type)
+{
+  return NULL;
+}
+
+static void
+slist_iterator (GType                                   list_type,
+		gpointer                                instance,
+		DBusGTypeSpecializedCollectionIterator  iterator,
+		gpointer                                user_data)
+{
+  GSList *slist;
+  GType elt_gtype;
+
+  slist = instance;
+
+  elt_gtype = dbus_g_type_get_collection_specialization (list_type);
+
+  for (slist = instance; slist != NULL; slist = slist->next)
+    {
+      GValue val = {0, };
+      g_value_init (&val, elt_gtype);
+      gvalue_take_ptrarray_value (&val, slist->data);
+      iterator (&val, user_data);
+    }
+}
+
+static void
+slist_copy_elt (const GValue *val, gpointer user_data)
+{
+  GSList **dest = user_data;
+  GValue val_copy = {0, };
+
+  g_value_init (&val_copy, G_VALUE_TYPE (val));
+  g_value_copy (val, &val_copy);
+
+  *dest = g_slist_append (*dest, ptrarray_value_from_gvalue (&val_copy));
+}
+
+static gpointer
+slist_copy (GType type, gpointer src)
+{
+  GSList *new;
+  GValue slist_val = {0, };
+
+  g_value_init (&slist_val, type);
+  g_value_set_static_boxed (&slist_val, src);
+
+  new = slist_constructor (type);
+  dbus_g_type_collection_value_iterate (&slist_val, slist_copy_elt, &new);
+
+  return new;
+}
+
+static void
+slist_append (DBusGTypeSpecializedAppendContext *ctx, GValue *value)
+{
+  GSList *list;
+
+  list = g_value_get_boxed (ctx->val);
+  list = g_slist_prepend (list, ptrarray_value_from_gvalue (value));
+  g_value_set_static_boxed (ctx->val, list);
+}
+
+static void
+slist_end_append (DBusGTypeSpecializedAppendContext *ctx)
+{
+  GSList *list;
+
+  /* if you append multiple times to the slist, this will reverse the existing
+   * elements... we need an init_append function */
+  list = g_value_get_boxed (ctx->val);
+  list = g_slist_reverse (list);
+
+  g_value_take_boxed (ctx->val, list);
+}
+
+static void
+slist_free (GType type, gpointer val)
+{
+  GSList *list;
+  GType elt_gtype;
+  list = val;
+
+  elt_gtype = dbus_g_type_get_collection_specialization (type);
+
+  while (list != NULL)
+    {
+      GValue elt_val = {0, };
+      g_value_init (&elt_val, elt_gtype);
+      gvalue_take_ptrarray_value (&elt_val, list->data);
+      g_value_unset (&elt_val);
+      list = g_slist_next(list);
+    }
+  list=val;
+  g_slist_free (list);
+}
+
+void
+_dbus_g_type_specialized_builtins_init (void)
+{
+  /* types with a simple_free function can be freed at run-time without
+   * the destroy function needing to know the type, so they can be
+   * stored in hash tables */
+
+  static const DBusGTypeSpecializedCollectionVtable array_vtable = {
+    {
+      array_constructor,
+      NULL,
+      array_copy,
+      array_simple_free,
+      NULL,
+      NULL,
+    },
+    array_fixed_accessor,
+    array_iterator,
+    array_append,
+    NULL
+  };
+
+
+  static const DBusGTypeSpecializedCollectionVtable ptrarray_vtable = {
+    {
+      ptrarray_constructor,
+      ptrarray_free,
+      ptrarray_copy,
+      NULL,
+      NULL,
+      NULL,
+    },
+    NULL,
+    ptrarray_iterator,
+    ptrarray_append,
+    NULL,
+  };
+
+
+  static const DBusGTypeSpecializedCollectionVtable slist_vtable = {
+    {
+      slist_constructor,
+      slist_free,
+      slist_copy,
+      NULL,
+      NULL,
+      NULL,
+    },
+    NULL,
+    slist_iterator,
+    slist_append,
+    slist_end_append,
+  };
+
+  static const DBusGTypeSpecializedMapVtable hashtable_vtable = {
+    {
+      hashtable_constructor,
+      hashtable_free,
+      hashtable_copy,
+      hashtable_simple_free,
+      NULL,
+      NULL
+    },
+    hashtable_iterator,
+    hashtable_append
+  };
+
+  static const DBusGTypeSpecializedStructVtable valuearray_vtable = {
+    {
+      valuearray_constructor,
+      NULL,
+      valuearray_copy,
+      valuearray_simple_free,
+      NULL,
+      NULL
+    },
+    valuearray_get_member,
+    valuearray_set_member
+  };
+
+  _dbus_g_type_register_collection ("GSList", &slist_vtable, 0);
+  _dbus_g_type_register_collection ("GArray", &array_vtable, 0);
+  _dbus_g_type_register_collection ("GPtrArray", &ptrarray_vtable, 0);
+  _dbus_g_type_register_map ("GHashTable", &hashtable_vtable, 0);
+  _dbus_g_type_register_struct ("GValueArray", &valuearray_vtable, 0);
+}
Index: dbus-glib-0.112-new/dbus/dbus-gvalue.c
===================================================================
--- dbus-glib-0.112-new/dbus/dbus-gvalue.c	(nonexistent)
+++ dbus-glib-0.112-new/dbus/dbus-gvalue.c	(revision 5)
@@ -0,0 +1,2101 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-gvalue.c GValue to-from DBusMessageIter
+ *
+ * Copyright (C) 2004 Ximian, Inc.
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * SPDX-License-Identifier: AFL-2.1 OR GPL-2.0-or-later
+ *
+ * Licensed under the Academic Free License version 2.1
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include "config.h"
+#include "dbus-gtest.h"
+#include "dbus-gvalue.h"
+#include "dbus-gsignature.h"
+#include "dbus-gobject.h"
+#include "dbus-gvalue-utils.h"
+#include "dbus/dbus-glib.h"
+#include <string.h>
+#include <glib.h>
+#include "dbus/dbus-signature.h"
+
+/* Seems reasonable, but this should probably be part of the standard protocol */
+#define DBUS_GLIB_MAX_VARIANT_RECURSION 32
+
+static gboolean demarshal_static_variant (DBusGValueMarshalCtx    *context,
+					  DBusMessageIter         *iter,
+					  GValue                  *value,
+					  GError                 **error);
+
+
+static gboolean marshal_basic                   (DBusMessageIter           *iter,
+						 const GValue              *value);
+static gboolean demarshal_basic                 (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+static gboolean marshal_strv                    (DBusMessageIter           *iter,
+						 const GValue              *value);
+static gboolean demarshal_strv                  (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+static gboolean marshal_valuearray              (DBusMessageIter           *iter,
+						 const GValue              *value);
+static gboolean demarshal_valuearray            (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+static gboolean marshal_variant                 (DBusMessageIter           *iter,
+						 const GValue              *value);
+static gboolean demarshal_variant               (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+static gboolean marshal_proxy                   (DBusMessageIter           *iter,
+						 const GValue             *value);
+static gboolean demarshal_proxy                 (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+static gboolean marshal_object_path             (DBusMessageIter           *iter,
+						 const GValue             *value);
+static gboolean demarshal_object_path           (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+static gboolean marshal_object                  (DBusMessageIter           *iter,
+						 const GValue              *value);
+static gboolean demarshal_object                (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+static gboolean marshal_signature		(DBusMessageIter           *iter,
+						 const GValue             *value);
+static gboolean demarshal_signature		(DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+static gboolean marshal_map                     (DBusMessageIter           *iter,
+						 const GValue              *value);
+static gboolean demarshal_map                   (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+
+static gboolean marshal_collection              (DBusMessageIter           *iter,
+						 const GValue              *value);
+static gboolean marshal_collection_ptrarray     (DBusMessageIter           *iter,
+						 const GValue              *value);
+static gboolean marshal_collection_array        (DBusMessageIter           *iter,
+						 const GValue              *value);
+static gboolean demarshal_collection            (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+static gboolean demarshal_collection_ptrarray   (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+static gboolean demarshal_collection_array      (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+static gboolean marshal_struct                  (DBusMessageIter           *iter,
+						 const GValue              *value);
+static gboolean demarshal_struct                (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+
+
+typedef gboolean (*DBusGValueMarshalFunc)       (DBusMessageIter           *iter,
+						 const GValue              *value);
+typedef gboolean (*DBusGValueDemarshalFunc)     (DBusGValueMarshalCtx      *context,
+						 DBusMessageIter           *iter,
+						 GValue                    *value,
+						 GError                   **error);
+
+typedef struct {
+  DBusGValueMarshalFunc       marshaller;
+  DBusGValueDemarshalFunc     demarshaller;
+} DBusGTypeMarshalVtable;
+
+typedef struct {
+  const char                       *sig;
+  const DBusGTypeMarshalVtable     *vtable;
+} DBusGTypeMarshalData;
+
+static GQuark
+dbus_g_type_metadata_data_quark ()
+{
+  static GQuark quark;
+  if (!quark)
+    quark = g_quark_from_static_string ("DBusGTypeMetaData");
+  
+  return quark;
+}
+
+static void
+set_type_metadata (GType type, const DBusGTypeMarshalData *data)
+{
+  g_type_set_qdata (type, dbus_g_type_metadata_data_quark (), (gpointer) data);
+}
+
+static void
+register_basic (int typecode, const DBusGTypeMarshalData *typedata)
+{
+  set_type_metadata (_dbus_gtype_from_basic_typecode (typecode), typedata);
+}
+
+void
+_dbus_g_value_types_init (void)
+{
+  static gboolean types_initialized;
+
+  static const DBusGTypeMarshalVtable basic_vtable = {
+    marshal_basic,
+    demarshal_basic
+  };
+
+  if (types_initialized)
+    return;
+
+  dbus_g_type_specialized_init ();
+
+  /* Register basic types */
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_BOOLEAN_AS_STRING,
+      &basic_vtable,
+    };
+    register_basic (DBUS_TYPE_BOOLEAN, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_BYTE_AS_STRING,
+      &basic_vtable,
+    };
+    register_basic (DBUS_TYPE_BYTE, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_INT16_AS_STRING,
+      &basic_vtable,
+    };
+    register_basic (DBUS_TYPE_INT16, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_UINT16_AS_STRING,
+      &basic_vtable,
+    };
+    register_basic (DBUS_TYPE_UINT16, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_UINT32_AS_STRING,
+      &basic_vtable,
+    };
+    register_basic (DBUS_TYPE_UINT32, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_INT32_AS_STRING,
+      &basic_vtable,
+    };
+    register_basic (DBUS_TYPE_INT32, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_UINT64_AS_STRING,
+      &basic_vtable,
+    };
+    register_basic (DBUS_TYPE_UINT64, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_INT64_AS_STRING,
+      &basic_vtable,
+    };
+    register_basic (DBUS_TYPE_INT64, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_DOUBLE_AS_STRING,
+      &basic_vtable,
+    };
+    register_basic (DBUS_TYPE_DOUBLE, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_STRING_AS_STRING,
+      &basic_vtable,
+    };
+    register_basic (DBUS_TYPE_STRING, &typedata);
+  }
+  /* fundamental GTypes that don't map 1:1 with D-BUS types */
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_BYTE_AS_STRING,
+      &basic_vtable,
+    };
+    set_type_metadata (G_TYPE_CHAR, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_INT32_AS_STRING,
+      &basic_vtable,
+    };
+    set_type_metadata (G_TYPE_LONG, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_UINT32_AS_STRING,
+      &basic_vtable,
+    };
+    set_type_metadata (G_TYPE_ULONG, &typedata);
+  }
+  {
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_DOUBLE_AS_STRING,
+      &basic_vtable,
+    };
+    set_type_metadata (G_TYPE_FLOAT, &typedata);
+  }
+
+  /* Register complex types with builtin GType mappings */
+  {
+    static const DBusGTypeMarshalVtable vtable = {
+      marshal_variant,
+      demarshal_variant
+    };
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_VARIANT_AS_STRING,
+      &vtable
+    };
+    set_type_metadata (G_TYPE_VALUE, &typedata);
+  };
+  {
+    static const DBusGTypeMarshalVtable vtable = {
+      marshal_strv,
+      demarshal_strv
+    };
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
+      &vtable
+    };
+    set_type_metadata (G_TYPE_STRV, &typedata);
+  };
+
+
+  /* Register some types specific to the D-BUS GLib bindings */
+  {
+    static const DBusGTypeMarshalVtable vtable = {
+      marshal_proxy,
+      demarshal_proxy
+    };
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_OBJECT_PATH_AS_STRING,
+      &vtable
+    };
+    set_type_metadata (DBUS_TYPE_G_PROXY, &typedata);
+  }
+
+  {
+    static const DBusGTypeMarshalVtable vtable = {
+      marshal_object_path,
+      demarshal_object_path
+    };
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_OBJECT_PATH_AS_STRING,
+      &vtable
+    };
+    set_type_metadata (DBUS_TYPE_G_OBJECT_PATH, &typedata);
+  }
+
+  {
+    static const DBusGTypeMarshalVtable vtable = {
+      marshal_object,
+      demarshal_object
+    };
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_OBJECT_PATH_AS_STRING,
+      &vtable
+    };
+    set_type_metadata (G_TYPE_OBJECT, &typedata);
+  }
+
+  {
+    static const DBusGTypeMarshalVtable vtable = {
+      marshal_signature,
+      demarshal_signature
+    };
+    static const DBusGTypeMarshalData typedata = {
+      DBUS_TYPE_SIGNATURE_AS_STRING,
+      &vtable
+    };
+    set_type_metadata (DBUS_TYPE_G_SIGNATURE, &typedata);
+  }
+
+  types_initialized = TRUE;
+}
+
+/**
+ * DBusGObjectPath:
+ *
+ * A typedef for a string used to represent D-Bus object paths.
+ * Its GType is %DBUS_TYPE_G_OBJECT_PATH, derived from %G_TYPE_BOXED.
+ *
+ * Prior to version 0.FIXME this was used as the type name of
+ * %DBUS_TYPE_G_OBJECT_PATH, but did not actually exist as a typedef.
+ *
+ * Since: 0.FIXME
+ *
+ * Deprecated: New code should use GDBus instead. The closest equivalent
+ *  is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_OBJECT_PATH.
+ */
+
+/**
+ * DBUS_TYPE_G_OBJECT_PATH:
+ *
+ * The #GType of a #DBusGObjectPath, which is a boxed type containing a
+ * D-Bus object path as a zero-terminated string. Object paths can be
+ * copied with g_strdup() and freed with g_free(), just like %G_TYPE_STRING,
+ * but have a distinct boxed type to allow them to be distinguished when
+ * stored in a #GValue.
+ *
+ * Returns: a type derived from %G_TYPE_BOXED
+ *
+ * Deprecated: New code should use GDBus instead. The closest equivalent
+ *  is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_OBJECT_PATH.
+ */
+GType
+dbus_g_object_path_get_g_type (void)
+{
+  static GType type_id = 0;
+
+  if (!type_id)
+    type_id = g_boxed_type_register_static ("DBusGObjectPath",
+					    (GBoxedCopyFunc) g_strdup,
+					    (GBoxedFreeFunc) g_free);
+  return type_id;
+}
+
+/**
+ * DBusGSignature:
+ *
+ * A typedef for a string used to represent D-Bus signatures.
+ * Its GType is %DBUS_TYPE_G_SIGNATURE, derived from %G_TYPE_BOXED.
+ *
+ * Prior to version 0.FIXME this was used as the type name of
+ * %DBUS_TYPE_G_SIGNATURE, but did not actually exist as a typedef.
+ *
+ * Since: 0.FIXME
+ *
+ * Deprecated: New code should use GDBus instead. The closest equivalent
+ *  is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_SIGNATURE.
+ */
+
+/**
+ * DBUS_TYPE_G_SIGNATURE:
+ *
+ * The #GType of a #DBusGSignature, which is a boxed type containing a
+ * D-Bus signature as a zero-terminated string. Signatures can be
+ * copied with g_strdup() and freed with g_free(), just like %G_TYPE_STRING,
+ * but have a distinct boxed type to allow them to be distinguished when
+ * stored in a #GValue.
+ *
+ * Returns: a type derived from %G_TYPE_BOXED
+ *
+ * Deprecated: New code should use GDBus instead. The closest equivalent
+ *  is a #GVariant (%G_TYPE_VARIANT) of type %G_VARIANT_TYPE_SIGNATURE.
+ */
+GType
+dbus_g_signature_get_g_type (void)
+{
+  static GType type_id = 0;
+
+  if (G_UNLIKELY (type_id == 0))
+    type_id = g_boxed_type_register_static ("DBusGSignature",
+					    (GBoxedCopyFunc) g_strdup,
+					    (GBoxedFreeFunc) g_free);
+
+  return type_id;
+}
+
+
+char *
+_dbus_gtype_to_signature (GType gtype)
+{
+  char *ret;
+  DBusGTypeMarshalData *typedata;
+
+  if (dbus_g_type_is_collection (gtype))
+    {
+      GType elt_gtype;
+      char *subsig;
+
+      elt_gtype = dbus_g_type_get_collection_specialization (gtype);
+      subsig = _dbus_gtype_to_signature (elt_gtype);
+      ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING, subsig, NULL);
+      g_free (subsig);
+    }
+  else if (dbus_g_type_is_map (gtype))
+    {
+      GType key_gtype;
+      GType val_gtype;
+      char *key_subsig;
+      char *val_subsig;
+
+      key_gtype = dbus_g_type_get_map_key_specialization (gtype);
+      val_gtype = dbus_g_type_get_map_value_specialization (gtype);
+      key_subsig = _dbus_gtype_to_signature (key_gtype);
+      val_subsig = _dbus_gtype_to_signature (val_gtype);
+      ret = g_strconcat (DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING, key_subsig, val_subsig, DBUS_DICT_ENTRY_END_CHAR_AS_STRING, NULL);
+      g_free (key_subsig);
+      g_free (val_subsig);
+    }
+  else if (dbus_g_type_is_struct (gtype))
+    {
+      guint i, size;
+      GString *sig;
+      size = dbus_g_type_get_struct_size (gtype);
+      sig = g_string_sized_new (size+2); /*some sensible starting size*/
+      g_string_assign (sig, DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
+      for (i = 0; i < size; i++)
+        {
+          gchar *subsig;
+          subsig = _dbus_gtype_to_signature (
+              dbus_g_type_get_struct_member_type (gtype, i));
+          g_string_append (sig, subsig);
+          g_free (subsig);
+        }
+      g_string_append (sig, DBUS_STRUCT_END_CHAR_AS_STRING);
+      ret = g_string_free (sig, FALSE);
+    }
+  else
+    {
+      typedata = g_type_get_qdata (gtype, dbus_g_type_metadata_data_quark ());
+      if (typedata == NULL)
+	return NULL;
+      ret = g_strdup (typedata->sig);
+    }
+  return ret;
+}
+
+char *
+_dbus_gvalue_to_signature (const GValue *val)
+{
+  GType gtype;
+
+  gtype = G_VALUE_TYPE (val);
+  if (g_type_is_a (gtype, G_TYPE_ARRAY))
+    {
+      GString *str;
+      guint i;
+      GValueArray *array;
+
+      array = g_value_get_boxed (val);
+      
+      str = g_string_new (DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
+      for (i = 0; i < array->n_values; i++)
+	{
+	  char *sig;
+	  sig = _dbus_gvalue_to_signature (g_value_array_get_nth (array, i));
+	  g_string_append (str, sig);
+	  g_free (sig);
+	}
+      g_string_append (str, DBUS_STRUCT_END_CHAR_AS_STRING);
+      
+      return g_string_free (str, FALSE);
+    }
+  else
+    return _dbus_gtype_to_signature (gtype);
+}
+
+static gboolean
+demarshal_basic (DBusGValueMarshalCtx      *context,
+		 DBusMessageIter           *iter,
+		 GValue                    *value,
+		 GError                   **error)
+{
+  int current_type;
+  
+  current_type = dbus_message_iter_get_arg_type (iter);
+  g_assert (dbus_type_is_basic (current_type));
+
+  switch (current_type)
+    {
+    case DBUS_TYPE_BOOLEAN:
+      {
+	dbus_bool_t bool;
+        if (!G_VALUE_HOLDS (value, G_TYPE_BOOLEAN))
+          goto invalid_type;
+	dbus_message_iter_get_basic (iter, &bool);
+	g_value_set_boolean (value, bool);
+	return TRUE;
+      }
+    case DBUS_TYPE_BYTE:
+      {
+	unsigned char byte;
+        if (!G_VALUE_HOLDS (value, G_TYPE_UCHAR))
+          goto invalid_type;
+	dbus_message_iter_get_basic (iter, &byte);
+	g_value_set_uchar (value, byte);
+	return TRUE;
+      }
+    case DBUS_TYPE_INT32:
+      {
+	dbus_int32_t intval;
+        if (!G_VALUE_HOLDS (value, G_TYPE_INT))
+          goto invalid_type;
+	dbus_message_iter_get_basic (iter, &intval);
+	g_value_set_int (value, intval);
+	return TRUE;
+      }
+    case DBUS_TYPE_UINT32:
+      {
+	dbus_uint32_t intval;
+        if (!G_VALUE_HOLDS (value, G_TYPE_UINT))
+          goto invalid_type;
+	dbus_message_iter_get_basic (iter, &intval);
+	g_value_set_uint (value, intval);
+	return TRUE;
+      }
+    case DBUS_TYPE_INT64:
+      {
+	dbus_int64_t intval;
+        if (!G_VALUE_HOLDS (value, G_TYPE_INT64))
+          goto invalid_type;
+	dbus_message_iter_get_basic (iter, &intval);
+	g_value_set_int64 (value, intval);
+	return TRUE;
+      }
+    case DBUS_TYPE_UINT64:
+      {
+	dbus_uint64_t intval;
+        if (!G_VALUE_HOLDS (value, G_TYPE_UINT64))
+          goto invalid_type;
+	dbus_message_iter_get_basic (iter, &intval);
+	g_value_set_uint64 (value, intval);
+	return TRUE;
+      }
+    case DBUS_TYPE_DOUBLE:
+      {
+	double dval;
+        if (!G_VALUE_HOLDS (value, G_TYPE_DOUBLE))
+          goto invalid_type;
+	dbus_message_iter_get_basic (iter, &dval);
+	g_value_set_double (value, dval);
+	return TRUE;
+      }
+    case DBUS_TYPE_INT16:
+      {
+        dbus_int16_t v;
+        if (!G_VALUE_HOLDS (value, G_TYPE_INT))
+          goto invalid_type;
+        dbus_message_iter_get_basic (iter, &v);
+        g_value_set_int (value, v);
+	return TRUE;
+      }
+    case DBUS_TYPE_UINT16:
+      {
+        dbus_uint16_t v;
+        if (!G_VALUE_HOLDS (value, G_TYPE_UINT))
+          goto invalid_type;
+        dbus_message_iter_get_basic (iter, &v);
+        g_value_set_uint (value, v);
+	return TRUE;
+      }
+    case DBUS_TYPE_STRING:
+      {
+        const char *s;
+        if (!G_VALUE_HOLDS (value, G_TYPE_STRING))
+          goto invalid_type;
+        dbus_message_iter_get_basic (iter, &s);
+	g_value_set_string (value, s);
+	return TRUE;
+      }
+    default:
+      /* fall through to invalid_type */
+      break;
+    }
+  invalid_type:
+    g_set_error (error,
+                 DBUS_GERROR,
+                 DBUS_GERROR_INVALID_ARGS,
+                 "Expected type %s, got type code \'%c\'",
+                 g_type_name (G_VALUE_TYPE (value)),
+                 (guchar) current_type);
+    return FALSE;
+}
+
+static gboolean
+demarshal_static_variant (DBusGValueMarshalCtx    *context,
+			  DBusMessageIter         *iter,
+			  GValue                  *value,
+			  GError                 **error)
+{
+  char *sig;
+  DBusMessageIter subiter;
+  GType variant_type;
+
+  dbus_message_iter_recurse (iter, &subiter);
+  sig = dbus_message_iter_get_signature (&subiter);
+
+  variant_type = _dbus_gtype_from_signature (sig, context->proxy != NULL);
+  if (variant_type == G_TYPE_INVALID)
+    {
+      /* It can happen if we received an unknown type such as
+       * DBUS_TYPE_UNIX_FD or DBUS_TYPE_MAYBE. */
+      g_set_error (error, DBUS_GERROR,
+                   DBUS_GERROR_INVALID_SIGNATURE,
+                   "Variant contains unknown signature \'%s\'", sig);
+      dbus_free (sig);
+      return FALSE;
+    }
+
+  dbus_free (sig);
+
+  g_value_init (value, variant_type);
+
+  if (!_dbus_gvalue_demarshal (context, &subiter, value, error))
+    return FALSE;
+
+  return TRUE;
+}
+
+static gboolean
+demarshal_variant (DBusGValueMarshalCtx    *context,
+		   DBusMessageIter         *iter,
+		   GValue                  *value,
+		   GError                 **error)
+
+{
+  GValue *variant_val;
+  variant_val = g_new0 (GValue, 1);
+
+  if (!demarshal_static_variant (context, iter, variant_val, error))
+    return FALSE;
+  
+  g_value_take_boxed (value, variant_val);
+  return TRUE;
+}
+
+static gboolean
+demarshal_proxy (DBusGValueMarshalCtx    *context,
+		 DBusMessageIter         *iter,
+		 GValue                  *value,
+		 GError                 **error)
+{
+  DBusGProxy *new_proxy;
+  const char *objpath;
+  int current_type;
+
+  current_type = dbus_message_iter_get_arg_type (iter);
+  if (current_type != DBUS_TYPE_OBJECT_PATH)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
+      return FALSE;
+    }
+
+  g_assert (context->proxy != NULL);
+  
+  dbus_message_iter_get_basic (iter, &objpath);
+
+  new_proxy = dbus_g_proxy_new_from_proxy (context->proxy, NULL, objpath);
+  g_value_take_object (value, new_proxy);
+
+  return TRUE;
+}
+
+static gboolean
+demarshal_object_path (DBusGValueMarshalCtx    *context,
+		       DBusMessageIter         *iter,
+		       GValue                  *value,
+		       GError                 **error)
+{
+  const char *objpath;
+  int current_type;
+
+  current_type = dbus_message_iter_get_arg_type (iter);
+  if (current_type != DBUS_TYPE_OBJECT_PATH)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
+      return FALSE;
+    }
+
+  dbus_message_iter_get_basic (iter, &objpath);
+
+  g_value_set_boxed (value, objpath);
+
+  return TRUE;
+}
+
+static gboolean
+demarshal_object (DBusGValueMarshalCtx    *context,
+		  DBusMessageIter         *iter,
+		  GValue                  *value,
+		  GError                 **error)
+{
+  const char *objpath;
+  int current_type;
+  GObject *obj;
+
+  current_type = dbus_message_iter_get_arg_type (iter);
+  if (current_type != DBUS_TYPE_OBJECT_PATH)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Expected D-BUS object path, got type code \'%c\'", (guchar) current_type);
+      return FALSE;
+    }
+  g_assert (context->proxy == NULL);
+
+  dbus_message_iter_get_basic (iter, &objpath);
+
+  obj = dbus_g_connection_lookup_g_object (context->gconnection, objpath);
+  if (obj == NULL)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Unregistered object at path '%s'",
+		   objpath);
+      return FALSE;
+    }
+  g_value_set_object (value, obj);
+
+  return TRUE;
+}
+
+static gboolean
+demarshal_signature (DBusGValueMarshalCtx    *context,
+		     DBusMessageIter         *iter,
+		     GValue                  *value,
+		     GError                 **error)
+{
+  const char *sig;
+  int current_type;
+
+  current_type = dbus_message_iter_get_arg_type (iter);
+  if (current_type != DBUS_TYPE_SIGNATURE)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Expected D-BUS signature, got type code \'%c\'", (guchar) current_type);
+      return FALSE;
+    }
+
+  dbus_message_iter_get_basic (iter, &sig);
+
+  g_value_set_boxed (value, sig);
+
+  return TRUE;
+}
+
+static gboolean
+demarshal_strv (DBusGValueMarshalCtx    *context,
+		DBusMessageIter         *iter,
+		GValue                  *value,
+		GError                 **error)
+{
+  DBusMessageIter subiter;
+  int current_type;
+  GArray *arr;
+
+  current_type = dbus_message_iter_get_arg_type (iter);
+  if (current_type != DBUS_TYPE_ARRAY)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
+      return FALSE;
+    }
+
+  dbus_message_iter_recurse (iter, &subiter);
+
+  current_type = dbus_message_iter_get_arg_type (&subiter);
+  if (current_type != DBUS_TYPE_INVALID
+      && current_type != DBUS_TYPE_STRING)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Expected D-BUS string, got type code \'%c\'", (guchar) current_type);
+      return FALSE;
+    }
+
+  arr = g_array_new (TRUE, FALSE, sizeof (char *));
+
+  while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
+    {
+      g_assert (current_type == DBUS_TYPE_STRING);
+      const char *str;
+      char *copy;
+      
+      dbus_message_iter_get_basic (&subiter, &str);
+      copy = g_strdup (str);
+      g_array_append_val (arr, copy);
+
+      dbus_message_iter_next (&subiter);
+    }
+
+  g_value_take_boxed (value, arr->data);
+  g_array_free (arr, FALSE);
+  
+  return TRUE;
+}
+
+static gboolean
+demarshal_valuearray (DBusGValueMarshalCtx    *context,
+		      DBusMessageIter         *iter,
+		      GValue                  *value,
+		      GError                 **error)
+{
+  int current_type;
+  GValueArray *ret;
+  DBusMessageIter subiter;
+
+  current_type = dbus_message_iter_get_arg_type (iter);
+  if (current_type != DBUS_TYPE_STRUCT)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Expected D-BUS struct, got type code \'%c\'", (guchar) current_type);
+      return FALSE;
+    }
+
+  dbus_message_iter_recurse (iter, &subiter);
+
+  ret = g_value_array_new (12);
+
+  while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
+    {
+      GValue *val;
+      GType elt_type; 
+      char *current_sig;
+
+      g_value_array_append (ret, NULL);
+      val = g_value_array_get_nth (ret, ret->n_values - 1);
+
+      current_sig = dbus_message_iter_get_signature (&subiter);
+      elt_type = _dbus_gtype_from_signature (current_sig, TRUE);
+
+      if (elt_type == G_TYPE_INVALID)
+	{
+	  g_value_array_free (ret);
+	  g_set_error (error,
+		       DBUS_GERROR,
+		       DBUS_GERROR_INVALID_ARGS,
+		       "Couldn't demarshal argument with signature \"%s\"", current_sig);
+	  dbus_free (current_sig);
+	  return FALSE;
+	}
+      dbus_free (current_sig);
+      
+      g_value_init (val, elt_type);
+
+      if (!_dbus_gvalue_demarshal (context, &subiter, val, error))
+	{
+	  g_value_array_free (ret);
+	  return FALSE;
+	}
+
+      dbus_message_iter_next (&subiter);
+    }
+
+  g_value_take_boxed (value, ret);
+  
+  return TRUE;
+}
+
+static gboolean
+demarshal_map (DBusGValueMarshalCtx    *context,
+	       DBusMessageIter         *iter,
+	       GValue                  *value,
+	       GError                 **error)
+{
+  GType gtype;
+  DBusMessageIter subiter;
+  int current_type;
+  gpointer ret;
+  GType key_gtype;
+  GType value_gtype;
+  DBusGTypeSpecializedAppendContext appendctx;
+
+  current_type = dbus_message_iter_get_arg_type (iter);
+  if (current_type != DBUS_TYPE_ARRAY)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
+      return FALSE;
+    }
+
+  gtype = G_VALUE_TYPE (value);
+
+  dbus_message_iter_recurse (iter, &subiter);
+
+  current_type = dbus_message_iter_get_arg_type (&subiter);
+  if (current_type != DBUS_TYPE_INVALID
+      && current_type != DBUS_TYPE_DICT_ENTRY)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Expected D-BUS dict entry, got type code \'%c\'", (guchar) current_type);
+      return FALSE;
+    }
+
+  key_gtype = dbus_g_type_get_map_key_specialization (gtype);
+  value_gtype = dbus_g_type_get_map_value_specialization (gtype);
+
+  ret = dbus_g_type_specialized_construct (gtype);
+  g_value_take_boxed (value, ret);
+
+  dbus_g_type_specialized_init_append (value, &appendctx);
+
+  while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
+    {
+      DBusMessageIter entry_iter;
+      GValue key_value = {0,};
+      GValue value_value = {0,};
+
+      current_type = dbus_message_iter_get_arg_type (&subiter);
+      g_assert (current_type == DBUS_TYPE_DICT_ENTRY);
+
+      dbus_message_iter_recurse (&subiter, &entry_iter);
+
+      g_value_init (&key_value, key_gtype);
+      if (!_dbus_gvalue_demarshal (context,
+				  &entry_iter,
+				  &key_value,
+				  error))
+	return FALSE;
+
+      dbus_message_iter_next (&entry_iter);
+
+      g_value_init (&value_value, value_gtype);
+      if (!_dbus_gvalue_demarshal (context,
+				  &entry_iter,
+				  &value_value,
+				  error))
+	return FALSE;
+
+      dbus_g_type_specialized_map_append (&appendctx, &key_value, &value_value);
+      /* Ownership of values passes to map, don't unset */
+
+      dbus_message_iter_next (&subiter);
+    }
+  
+  return TRUE;
+}
+
+static gboolean
+demarshal_struct (DBusGValueMarshalCtx    *context,
+                  DBusMessageIter         *iter,
+                  GValue                  *value,
+                  GError                 **error)
+{
+  int current_type;
+  DBusMessageIter subiter;
+  guint i, size;
+  GValue val = {0,};
+  GType elt_type;
+
+  current_type = dbus_message_iter_get_arg_type (iter);
+  if (current_type != DBUS_TYPE_STRUCT)
+    {
+      g_set_error (error,
+                   DBUS_GERROR,
+                   DBUS_GERROR_INVALID_ARGS,
+                   "Expected D-BUS struct, got type code \'%c\'", (guchar) current_type);
+      return FALSE;
+    }
+
+  dbus_message_iter_recurse (iter, &subiter);
+
+  g_value_take_boxed (value,
+    dbus_g_type_specialized_construct (G_VALUE_TYPE (value)));
+
+  size = dbus_g_type_get_struct_size (G_VALUE_TYPE (value));
+
+  for (i=0; i < size; i++)
+    {
+
+      elt_type = dbus_g_type_get_struct_member_type (G_VALUE_TYPE(value), i);
+      if (elt_type == G_TYPE_INVALID)
+        {
+          g_value_unset (value);
+          g_set_error (error,
+                       DBUS_GERROR,
+                       DBUS_GERROR_INVALID_ARGS,
+                       "Couldn't demarshal argument, "
+                         "struct type %s has no member %d",
+                       g_type_name (G_VALUE_TYPE(value)), i);
+          return FALSE;
+        }
+
+      g_value_init (&val, elt_type);
+
+      if (!_dbus_gvalue_demarshal (context, &subiter, &val, error))
+        {
+          g_value_unset (&val);
+          g_value_unset (value);
+          return FALSE;
+        }
+      if (!dbus_g_type_struct_set_member (value, i, &val))
+        {
+          g_value_unset (&val);
+          g_value_unset (value);
+          return FALSE;
+        }
+
+      dbus_message_iter_next (&subiter);
+      g_value_unset (&val);
+    }
+
+  g_assert (dbus_message_iter_get_arg_type (&subiter) == DBUS_TYPE_INVALID);
+
+  return TRUE;
+}
+
+
+static DBusGValueDemarshalFunc
+get_type_demarshaller (GType type)
+{
+  DBusGTypeMarshalData *typedata;
+
+  typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
+  if (typedata == NULL)
+    {
+      if (g_type_is_a (type, G_TYPE_ARRAY))
+	return demarshal_valuearray;
+      if (dbus_g_type_is_collection (type))
+	return demarshal_collection;
+      if (dbus_g_type_is_map (type))
+	return demarshal_map;
+      if (dbus_g_type_is_struct (type))
+        return demarshal_struct;
+
+      g_warning ("No demarshaller registered for type \"%s\"", g_type_name (type));
+      return NULL;
+    }
+  g_assert (typedata->vtable);
+  return typedata->vtable->demarshaller;
+}
+
+static gboolean
+demarshal_collection (DBusGValueMarshalCtx    *context,
+		      DBusMessageIter         *iter,
+		      GValue                  *value,
+		      GError                 **error)
+{
+  GType coltype;
+  GType subtype;
+  
+  coltype = G_VALUE_TYPE (value);
+  subtype = dbus_g_type_get_collection_specialization (coltype);
+
+  if (_dbus_g_type_is_fixed (subtype))
+    return demarshal_collection_array (context, iter, value, error);
+  else
+    return demarshal_collection_ptrarray (context, iter, value, error);
+}
+
+static gboolean
+demarshal_collection_ptrarray (DBusGValueMarshalCtx    *context,
+			       DBusMessageIter         *iter,
+			       GValue                  *value,
+			       GError                 **error)
+{
+  GType coltype;
+  GType subtype;
+  gpointer instance;
+  DBusGTypeSpecializedAppendContext ctx;
+  DBusGValueDemarshalFunc demarshaller;
+  DBusMessageIter subiter;
+  int current_type;
+
+  current_type = dbus_message_iter_get_arg_type (iter);
+
+  if (current_type != DBUS_TYPE_ARRAY)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Expected D-BUS array, got type code \'%c\'", (guchar) current_type);
+      return FALSE;
+    }
+
+  dbus_message_iter_recurse (iter, &subiter);
+  
+  coltype = G_VALUE_TYPE (value);
+  subtype = dbus_g_type_get_collection_specialization (coltype);
+
+  demarshaller = get_type_demarshaller (subtype);
+
+  if (!demarshaller)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "No demarshaller registered for type \"%s\" of collection \"%s\"",
+		   g_type_name (coltype),
+		   g_type_name (subtype));
+      return FALSE;
+    }
+
+  instance = dbus_g_type_specialized_construct (coltype);
+  g_value_take_boxed (value, instance);
+
+  dbus_g_type_specialized_init_append (value, &ctx);
+
+  while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID)
+    {
+      GValue eltval = {0, };
+
+      g_value_init (&eltval, subtype);
+
+      if (!demarshaller (context, &subiter, &eltval, error))
+	{
+	  dbus_g_type_specialized_collection_end_append (&ctx);
+	  g_value_unset (value);
+	  return FALSE;
+	}
+      dbus_g_type_specialized_collection_append (&ctx, &eltval);
+      
+      dbus_message_iter_next (&subiter);
+    }
+  dbus_g_type_specialized_collection_end_append (&ctx);
+  
+  return TRUE;
+}
+
+static gboolean
+demarshal_collection_array (DBusGValueMarshalCtx    *context,
+			    DBusMessageIter         *iter,
+			    GValue                  *value,
+			    GError                 **error)
+{
+  DBusMessageIter subiter;
+  GArray *ret;
+  GType elt_gtype;
+  int elt_size;
+  void *msgarray;
+  int msgarray_len;
+
+  dbus_message_iter_recurse (iter, &subiter);
+
+  elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
+  g_assert (elt_gtype != G_TYPE_INVALID);
+  g_assert (_dbus_g_type_is_fixed (elt_gtype));
+
+  elt_size = _dbus_g_type_fixed_get_size (elt_gtype);
+  
+  ret = g_array_new (FALSE, TRUE, elt_size);
+
+  msgarray = NULL;
+  dbus_message_iter_get_fixed_array (&subiter,
+				     &msgarray,
+				     &msgarray_len);
+  g_assert (msgarray != NULL || msgarray_len == 0);
+
+  if (msgarray_len)
+    g_array_append_vals (ret, msgarray, (guint) msgarray_len);
+
+  g_value_take_boxed (value, ret);
+  
+  return TRUE;
+}
+
+gboolean
+_dbus_gvalue_demarshal (DBusGValueMarshalCtx    *context,
+		       DBusMessageIter         *iter,
+		       GValue                  *value,
+		       GError                 **error)
+{
+  GType gtype;
+  DBusGValueDemarshalFunc demarshaller;
+  gboolean retcode = FALSE;
+
+  if (context->recursion_depth > DBUS_GLIB_MAX_VARIANT_RECURSION)
+    {
+      g_set_error (error, DBUS_GERROR,
+                   DBUS_GERROR_NO_MEMORY, 
+                   "Variant recursion limit exceeded");
+      return FALSE;
+    }
+  context->recursion_depth++;
+
+  gtype = G_VALUE_TYPE (value);
+
+  demarshaller = get_type_demarshaller (gtype);
+
+  if (demarshaller == NULL)
+    {
+      g_set_error (error,
+		   DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "No demarshaller registered for type \"%s\"",
+		   g_type_name (gtype));
+    
+      goto out;
+    }
+  
+  retcode = demarshaller (context, iter, value, error);
+ out:
+  context->recursion_depth--;  
+  return retcode;
+}
+
+gboolean
+_dbus_gvalue_demarshal_variant (DBusGValueMarshalCtx    *context,
+			       DBusMessageIter         *iter,
+			       GValue                  *value,
+			       GError                 **error)
+{
+  return demarshal_static_variant (context, iter, value, error);
+}
+
+GValueArray *
+_dbus_gvalue_demarshal_message  (DBusGValueMarshalCtx    *context,
+				DBusMessage             *message,
+				guint                    n_types,
+				const GType             *types,
+				GError                 **error)
+{
+  GValueArray *ret;
+  DBusMessageIter iter;
+  int current_type;
+  guint index_;
+  
+  ret = g_value_array_new (6);  /* 6 is a typical maximum for arguments */
+
+  dbus_message_iter_init (message, &iter);
+  index_ = 0;
+  while ((current_type = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID)
+    {
+      GValue *value;
+      GType gtype;
+
+      if (index_ >= n_types)
+	{
+	  g_set_error (error, DBUS_GERROR,
+		       DBUS_GERROR_INVALID_ARGS,
+		       "Too many arguments in message");
+	  goto lose;
+	}
+      
+      g_value_array_append (ret, NULL);
+      value = g_value_array_get_nth (ret, index_);
+
+      gtype = types[index_]; 
+      g_value_init (value, gtype);
+
+      if (!_dbus_gvalue_demarshal (context, &iter, value, error))
+	goto lose;
+      dbus_message_iter_next (&iter);
+      index_++;
+    }
+  if (index_ < n_types)
+    {
+      g_set_error (error, DBUS_GERROR,
+		   DBUS_GERROR_INVALID_ARGS,
+		   "Too few arguments in message");
+      goto lose;
+    }
+
+  return ret;
+ lose:
+  g_value_array_free (ret);
+  return NULL;
+}
+
+static void oom (void) G_GNUC_NORETURN;
+static void
+oom (void)
+{
+  g_error ("no memory");
+}
+
+static gboolean
+marshal_basic (DBusMessageIter *iter, const GValue *value)
+{
+  GType value_type;
+
+  value_type = G_VALUE_TYPE (value);
+  
+  switch (value_type)
+    {
+    case G_TYPE_CHAR:
+      {
+        char b = g_value_get_char (value);
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_BYTE,
+                                             &b))
+          oom ();
+      }
+      return TRUE;
+    case G_TYPE_UCHAR:
+      {
+        unsigned char b = g_value_get_uchar (value);
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_BYTE,
+                                             &b))
+          oom ();
+      }
+      return TRUE;
+    case G_TYPE_BOOLEAN:
+      {
+        dbus_bool_t b = g_value_get_boolean (value);
+
+        g_return_val_if_fail (b == TRUE || b == FALSE, FALSE);
+
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_BOOLEAN,
+                                             &b))
+          oom ();
+      }
+      return TRUE;
+    case G_TYPE_INT:
+      {
+        dbus_int32_t v = g_value_get_int (value);
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_INT32,
+                                             &v))
+          oom ();
+      }
+      return TRUE;
+    case G_TYPE_UINT:
+      {
+        dbus_uint32_t v = g_value_get_uint (value);
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_UINT32,
+                                             &v))
+          oom ();
+      }
+      return TRUE;
+    case G_TYPE_LONG:
+      {
+        dbus_int32_t v = g_value_get_long (value);
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_INT32,
+                                             &v))
+          oom ();
+      }
+      return TRUE;
+    case G_TYPE_ULONG:
+      {
+        dbus_uint32_t v = g_value_get_ulong (value);
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_UINT32,
+                                             &v))
+          oom ();
+      }
+      return TRUE;
+    case G_TYPE_INT64:
+      {
+        gint64 v = g_value_get_int64 (value);
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_INT64,
+                                             &v))
+          oom ();
+      }
+      return TRUE;
+    case G_TYPE_UINT64:
+      {
+        guint64 v = g_value_get_uint64 (value);
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_UINT64,
+                                             &v))
+          oom ();
+      }
+      return TRUE;
+    case G_TYPE_FLOAT:
+      {
+        double v = g_value_get_float (value);
+        
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_DOUBLE,
+                                             &v))
+          oom ();
+      }
+      return TRUE;
+    case G_TYPE_DOUBLE:
+      {
+        double v = g_value_get_double (value);
+        
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_DOUBLE,
+                                             &v))
+          oom ();
+      }
+      return TRUE;
+    case G_TYPE_STRING:
+      {
+        const char *v = g_value_get_string (value);
+	if (!v)
+	  v = "";
+
+        /* FIXME: fd.o #16320: consider using g_return_if_fail to check UTF-8
+         * validity */
+
+        if (!dbus_message_iter_append_basic (iter,
+                                             DBUS_TYPE_STRING,
+                                             &v))
+          {
+            gchar *s = g_strdup_value_contents (value);
+
+            g_critical ("Unable to marshal string (not UTF-8 or OOM?): %s",
+                s);
+            g_free (s);
+            return FALSE;
+          }
+      }
+      return TRUE;
+      
+    default:
+      {
+	g_assert_not_reached ();
+	return FALSE;
+      }
+    }
+}
+
+static gboolean
+marshal_strv (DBusMessageIter   *iter,
+	      const GValue       *value)
+{
+  DBusMessageIter subiter;
+  char **array;
+  char **elt;
+  gboolean ret = FALSE;
+
+  g_assert (G_VALUE_TYPE (value) == g_strv_get_type ());
+
+  array = g_value_get_boxed (value);
+
+  if (!dbus_message_iter_open_container (iter,
+					 DBUS_TYPE_ARRAY,
+					 "s",
+					 &subiter))
+    goto out;
+
+  if (array)
+    {
+      for (elt = array; *elt; elt++)
+        {
+          if (!dbus_message_iter_append_basic (&subiter,
+					   DBUS_TYPE_STRING,
+					   elt))
+	        goto out;
+        }
+    }
+
+  if (!dbus_message_iter_close_container (iter, &subiter))
+    goto out;
+  ret = TRUE;
+ out:
+  return ret;
+}
+
+static gboolean
+marshal_valuearray (DBusMessageIter   *iter,
+		    const GValue       *value)
+{
+  GValueArray *array;
+  guint i;
+  DBusMessageIter subiter;
+
+  g_assert (G_VALUE_TYPE (value) == G_TYPE_ARRAY);
+
+  array = g_value_get_boxed (value);
+
+  if (!dbus_message_iter_open_container (iter,
+					 DBUS_TYPE_STRUCT,
+					 NULL,
+					 &subiter))
+    oom ();
+
+  if (array)
+    {
+      for (i = 0; i < array->n_values; i++)
+        {
+          if (!_dbus_gvalue_marshal (&subiter, g_value_array_get_nth (array, i)))
+            {
+              dbus_message_iter_abandon_container (iter, &subiter);
+              return FALSE;
+            }
+        }
+    }
+
+  return dbus_message_iter_close_container (iter, &subiter);
+}
+
+static gboolean
+marshal_proxy (DBusMessageIter         *iter,
+	       const GValue            *value)
+{
+  const char *path;
+  DBusGProxy *proxy;
+
+  g_assert (G_VALUE_TYPE (value) == dbus_g_proxy_get_type ());
+
+  proxy = g_value_get_object (value);
+  g_return_val_if_fail (DBUS_IS_G_PROXY (proxy), FALSE);
+  path = dbus_g_proxy_get_path (proxy);
+  g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
+
+  if (!dbus_message_iter_append_basic (iter,
+				       DBUS_TYPE_OBJECT_PATH,
+				       &path))
+    oom ();
+
+  return TRUE;
+}
+
+static gboolean
+marshal_object_path (DBusMessageIter         *iter,
+		     const GValue            *value)
+{
+  const char *path;
+
+  g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_OBJECT_PATH);
+
+  path = g_value_get_boxed (value);
+  g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
+
+  if (!dbus_message_iter_append_basic (iter,
+				       DBUS_TYPE_OBJECT_PATH,
+				       &path))
+    oom ();
+
+  return TRUE;
+}
+
+static gboolean
+marshal_object (DBusMessageIter         *iter,
+		const GValue            *value)
+{
+  const char *path;
+  GObject *obj;
+
+  obj = g_value_get_object (value);
+  g_return_val_if_fail (G_IS_OBJECT (obj), FALSE);
+
+  path = _dbus_gobject_get_path (obj);
+  g_return_val_if_fail (g_variant_is_object_path (path), FALSE);
+
+  if (!dbus_message_iter_append_basic (iter,
+				       DBUS_TYPE_OBJECT_PATH,
+				       &path))
+    oom ();
+
+  return TRUE;
+}
+
+static gboolean
+marshal_signature (DBusMessageIter         *iter,
+		   const GValue            *value)
+{
+  const char *sig;
+
+  g_assert (G_VALUE_TYPE (value) == DBUS_TYPE_G_SIGNATURE);
+
+  sig = g_value_get_boxed (value);
+  g_return_val_if_fail (g_variant_is_signature (sig), FALSE);
+
+  /* failure here isn't strictly *guaranteed* to be OOM, since GDBus might
+   * understand more type-codes than our libdbus */
+  if (!dbus_message_iter_append_basic (iter,
+				       DBUS_TYPE_SIGNATURE,
+				       &sig))
+    return FALSE;
+
+  return TRUE;
+}
+
+struct DBusGLibHashMarshalData
+{
+  const char *entry_sig;
+  DBusMessageIter *iter;
+  gboolean err;
+};
+
+static void
+marshal_map_entry (const GValue *key,
+		   const GValue *value,
+		   gpointer data)
+{
+  struct DBusGLibHashMarshalData *hashdata = data;
+  DBusMessageIter subiter;
+
+  if (hashdata->err)
+    return;
+
+  if (!dbus_message_iter_open_container (hashdata->iter,
+					 DBUS_TYPE_DICT_ENTRY,
+					 NULL,
+					 &subiter))
+    goto lose;
+
+  if (!_dbus_gvalue_marshal (&subiter, key))
+    goto lose;
+
+  if (!_dbus_gvalue_marshal (&subiter, value))
+    goto lose;
+
+  if (!dbus_message_iter_close_container (hashdata->iter, &subiter))
+    goto lose;
+  
+  return;
+ lose:
+  hashdata->err = TRUE;
+}
+
+static gboolean
+marshal_map (DBusMessageIter   *iter,
+	     const GValue      *value)
+{
+  GType gtype;
+  DBusMessageIter arr_iter;
+  struct DBusGLibHashMarshalData hashdata;
+  char *key_sig;
+  char *value_sig;
+  GType key_type;
+  GType value_type;
+  char *entry_sig;
+  char *array_sig;
+
+  gtype = G_VALUE_TYPE (value);
+
+  key_type = dbus_g_type_get_map_key_specialization (gtype);
+  g_assert (_dbus_gtype_is_valid_hash_key (key_type));
+  value_type = dbus_g_type_get_map_value_specialization (gtype);
+  g_assert (_dbus_gtype_is_valid_hash_value (value_type));
+
+  key_sig = _dbus_gtype_to_signature (key_type);
+  if (!key_sig)
+    {
+      g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (key_type));
+      return FALSE;
+    }
+  value_sig = _dbus_gtype_to_signature (value_type);
+  if (!value_sig)
+    {
+      g_free (key_sig);
+      g_warning ("Cannot marshal type \"%s\" in map\n", g_type_name (value_type));
+      return FALSE;
+    }
+  entry_sig = g_strdup_printf ("%s%s", key_sig, value_sig);
+  g_free (key_sig);
+  g_free (value_sig);
+  array_sig = g_strdup_printf ("%c%s%c",
+			       DBUS_DICT_ENTRY_BEGIN_CHAR,
+			       entry_sig,
+			       DBUS_DICT_ENTRY_END_CHAR);
+  if (!dbus_message_iter_open_container (iter,
+					 DBUS_TYPE_ARRAY,
+					 array_sig,
+					 &arr_iter))
+    goto lose;
+
+  hashdata.iter = &arr_iter;
+  hashdata.err = FALSE;
+  hashdata.entry_sig = entry_sig;
+
+  dbus_g_type_map_value_iterate (value,
+				 marshal_map_entry,
+				 &hashdata);
+
+  if (hashdata.err)
+    {
+      dbus_message_iter_abandon_container (iter, &arr_iter);
+      goto lose;
+    }
+  else if (!dbus_message_iter_close_container (iter, &arr_iter))
+    {
+      goto lose;
+    }
+
+ out:
+  g_free (entry_sig);
+  g_free (array_sig);
+  return !hashdata.err;
+ lose:
+  hashdata.err = TRUE;
+  goto out;
+}
+
+static gboolean
+marshal_struct (DBusMessageIter   *iter,
+                const GValue      *value)
+{
+  GType gtype;
+  DBusMessageIter subiter;
+  guint size, i;
+  GValue val = {0,};
+
+  gtype = G_VALUE_TYPE (value);
+
+  size = dbus_g_type_get_struct_size (gtype);
+
+  if (!dbus_message_iter_open_container (iter,
+                                         DBUS_TYPE_STRUCT,
+                                         NULL,
+                                         &subiter))
+    oom ();
+
+  for (i = 0; i < size; i++)
+    {
+      g_value_init (&val, dbus_g_type_get_struct_member_type
+          (G_VALUE_TYPE(value), i));
+
+      if (!dbus_g_type_struct_get_member (value, i, &val))
+        goto abandon;
+
+      if (!_dbus_gvalue_marshal (&subiter, &val))
+        goto abandon;
+
+      g_value_unset(&val);
+    }
+
+  return dbus_message_iter_close_container (iter, &subiter);
+
+abandon:
+  dbus_message_iter_abandon_container (iter, &subiter);
+  return FALSE;
+}
+
+static gboolean
+marshal_variant (DBusMessageIter          *iter,
+		 const GValue             *value)
+{
+  GType value_gtype;
+  DBusMessageIter subiter;
+  char *variant_sig;
+  GValue *real_value;
+  gboolean ret = FALSE;
+
+  real_value = g_value_get_boxed (value);
+  value_gtype = G_VALUE_TYPE (real_value);
+
+  variant_sig = _dbus_gvalue_to_signature (real_value);
+  if (variant_sig == NULL)
+    {
+      g_warning ("Cannot marshal type \"%s\" in variant", g_type_name (value_gtype));
+      return FALSE;
+    }
+
+  if (!dbus_message_iter_open_container (iter,
+					 DBUS_TYPE_VARIANT,
+					 variant_sig,
+					 &subiter))
+    goto out;
+
+  if (!_dbus_gvalue_marshal (&subiter, real_value))
+    {
+      dbus_message_iter_abandon_container (iter, &subiter);
+      goto out;
+    }
+
+  if (!dbus_message_iter_close_container (iter, &subiter))
+    goto out;
+
+  ret = TRUE;
+ out:
+  g_free (variant_sig);
+  return ret;
+}
+
+static DBusGValueMarshalFunc
+get_type_marshaller (GType type)
+{
+  DBusGTypeMarshalData *typedata;
+
+  typedata = g_type_get_qdata (type, dbus_g_type_metadata_data_quark ());
+  if (typedata == NULL)
+    {
+      if (g_type_is_a (type, G_TYPE_ARRAY))
+	return marshal_valuearray;
+      if (dbus_g_type_is_collection (type))
+	return marshal_collection;
+      if (dbus_g_type_is_map (type))
+	return marshal_map;
+      if (dbus_g_type_is_struct (type))
+	return marshal_struct;
+
+      g_warning ("No marshaller registered for type \"%s\"", g_type_name (type));
+      return NULL;
+    }
+  g_assert (typedata->vtable);
+  return typedata->vtable->marshaller;
+}
+
+typedef struct
+{
+  DBusMessageIter *iter;
+  DBusGValueMarshalFunc marshaller;
+  gboolean err;
+} DBusGValueCollectionMarshalData;
+
+static void
+collection_marshal_iterator (const GValue *eltval,
+			     gpointer      user_data)
+{
+  DBusGValueCollectionMarshalData *data = user_data;
+
+  if (data->err)
+    return;
+
+  if (!data->marshaller (data->iter, eltval))
+    data->err = TRUE;
+}
+
+static gboolean
+marshal_collection (DBusMessageIter         *iter,
+		    const GValue            *value)
+{
+  GType coltype;
+  GType subtype;
+  
+  coltype = G_VALUE_TYPE (value);
+  subtype = dbus_g_type_get_collection_specialization (coltype);
+
+  if (_dbus_g_type_is_fixed (subtype))
+    return marshal_collection_array (iter, value);
+  else
+    return marshal_collection_ptrarray (iter, value);
+}
+
+static gboolean
+marshal_collection_ptrarray (DBusMessageIter         *iter,
+			     const GValue            *value)
+{
+  GType coltype;
+  GType elt_gtype;
+  DBusGValueCollectionMarshalData data;
+  DBusMessageIter subiter;
+  char *elt_sig;
+  
+  coltype = G_VALUE_TYPE (value);
+  elt_gtype = dbus_g_type_get_collection_specialization (coltype);
+  data.marshaller = get_type_marshaller (elt_gtype);
+  if (!data.marshaller)
+    return FALSE;
+
+  elt_sig = _dbus_gtype_to_signature (elt_gtype);
+  if (!elt_sig)
+    {
+      g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
+      return FALSE;
+    }
+  g_assert (g_variant_is_signature (elt_sig));
+
+  if (!dbus_message_iter_open_container (iter,
+					 DBUS_TYPE_ARRAY,
+					 elt_sig,
+					 &subiter))
+    oom ();
+
+  g_free (elt_sig);
+
+  data.iter = &subiter;
+  data.err = FALSE;
+
+  dbus_g_type_collection_value_iterate (value,
+					collection_marshal_iterator,
+					&data);
+
+  if (data.err)
+    {
+      dbus_message_iter_abandon_container (iter, &subiter);
+      return FALSE;
+    }
+
+  return dbus_message_iter_close_container (iter, &subiter);
+}
+
+/* If any of these assertions are violated, then marshal_collection_array
+ * is buggy for that type. dbus_g_value_basic_array_parse_variant() has
+ * general size-conversion code, if needed. */
+G_STATIC_ASSERT (sizeof (dbus_bool_t) == sizeof (gboolean));
+G_STATIC_ASSERT (sizeof (dbus_int32_t) == sizeof (gint));
+G_STATIC_ASSERT (sizeof (dbus_uint32_t) == sizeof (guint));
+/* These should be true regardless, but just for completeness... */
+G_STATIC_ASSERT (sizeof (dbus_int64_t) == sizeof (gint64));
+G_STATIC_ASSERT (sizeof (dbus_uint64_t) == sizeof (guint64));
+G_STATIC_ASSERT (sizeof (double) == sizeof (gdouble));
+
+static gboolean
+marshal_collection_array (DBusMessageIter   *iter,
+			  const GValue      *value)
+{
+  GType elt_gtype;
+  DBusMessageIter subiter;
+  GArray *array;
+  char *subsignature_str;
+
+  array = g_value_get_boxed (value);
+  g_return_val_if_fail (array != NULL, FALSE);
+
+  elt_gtype = dbus_g_type_get_collection_specialization (G_VALUE_TYPE (value));
+  g_assert (_dbus_g_type_is_fixed (elt_gtype));
+  subsignature_str = _dbus_gtype_to_signature (elt_gtype);
+  if (!subsignature_str)
+    {
+      g_warning ("Cannot marshal type \"%s\" in collection\n", g_type_name (elt_gtype));
+      return FALSE;
+    }
+  g_assert (g_variant_is_signature (subsignature_str));
+
+  if (!dbus_message_iter_open_container (iter,
+					 DBUS_TYPE_ARRAY,
+					 subsignature_str,
+					 &subiter))
+    oom ();
+
+  /* TODO - This assumes that basic values are the same size
+   * is this always true?  If it is we can probably avoid
+   * a lot of the overhead in _marshal_basic_instance...
+   */
+  if (!dbus_message_iter_append_fixed_array (&subiter,
+					     subsignature_str[0],
+					     &(array->data),
+					     array->len))
+    {
+      g_critical ("Unable to serialize %u GArray members as signature %s "
+          "(OOM or invalid boolean value?)", array->len, subsignature_str);
+
+      g_free (subsignature_str);
+      dbus_message_iter_abandon_container (iter, &subiter);
+      return FALSE;
+    }
+
+  g_free (subsignature_str);
+  return dbus_message_iter_close_container (iter, &subiter);
+}
+
+gboolean
+_dbus_gvalue_marshal (DBusMessageIter         *iter,
+		     const GValue       *value)
+{
+  GType gtype;
+  DBusGValueMarshalFunc marshaller;
+
+  gtype = G_VALUE_TYPE (value);
+
+  marshaller = get_type_marshaller (gtype);
+  if (marshaller == NULL)
+    return FALSE;
+  return marshaller (iter, value);
+}
+
+#ifdef DBUS_BUILD_TESTS
+
+static void
+assert_type_maps_to (GType gtype, const char *expected_sig)
+{
+  char *sig;
+  sig = _dbus_gtype_to_signature (gtype);
+  g_assert_nonnull (sig);
+  g_assert_cmpstr (expected_sig, ==, sig);
+  g_free (sig);
+}
+
+static void
+assert_signature_maps_to (const char *sig, GType expected_gtype)
+{
+  g_assert_cmpuint (_dbus_gtype_from_signature (sig, TRUE), ==, expected_gtype);
+}
+
+static void
+assert_bidirectional_mapping (GType gtype, const char *expected_sig)
+{
+  assert_type_maps_to (gtype, expected_sig);
+  assert_signature_maps_to (expected_sig, gtype);
+}
+
+/*
+ * Unit test for general glib stuff
+ * Returns: %TRUE on success.
+ */
+gboolean
+_dbus_gvalue_test (const char *test_data_dir)
+{
+  GType type;
+  GType rectype;
+
+  g_type_init ();
+  _dbus_g_value_types_init ();
+  
+  assert_bidirectional_mapping (G_TYPE_STRING, DBUS_TYPE_STRING_AS_STRING);
+  assert_bidirectional_mapping (G_TYPE_UCHAR, DBUS_TYPE_BYTE_AS_STRING);
+  assert_bidirectional_mapping (G_TYPE_UINT, DBUS_TYPE_UINT32_AS_STRING);
+
+  assert_bidirectional_mapping (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE),
+			      DBUS_TYPE_ARRAY_AS_STRING DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
+  assert_bidirectional_mapping (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
+				DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING);
+  assert_bidirectional_mapping (dbus_g_type_get_collection ("GArray", G_TYPE_INT),
+				DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_INT32_AS_STRING);
+
+  assert_bidirectional_mapping (dbus_g_type_get_struct ("GValueArray", G_TYPE_INT, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID),
+  				DBUS_STRUCT_BEGIN_CHAR_AS_STRING DBUS_TYPE_INT32_AS_STRING DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING DBUS_STRUCT_END_CHAR_AS_STRING );
+
+  rectype = dbus_g_type_get_collection ("GArray", G_TYPE_UINT);
+  g_assert_cmpuint (rectype, !=, G_TYPE_INVALID);
+  g_assert_cmpstr (g_type_name (rectype), ==, "GArray_guint_");
+
+  type = _dbus_gtype_from_signature ("au", TRUE);
+  g_assert_cmpuint (type, ==, rectype);
+
+  rectype = dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING);
+  g_assert_cmpuint (rectype, !=, G_TYPE_INVALID);
+  g_assert_cmpstr (g_type_name (rectype), ==, "GHashTable_gchararray+gchararray_");
+
+  type = _dbus_gtype_from_signature ("a{ss}", TRUE);
+  g_assert_cmpuint (type, ==, rectype);
+
+  type = _dbus_gtype_from_signature ("o", FALSE);
+  g_assert_cmpuint (type, ==, DBUS_TYPE_G_OBJECT_PATH);
+  type = _dbus_gtype_from_signature ("o", TRUE);
+  g_assert_cmpuint (type, ==, DBUS_TYPE_G_OBJECT_PATH);
+
+  type = _dbus_gtype_from_signature ("g", TRUE);
+  g_assert_cmpuint (type, ==, DBUS_TYPE_G_SIGNATURE);
+
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
Index: dbus-glib-0.112-new/dbus
===================================================================
--- dbus-glib-0.112-new/dbus	(nonexistent)
+++ dbus-glib-0.112-new/dbus	(revision 5)

Property changes on: dbus-glib-0.112-new/dbus
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: dbus-glib-0.112-new
===================================================================
--- dbus-glib-0.112-new	(nonexistent)
+++ dbus-glib-0.112-new	(revision 5)

Property changes on: dbus-glib-0.112-new
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~
Index: file.list
===================================================================
--- file.list	(nonexistent)
+++ file.list	(revision 5)
@@ -0,0 +1,3 @@
+dbus-glib-0.112/dbus/dbus-binding-tool-glib.c
+dbus-glib-0.112/dbus/dbus-gvalue-utils.c
+dbus-glib-0.112/dbus/dbus-gvalue.c
Index: .
===================================================================
--- .	(nonexistent)
+++ .	(revision 5)

Property changes on: .
___________________________________________________________________
Added: svn:ignore
## -0,0 +1,73 ##
+
+# install dir
+dist
+
+# Target build dirs
+.a1x-newlib
+.a2x-newlib
+.at91sam7s-newlib
+
+.build-machine
+
+.a1x-glibc
+.a2x-glibc
+.h3-glibc
+.h5-glibc
+.i586-glibc
+.i686-glibc
+.imx6-glibc
+.jz47xx-glibc
+.makefile
+.am335x-glibc
+.omap543x-glibc
+.p5600-glibc
+.power8-glibc
+.power8le-glibc
+.power9-glibc
+.power9le-glibc
+.m1000-glibc
+.riscv64-glibc
+.rk328x-glibc
+.rk33xx-glibc
+.rk339x-glibc
+.s8xx-glibc
+.s9xx-glibc
+.x86_64-glibc
+
+# Hidden files (each file)
+.makefile
+.dist
+.rootfs
+
+# src & hw requires
+.src_requires
+.src_requires_depend
+.requires
+.requires_depend
+
+# Tarballs
+*.gz
+*.bz2
+*.lz
+*.xz
+*.tgz
+*.txz
+
+# Signatures
+*.asc
+*.sig
+*.sign
+*.sha1sum
+
+# Patches
+*.patch
+
+# Descriptions
+*.dsc
+*.txt
+
+# Default linux config files
+*.defconfig
+
+# backup copies
+*~