ofdbus/dbus-glib/dbus/dbus-binding-tool-glib.c
changeset 31 ce057bb09d0b
parent 0 e4d67989cc36
equal deleted inserted replaced
30:e20de85af2ee 31:ce057bb09d0b
       
     1 /* -*- mode: C; c-file-style: "gnu" -*- */
       
     2 /* dbus-binding-tool-glib.c: Output C glue
       
     3  *
       
     4  * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
       
     5  * Copyright (C) 2005 Nokia
       
     6  * Portion Copyright © 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
       
     7  * Licensed under the Academic Free License version 2.1
       
     8  *
       
     9  * This program is free software; you can redistribute it and/or modify
       
    10  * it under the terms of the GNU General Public License as published by
       
    11  * the Free Software Foundation; either version 2 of the License, or
       
    12  * (at your option) any later version.
       
    13  *
       
    14  * This program is distributed in the hope that it will be useful,
       
    15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    17  * GNU General Public License for more details.
       
    18  *
       
    19  * You should have received a copy of the GNU General Public License
       
    20  * along with this program; if not, write to the Free Software
       
    21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    22  *
       
    23  */
       
    24 
       
    25 #ifndef __SYMBIAN32__
       
    26 #include <config.h>
       
    27 #else
       
    28 #include "config.h"
       
    29 #endif //__SYMBIAN32__
       
    30 #include "dbus/dbus-glib.h"
       
    31 #include "dbus-gidl.h"
       
    32 #include "dbus-gparser.h"
       
    33 #include "dbus-gutils.h"
       
    34 #include "dbus-gtype-specialized.h"
       
    35 #include "dbus-gsignature.h"
       
    36 #include "dbus-gvalue-utils.h"
       
    37 #include "dbus-glib-tool.h"
       
    38 #include "dbus-binding-tool-glib.h"
       
    39 
       
    40 #ifndef __SYMBIAN32__
       
    41 #include <glib/gi18n.h>
       
    42 #include <libintl.h>
       
    43 #define _(x) dgettext (GETTEXT_PACKAGE, x)
       
    44 #define N_(x) x
       
    45 #else
       
    46 
       
    47 #define _(x) x
       
    48 #define N_(x) x
       
    49 #endif
       
    50 
       
    51 #include <stdio.h>
       
    52 #include <stdlib.h>
       
    53 #include <string.h>
       
    54 #include <unistd.h>
       
    55 
       
    56 #define MARSHAL_PREFIX "dbus_glib_marshal_"
       
    57 
       
    58 typedef struct
       
    59 {
       
    60   gboolean ignore_unsupported;
       
    61   const char* prefix;
       
    62   GIOChannel *channel;
       
    63   
       
    64   GError **error;
       
    65   
       
    66   GHashTable *generated;
       
    67   GString *blob;
       
    68   GString *signal_blob;
       
    69   GString *property_blob;
       
    70   guint count;
       
    71 } DBusBindingToolCData;
       
    72 
       
    73 static gboolean gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error);
       
    74 static gboolean generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error);
       
    75 static gboolean generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error);
       
    76 
       
    77 static const char *
       
    78 dbus_g_type_get_marshal_name (GType gtype)
       
    79 {
       
    80   switch (G_TYPE_FUNDAMENTAL (gtype))
       
    81     {
       
    82     case G_TYPE_NONE:
       
    83       return "NONE";
       
    84     case G_TYPE_BOOLEAN:
       
    85       return "BOOLEAN";
       
    86     case G_TYPE_UCHAR:
       
    87       return "UCHAR";
       
    88     case G_TYPE_INT:
       
    89       return "INT";
       
    90     case G_TYPE_UINT:
       
    91       return "UINT";
       
    92     case G_TYPE_INT64:
       
    93       return "INT64";
       
    94     case G_TYPE_UINT64:
       
    95       return "UINT64";
       
    96     case G_TYPE_DOUBLE:
       
    97       return "DOUBLE";
       
    98     case G_TYPE_STRING:
       
    99       return "STRING";
       
   100     case G_TYPE_POINTER:
       
   101       return "POINTER";
       
   102     case G_TYPE_BOXED:
       
   103       return "BOXED";
       
   104     case G_TYPE_OBJECT:
       
   105       return "OBJECT";
       
   106     default:
       
   107       return NULL;
       
   108     }
       
   109 }
       
   110 
       
   111 /* This entire function is kind of...ugh. */
       
   112 static const char *
       
   113 dbus_g_type_get_c_name (GType gtype)
       
   114 {
       
   115   GType subtype;
       
   116   if (dbus_g_type_is_struct (gtype))
       
   117     {
       
   118       return "GValueArray";
       
   119     }
       
   120   if (dbus_g_type_is_collection (gtype))
       
   121     {
       
   122       subtype = dbus_g_type_get_collection_specialization(gtype);
       
   123       if (_dbus_g_type_is_fixed (subtype))
       
   124         return "GArray";
       
   125       else
       
   126         return "GPtrArray";
       
   127     }
       
   128 
       
   129   if (dbus_g_type_is_map (gtype))
       
   130     return "GHashTable";
       
   131 
       
   132   if (g_type_is_a (gtype, G_TYPE_STRING))
       
   133     return "char *";
       
   134 
       
   135   /* This one is even more hacky...we get an extra *
       
   136    * because G_TYPE_STRV is a G_TYPE_BOXED
       
   137    */
       
   138   if (g_type_is_a (gtype, G_TYPE_STRV))
       
   139     return "char *";
       
   140 
       
   141   if (g_type_is_a (gtype, DBUS_TYPE_G_OBJECT_PATH))
       
   142     return "char";
       
   143 
       
   144   return g_type_name (gtype);
       
   145 }
       
   146 
       
   147 static gboolean
       
   148 compute_gsignature (MethodInfo *method, GType *rettype, GArray **params, GError **error)
       
   149 {
       
   150   GSList *elt;
       
   151   GType retval_type;
       
   152   GArray *ret;
       
   153   gboolean is_async;
       
   154   const char *arg_type;
       
   155   gboolean retval_signals_error;
       
   156   
       
   157   is_async = method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL;
       
   158   retval_signals_error = FALSE;
       
   159 
       
   160   ret = g_array_new (TRUE, TRUE, sizeof (GType));
       
   161 
       
   162   if (is_async)
       
   163     retval_type = G_TYPE_NONE;
       
   164   else
       
   165     {
       
   166       gboolean found_retval;
       
   167 
       
   168       /* Look for return value */
       
   169       found_retval = FALSE;
       
   170       for (elt = method_info_get_args (method); elt; elt = elt->next)
       
   171 	{
       
   172 	  ArgInfo *arg = elt->data;
       
   173 	  const char *returnval_annotation;
       
   174       
       
   175 	  returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL);
       
   176 	  if (returnval_annotation != NULL)
       
   177 	    {
       
   178 	      arg_type = arg_info_get_type (arg);
       
   179 	      retval_type = _dbus_gtype_from_signature (arg_type, FALSE);
       
   180 	      if (retval_type == G_TYPE_INVALID)
       
   181 		goto invalid_type;
       
   182 	      found_retval = TRUE;
       
   183 	      if (!strcmp (returnval_annotation, "error"))
       
   184 		retval_signals_error = TRUE;
       
   185 	      break;
       
   186 	    }
       
   187 	}
       
   188       if (!found_retval)
       
   189 	{
       
   190 	  retval_type = G_TYPE_BOOLEAN;
       
   191 	  retval_signals_error = TRUE;
       
   192 	}
       
   193     }
       
   194 
       
   195   *rettype = retval_type;
       
   196 
       
   197   /* Handle all input arguments */
       
   198   for (elt = method_info_get_args (method); elt; elt = elt->next)
       
   199     {
       
   200       ArgInfo *arg = elt->data;
       
   201       if (arg_info_get_direction (arg) == ARG_IN)
       
   202 	{
       
   203 	  GType gtype;
       
   204 	  
       
   205 	  arg_type = arg_info_get_type (arg);
       
   206 	  gtype = _dbus_gtype_from_signature (arg_type, FALSE);
       
   207 	  if (gtype == G_TYPE_INVALID)
       
   208 	    goto invalid_type;
       
   209 	  
       
   210 	  g_array_append_val (ret, gtype);
       
   211 	}
       
   212     }
       
   213 
       
   214   if (!is_async)
       
   215     {
       
   216       /* Append pointer for each out arg storage */
       
   217       for (elt = method_info_get_args (method); elt; elt = elt->next)
       
   218 	{
       
   219 	  ArgInfo *arg = elt->data;
       
   220 
       
   221 	  /* Skip return value */
       
   222 	  if (arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL) != NULL)
       
   223 	    continue;
       
   224       
       
   225 	  if (arg_info_get_direction (arg) == ARG_OUT)
       
   226 	    {
       
   227 	      GType gtype;
       
   228 	      arg_type = arg_info_get_type (arg);
       
   229 	      gtype = _dbus_gtype_from_signature (arg_type, FALSE);
       
   230 	      if (gtype == G_TYPE_INVALID)
       
   231 		goto invalid_type;
       
   232 	      /* We actually just need a pointer for the return value
       
   233 		 storage */
       
   234 	      gtype = G_TYPE_POINTER;
       
   235 	      g_array_append_val (ret, gtype);
       
   236 	    }
       
   237 	}
       
   238 
       
   239       if (retval_signals_error)
       
   240 	{
       
   241 	  /* Final GError parameter */
       
   242 	  GType gtype = G_TYPE_POINTER;
       
   243 	  g_array_append_val (ret, gtype);
       
   244 	}
       
   245     }
       
   246   else
       
   247     {
       
   248       /* Context pointer */
       
   249       GType gtype = G_TYPE_POINTER;
       
   250       g_array_append_val (ret, gtype);
       
   251     }
       
   252 
       
   253   *params = ret;
       
   254   return TRUE;
       
   255 
       
   256  invalid_type:
       
   257   g_set_error (error,
       
   258 	       DBUS_BINDING_TOOL_ERROR,
       
   259 	       DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
       
   260 	       _("Unsupported conversion from D-BUS type %s to glib-genmarshal type"),
       
   261 	       arg_type);
       
   262   return FALSE;
       
   263 }
       
   264   
       
   265 
       
   266 static char *
       
   267 compute_marshaller (MethodInfo *method, GError **error)
       
   268 {
       
   269   GArray *signature;
       
   270   GType rettype;
       
   271   const char *marshal_name;
       
   272   GString *ret;
       
   273   guint i;
       
   274 
       
   275   if (!compute_gsignature (method, &rettype, &signature, error))
       
   276     return NULL;
       
   277 
       
   278   ret = g_string_new ("");
       
   279   marshal_name = dbus_g_type_get_marshal_name (rettype);
       
   280   g_assert (marshal_name != NULL);
       
   281   g_string_append (ret, marshal_name);
       
   282   g_string_append_c (ret, ':');
       
   283   for (i = 0; i < signature->len; i++)
       
   284     {
       
   285       marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i));
       
   286       g_assert (marshal_name != NULL);
       
   287       g_string_append (ret, marshal_name);
       
   288       if (i < signature->len - 1)
       
   289 	g_string_append_c (ret, ',');
       
   290     }
       
   291   if (signature->len == 0)
       
   292     {
       
   293       marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE);
       
   294       g_assert (marshal_name != NULL);
       
   295       g_string_append (ret, marshal_name);
       
   296     }
       
   297   g_array_free (signature, TRUE);
       
   298   return g_string_free (ret, FALSE);
       
   299 }
       
   300 
       
   301 static char *
       
   302 compute_marshaller_name (MethodInfo *method, const char *prefix, GError **error)
       
   303 {
       
   304   GString *ret;
       
   305   GArray *signature;
       
   306   GType rettype;
       
   307   const char *marshal_name;
       
   308   guint i;
       
   309 
       
   310   if (!compute_gsignature (method, &rettype, &signature, error))
       
   311     return NULL;
       
   312 
       
   313   ret = g_string_new (MARSHAL_PREFIX);
       
   314   g_string_append (ret, prefix);
       
   315   g_string_append_c (ret, '_');
       
   316 
       
   317   marshal_name = dbus_g_type_get_marshal_name (rettype);
       
   318   g_assert (marshal_name != NULL);
       
   319   g_string_append (ret, marshal_name);
       
   320   g_string_append (ret, "__");
       
   321   for (i = 0; i < signature->len; i++)
       
   322     {
       
   323       marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i));
       
   324       g_assert (marshal_name != NULL);
       
   325       g_string_append (ret, marshal_name);
       
   326       if (i < signature->len - 1)
       
   327 	g_string_append_c (ret, '_');
       
   328     }
       
   329   if (signature->len == 0)
       
   330     {
       
   331       marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE);
       
   332       g_assert (marshal_name != NULL);
       
   333       g_string_append (ret, marshal_name);
       
   334     }
       
   335   g_array_free (signature, TRUE);
       
   336   return g_string_free (ret, FALSE);
       
   337 }
       
   338 
       
   339 static gboolean
       
   340 gather_marshallers_list (GSList *list, DBusBindingToolCData *data, GError **error)
       
   341 {
       
   342   GSList *tmp;
       
   343 
       
   344   tmp = list;
       
   345   while (tmp != NULL)
       
   346     {
       
   347       if (!gather_marshallers (tmp->data, data, error))
       
   348 	return FALSE;
       
   349       tmp = tmp->next;
       
   350     }
       
   351   return TRUE;
       
   352 }
       
   353 
       
   354 static gboolean
       
   355 gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error)
       
   356 {
       
   357   if (base_info_get_type (base) == INFO_TYPE_NODE)
       
   358     {
       
   359       if (!gather_marshallers_list (node_info_get_nodes ((NodeInfo *) base),
       
   360 				    data, error))
       
   361 	return FALSE;
       
   362       if (!gather_marshallers_list (node_info_get_interfaces ((NodeInfo *) base),
       
   363 				    data, error))
       
   364 	return FALSE;
       
   365     }
       
   366   else
       
   367     {
       
   368       InterfaceInfo *interface;
       
   369       GSList *methods;
       
   370       GSList *tmp;
       
   371       const char *interface_c_name;
       
   372 
       
   373       interface = (InterfaceInfo *) base;
       
   374       interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_C_SYMBOL);
       
   375       if (interface_c_name == NULL)
       
   376         {
       
   377 	  if (!data->prefix)
       
   378 	    return TRUE;
       
   379         }
       
   380 
       
   381       methods = interface_info_get_methods (interface);
       
   382 
       
   383       /* Generate the necessary marshallers for the methods. */
       
   384 
       
   385       for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
       
   386         {
       
   387           MethodInfo *method;
       
   388           char *marshaller_name;
       
   389 
       
   390           method = (MethodInfo *) tmp->data;
       
   391 
       
   392           marshaller_name = compute_marshaller (method, error);
       
   393 	  if (!marshaller_name)
       
   394 	    return FALSE;
       
   395 
       
   396 	  if (g_hash_table_lookup (data->generated, marshaller_name))
       
   397 	    {
       
   398 	      g_free (marshaller_name);
       
   399 	      continue;
       
   400 	    }
       
   401 
       
   402 	  g_hash_table_insert (data->generated, marshaller_name, NULL);
       
   403         }
       
   404 
       
   405     }
       
   406   return TRUE;
       
   407 }
       
   408 
       
   409 static gboolean
       
   410 generate_glue_list (GSList *list, DBusBindingToolCData *data, GError **error)
       
   411 {
       
   412   GSList *tmp;
       
   413 
       
   414   tmp = list;
       
   415   while (tmp != NULL)
       
   416     {
       
   417       if (!generate_glue (tmp->data, data, error))
       
   418 	return FALSE;
       
   419       tmp = tmp->next;
       
   420     }
       
   421   return TRUE;
       
   422 }
       
   423 
       
   424 #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)
       
   425 
       
   426 static gboolean
       
   427 write_printf_to_iochannel (const char *fmt, GIOChannel *channel, GError **error, ...)
       
   428 {
       
   429   char *str;
       
   430   va_list args;
       
   431   GIOStatus status;
       
   432   gsize written;
       
   433   gboolean ret;
       
   434 
       
   435   va_start (args, error);
       
   436 
       
   437   str = g_strdup_vprintf (fmt, args);
       
   438   if ((status = g_io_channel_write_chars (channel, str, -1, &written, error)) == G_IO_STATUS_NORMAL)
       
   439     ret = TRUE;
       
   440   else
       
   441     ret = FALSE;
       
   442 
       
   443   g_free (str);
       
   444 
       
   445   va_end (args);
       
   446 
       
   447   return ret;
       
   448 }
       
   449 
       
   450 static gboolean
       
   451 write_quoted_string (GIOChannel *channel, GString *string, GError **error)
       
   452 {
       
   453   guint i;
       
   454 
       
   455   WRITE_OR_LOSE ("\"");
       
   456   for (i = 0; i < string->len; i++)
       
   457     {
       
   458       if (string->str[i] != '\0')
       
   459 	{
       
   460 	  if (!g_io_channel_write_chars (channel, string->str + i, 1, NULL, error))
       
   461 	    return FALSE;
       
   462 	}
       
   463       else
       
   464 	{
       
   465 	  if (!g_io_channel_write_chars (channel, "\\0", -1, NULL, error))
       
   466 	    return FALSE;
       
   467 	}
       
   468     }
       
   469   WRITE_OR_LOSE ("\\0\"");
       
   470   return TRUE;
       
   471  io_lose:
       
   472   return FALSE;
       
   473 }
       
   474 
       
   475 static gboolean
       
   476 generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
       
   477 {
       
   478   if (base_info_get_type (base) == INFO_TYPE_NODE)
       
   479     {
       
   480       GString *object_introspection_data_blob;
       
   481       GIOChannel *channel;
       
   482 
       
   483       channel = data->channel;
       
   484       
       
   485       object_introspection_data_blob = g_string_new_len ("", 0);
       
   486       
       
   487       data->blob = object_introspection_data_blob;
       
   488       data->count = 0;
       
   489 
       
   490       data->signal_blob = g_string_new_len ("", 0);
       
   491       data->property_blob = g_string_new_len ("", 0);
       
   492 
       
   493       if (!write_printf_to_iochannel ("static const DBusGMethodInfo dbus_glib_%s_methods[] = {\n", channel, error, data->prefix))
       
   494 	goto io_lose;
       
   495 
       
   496       if (!generate_glue_list (node_info_get_nodes ((NodeInfo *) base),
       
   497 			       data, error))
       
   498 	return FALSE;
       
   499       if (!generate_glue_list (node_info_get_interfaces ((NodeInfo *) base),
       
   500 			       data, error))
       
   501 	return FALSE;
       
   502 
       
   503       WRITE_OR_LOSE ("};\n\n");
       
   504 
       
   505       /* Information about the object. */
       
   506 
       
   507       if (!write_printf_to_iochannel ("const DBusGObjectInfo dbus_glib_%s_object_info = {\n",
       
   508 				      channel, error, data->prefix))
       
   509 	goto io_lose;
       
   510       WRITE_OR_LOSE ("  0,\n");
       
   511       if (!write_printf_to_iochannel ("  dbus_glib_%s_methods,\n", channel, error, data->prefix))
       
   512 	goto io_lose;
       
   513       if (!write_printf_to_iochannel ("  %d,\n", channel, error, data->count))
       
   514 	goto io_lose;
       
   515 
       
   516       if (!write_quoted_string (channel, object_introspection_data_blob, error))
       
   517 	goto io_lose;
       
   518       WRITE_OR_LOSE (",\n");
       
   519       if (!write_quoted_string (channel, data->signal_blob, error))
       
   520 	goto io_lose;
       
   521       WRITE_OR_LOSE (",\n");
       
   522       if (!write_quoted_string (channel, data->property_blob, error))
       
   523 	goto io_lose;
       
   524       WRITE_OR_LOSE ("\n};\n\n");
       
   525 
       
   526       g_string_free (object_introspection_data_blob, TRUE);
       
   527       g_string_free (data->signal_blob, TRUE);
       
   528       g_string_free (data->property_blob, TRUE);
       
   529     }
       
   530   else
       
   531     {
       
   532       GIOChannel *channel;
       
   533       InterfaceInfo *interface;
       
   534       GSList *methods;
       
   535       GSList *signals;
       
   536       GSList *properties;
       
   537       GSList *tmp;
       
   538       const char *interface_c_name;
       
   539       GString *object_introspection_data_blob;
       
   540 
       
   541       channel = data->channel;
       
   542       object_introspection_data_blob = data->blob;
       
   543 
       
   544       interface = (InterfaceInfo *) base;
       
   545       interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_C_SYMBOL);
       
   546       if (interface_c_name == NULL)
       
   547         {
       
   548 	  if (data->prefix == NULL)
       
   549 	    return TRUE;
       
   550 	  interface_c_name = data->prefix;
       
   551         }
       
   552 
       
   553       methods = interface_info_get_methods (interface);
       
   554 
       
   555       /* Table of marshalled methods. */
       
   556 
       
   557       for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
       
   558         {
       
   559           MethodInfo *method;
       
   560           char *marshaller_name;
       
   561 	  char *method_c_name;
       
   562           gboolean async = FALSE;
       
   563 	  GSList *args;
       
   564 	  gboolean found_retval = FALSE;
       
   565 
       
   566           method = (MethodInfo *) tmp->data;
       
   567 	  method_c_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_C_SYMBOL));
       
   568           if (method_c_name == NULL)
       
   569 	    {
       
   570 	      char *method_name_uscored;
       
   571 	      method_name_uscored = _dbus_gutils_wincaps_to_uscore (method_info_get_name (method));
       
   572               method_c_name = g_strdup_printf ("%s_%s",
       
   573 					       interface_c_name,
       
   574 					       method_name_uscored);
       
   575 	      g_free (method_name_uscored);
       
   576             }
       
   577 
       
   578           if (!write_printf_to_iochannel ("  { (GCallback) %s, ", channel, error,
       
   579 					  method_c_name))
       
   580 	    goto io_lose;
       
   581 
       
   582           marshaller_name = compute_marshaller_name (method, data->prefix, error);
       
   583 	  if (!marshaller_name)
       
   584 	    goto io_lose;
       
   585 
       
   586           if (!write_printf_to_iochannel ("%s, %d },\n", channel, error,
       
   587 					  marshaller_name,
       
   588 					  object_introspection_data_blob->len))
       
   589 	    {
       
   590 	      g_free (marshaller_name);
       
   591 	      goto io_lose;
       
   592 	    }
       
   593 
       
   594           if (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL)
       
   595             async = TRUE;
       
   596 
       
   597 	  /* Object method data blob format:
       
   598 	   * <iface>\0<name>\0(<argname>\0<argdirection>\0<argtype>\0)*\0
       
   599 	   */
       
   600 
       
   601 	  g_string_append (object_introspection_data_blob, interface_info_get_name (interface));
       
   602 	  g_string_append_c (object_introspection_data_blob, '\0');
       
   603 
       
   604 	  g_string_append (object_introspection_data_blob, method_info_get_name (method));
       
   605 	  g_string_append_c (object_introspection_data_blob, '\0');
       
   606 
       
   607 	  g_string_append_c (object_introspection_data_blob, async ? 'A' : 'S');
       
   608 	  g_string_append_c (object_introspection_data_blob, '\0');
       
   609 
       
   610 	  for (args = method_info_get_args (method); args; args = args->next)
       
   611 	    {
       
   612 	      ArgInfo *arg;
       
   613 	      char direction;
       
   614 	      const char *returnval_annotation;
       
   615 
       
   616 	      arg = args->data;
       
   617 
       
   618 	      g_string_append (object_introspection_data_blob, arg_info_get_name (arg));
       
   619 	      g_string_append_c (object_introspection_data_blob, '\0');
       
   620 
       
   621 	      switch (arg_info_get_direction (arg))
       
   622 		{
       
   623 		case ARG_IN:
       
   624 		  direction = 'I';
       
   625 		  break;
       
   626 		case ARG_OUT:
       
   627 		  direction = 'O';
       
   628 		  break;
       
   629 		case ARG_INVALID:
       
   630                 default:
       
   631                   g_assert_not_reached ();
       
   632                   direction = 0; /* silence gcc */
       
   633 		  break;
       
   634 		}
       
   635 	      g_string_append_c (object_introspection_data_blob, direction);
       
   636 	      g_string_append_c (object_introspection_data_blob, '\0');
       
   637 
       
   638 	      if (arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_CONST) != NULL)
       
   639 		{
       
   640 		  if (arg_info_get_direction (arg) == ARG_IN)
       
   641 		    {
       
   642 		      g_set_error (error,
       
   643 				   DBUS_BINDING_TOOL_ERROR,
       
   644 				   DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
       
   645 				   "Input argument \"%s\" cannot have const annotation in method \"%s\" of interface \"%s\"\n",
       
   646 				   arg_info_get_name (arg),
       
   647 				   method_info_get_name (method),
       
   648 				   interface_info_get_name (interface));
       
   649 		      return FALSE;
       
   650 		    }
       
   651 		  g_string_append_c (object_introspection_data_blob, 'C');
       
   652 		  g_string_append_c (object_introspection_data_blob, '\0');
       
   653 		}
       
   654 	      else if (arg_info_get_direction (arg) == ARG_OUT)
       
   655 		{
       
   656 		  g_string_append_c (object_introspection_data_blob, 'F');
       
   657 		  g_string_append_c (object_introspection_data_blob, '\0');
       
   658 		}
       
   659 
       
   660 	      returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL);
       
   661 	      if (returnval_annotation != NULL)
       
   662 		{
       
   663 		  GType gtype;
       
   664 
       
   665 		  if (found_retval)
       
   666 		    {
       
   667 		      g_set_error (error,
       
   668 				   DBUS_BINDING_TOOL_ERROR,
       
   669 				   DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
       
   670 				   "Multiple arguments with return value annotation in method \"%s\" of interface \"%s\"\n",
       
   671 				   method_info_get_name (method),
       
   672 				   interface_info_get_name (interface));
       
   673 		      return FALSE;
       
   674 		    }
       
   675 		  found_retval = TRUE;
       
   676 		  if (arg_info_get_direction (arg) == ARG_IN)
       
   677 		    {
       
   678 		      g_set_error (error,
       
   679 				   DBUS_BINDING_TOOL_ERROR,
       
   680 				   DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
       
   681 				   "Input argument \"%s\" cannot have return value annotation in method \"%s\" of interface \"%s\"\n",
       
   682 				   arg_info_get_name (arg),
       
   683 				   method_info_get_name (method),
       
   684 				   interface_info_get_name (interface));
       
   685 		      return FALSE;
       
   686 		    }
       
   687 		  if (!strcmp ("", returnval_annotation))
       
   688 		    g_string_append_c (object_introspection_data_blob, 'R');
       
   689 		  else if (!strcmp ("error", returnval_annotation))
       
   690 		    {
       
   691 		      gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
       
   692 		      if (!_dbus_gtype_can_signal_error (gtype))
       
   693 			{
       
   694 			  g_set_error (error,
       
   695 				       DBUS_BINDING_TOOL_ERROR,
       
   696 				       DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
       
   697 				       "Output argument \"%s\" cannot signal error with type \"%s\" in method \"%s\" of interface \"%s\"\n",
       
   698 				       arg_info_get_name (arg),
       
   699 				       g_type_name (gtype),
       
   700 				       method_info_get_name (method),
       
   701 				       interface_info_get_name (interface));
       
   702 			  return FALSE;
       
   703 			}
       
   704 		      g_string_append_c (object_introspection_data_blob, 'E');
       
   705 		    }
       
   706 		  else
       
   707 		    {
       
   708 		      g_set_error (error,
       
   709 				   DBUS_BINDING_TOOL_ERROR,
       
   710 				   DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
       
   711 				   "Invalid ReturnVal annotation for argument \"%s\" in method \"%s\" of interface \"%s\"\n",
       
   712 				   arg_info_get_name (arg),
       
   713 				   method_info_get_name (method),
       
   714 				   interface_info_get_name (interface));
       
   715 		      return FALSE;
       
   716 		    }
       
   717 		      
       
   718 		  g_string_append_c (object_introspection_data_blob, '\0');
       
   719 		}
       
   720 	      else if (arg_info_get_direction (arg) == ARG_OUT)
       
   721 		{
       
   722 		  g_string_append_c (object_introspection_data_blob, 'N');
       
   723 		  g_string_append_c (object_introspection_data_blob, '\0');
       
   724 		}
       
   725 
       
   726 	      g_string_append (object_introspection_data_blob, arg_info_get_type (arg));
       
   727 	      g_string_append_c (object_introspection_data_blob, '\0');
       
   728 	    }
       
   729 
       
   730 	  g_string_append_c (object_introspection_data_blob, '\0');
       
   731 
       
   732           data->count++;
       
   733         }
       
   734 
       
   735       signals = interface_info_get_signals (interface);
       
   736 
       
   737       for (tmp = signals; tmp != NULL; tmp = g_slist_next (tmp))
       
   738         {
       
   739           SignalInfo *sig;
       
   740 	  
       
   741 	  sig = tmp->data;
       
   742 
       
   743 	  g_string_append (data->signal_blob, interface_info_get_name (interface));
       
   744 	  g_string_append_c (data->signal_blob, '\0');
       
   745 	  g_string_append (data->signal_blob, signal_info_get_name (sig));
       
   746 	  g_string_append_c (data->signal_blob, '\0');
       
   747 	}
       
   748 
       
   749       properties = interface_info_get_properties (interface);
       
   750 
       
   751       for (tmp = properties; tmp != NULL; tmp = g_slist_next (tmp))
       
   752         {
       
   753           PropertyInfo *prop;
       
   754 	  
       
   755 	  prop = tmp->data;
       
   756 
       
   757 	  g_string_append (data->property_blob, interface_info_get_name (interface));
       
   758 	  g_string_append_c (data->property_blob, '\0');
       
   759 	  g_string_append (data->property_blob, property_info_get_name (prop));
       
   760 	  g_string_append_c (data->property_blob, '\0');
       
   761 	}
       
   762     }
       
   763   return TRUE;
       
   764  io_lose:
       
   765   return FALSE;
       
   766 }
       
   767 
       
   768 static void
       
   769 write_marshaller (gpointer key, gpointer value, gpointer user_data)
       
   770 {
       
   771   DBusBindingToolCData *data;
       
   772   const char *marshaller;
       
   773   gsize bytes_written;
       
   774 
       
   775   data = user_data;
       
   776   marshaller = key;
       
   777 
       
   778   if (data->error && *data->error)
       
   779     return;
       
   780 
       
   781   if (g_io_channel_write_chars (data->channel, marshaller, -1, &bytes_written, data->error) == G_IO_STATUS_NORMAL)
       
   782     g_io_channel_write_chars (data->channel, "\n", -1, &bytes_written, data->error);
       
   783 }
       
   784 
       
   785 gboolean
       
   786 dbus_binding_tool_output_glib_server (BaseInfo *info, GIOChannel *channel, const char *prefix, GError **error)
       
   787 {
       
   788   gboolean ret;
       
   789   GPtrArray *argv;
       
   790   gint child_stdout;
       
   791   GIOChannel *genmarshal_stdout;
       
   792   GPid child_pid;
       
   793   DBusBindingToolCData data;
       
   794   char *tempfile_name;
       
   795   gint tempfile_fd;
       
   796   GIOStatus iostatus;
       
   797   char buf[4096];
       
   798   gsize bytes_read, bytes_written;
       
   799 
       
   800   memset (&data, 0, sizeof (data));
       
   801 
       
   802   dbus_g_type_specialized_init ();
       
   803   _dbus_g_type_specialized_builtins_init ();
       
   804 
       
   805   data.prefix = prefix;
       
   806   data.generated = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
       
   807   data.error = error;
       
   808   genmarshal_stdout = NULL;
       
   809   tempfile_name = NULL;
       
   810 
       
   811   if (!gather_marshallers (info, &data, error))
       
   812     goto io_lose;
       
   813 
       
   814   tempfile_fd = g_file_open_tmp ("dbus-binding-tool-c-marshallers.XXXXXX",
       
   815 				 &tempfile_name, error);
       
   816   if (tempfile_fd < 0)
       
   817     goto io_lose;
       
   818 
       
   819   data.channel = g_io_channel_unix_new (tempfile_fd);
       
   820   if (!g_io_channel_set_encoding (data.channel, NULL, error))
       
   821     goto io_lose;
       
   822   g_hash_table_foreach (data.generated, write_marshaller, &data); 
       
   823   if (error && *error != NULL)
       
   824     {
       
   825       ret = FALSE;
       
   826       g_io_channel_close (data.channel);
       
   827       g_io_channel_unref (data.channel);
       
   828       goto io_lose;
       
   829     }
       
   830 
       
   831   g_io_channel_close (data.channel);
       
   832   g_io_channel_unref (data.channel);
       
   833   
       
   834   /* Now spawn glib-genmarshal to insert all our required marshallers */
       
   835   argv = g_ptr_array_new ();
       
   836   g_ptr_array_add (argv, "glib-genmarshal");
       
   837   g_ptr_array_add (argv, "--header");
       
   838   g_ptr_array_add (argv, "--body");
       
   839   g_ptr_array_add (argv, g_strdup_printf ("--prefix=%s%s", MARSHAL_PREFIX, prefix));
       
   840   g_ptr_array_add (argv, tempfile_name);
       
   841   g_ptr_array_add (argv, NULL);
       
   842   if (!g_spawn_async_with_pipes (NULL, (char**)argv->pdata, NULL,
       
   843 				 G_SPAWN_SEARCH_PATH,
       
   844 				 NULL, NULL,
       
   845 				 &child_pid,
       
   846 				 NULL,
       
   847 				 &child_stdout, NULL, error))
       
   848     {
       
   849       g_ptr_array_free (argv, TRUE);
       
   850       goto io_lose;
       
   851     }
       
   852   g_ptr_array_free (argv, TRUE);
       
   853 
       
   854   genmarshal_stdout = g_io_channel_unix_new (child_stdout);
       
   855   if (!g_io_channel_set_encoding (genmarshal_stdout, NULL, error))
       
   856     goto io_lose;
       
   857 
       
   858   WRITE_OR_LOSE ("/* Generated by dbus-binding-tool; do not edit! */\n\n");
       
   859 
       
   860   while ((iostatus = g_io_channel_read_chars (genmarshal_stdout, buf, sizeof (buf),
       
   861 					      &bytes_read, error)) == G_IO_STATUS_NORMAL)
       
   862     if (g_io_channel_write_chars (channel, buf, bytes_read, &bytes_written, error) != G_IO_STATUS_NORMAL)
       
   863       goto io_lose;
       
   864   if (iostatus != G_IO_STATUS_EOF)
       
   865     goto io_lose;
       
   866 
       
   867   g_io_channel_close (genmarshal_stdout);
       
   868 
       
   869   WRITE_OR_LOSE ("#include <dbus/dbus-glib.h>\n");
       
   870 
       
   871   data.channel = channel;
       
   872   g_io_channel_ref (data.channel);
       
   873   if (!generate_glue (info, &data, error))
       
   874     goto io_lose;
       
   875   
       
   876   ret = TRUE;
       
   877  cleanup:
       
   878   if (tempfile_name)
       
   879     unlink (tempfile_name);
       
   880   g_free (tempfile_name);
       
   881   if (genmarshal_stdout)
       
   882     g_io_channel_unref (genmarshal_stdout);
       
   883   if (data.channel)
       
   884     g_io_channel_unref (data.channel);
       
   885   g_hash_table_destroy (data.generated);
       
   886 
       
   887   return ret;
       
   888  io_lose:
       
   889   ret = FALSE;
       
   890   goto cleanup;
       
   891 }
       
   892 
       
   893 static char *
       
   894 iface_to_c_prefix (const char *iface)
       
   895 {
       
   896   char **components;
       
   897   char **component;
       
   898   GString *ret;
       
   899   gboolean first;
       
   900   
       
   901   components = g_strsplit (iface, ".", 0);
       
   902 
       
   903   first = TRUE;
       
   904   ret = g_string_new ("");
       
   905   for (component = components; *component; component++)
       
   906     {
       
   907       if (!first)
       
   908 	g_string_append_c (ret, '_');
       
   909       else
       
   910 	first = FALSE;
       
   911       g_string_append (ret, *component);
       
   912     }
       
   913   g_strfreev (components);
       
   914   return g_string_free (ret, FALSE);
       
   915 }
       
   916 
       
   917 static char *
       
   918 compute_client_method_name (const char *iface_prefix, MethodInfo *method)
       
   919 {
       
   920   char *method_name_uscored, *ret;
       
   921 
       
   922   method_name_uscored = _dbus_gutils_wincaps_to_uscore (method_info_get_name (method));
       
   923   ret = g_strdup_printf ("%s_%s", iface_prefix, method_name_uscored);
       
   924   g_free (method_name_uscored);
       
   925 
       
   926   return ret;
       
   927 }
       
   928 
       
   929 static gboolean
       
   930 write_formal_parameters (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, GError **error)
       
   931 {
       
   932   GSList *args;
       
   933 
       
   934   for (args = method_info_get_args (method); args; args = args->next)
       
   935     {
       
   936       ArgInfo *arg;
       
   937       const char *type_str;
       
   938       const char *type_suffix;
       
   939       GType gtype;
       
   940       int direction;
       
   941 
       
   942       arg = args->data;
       
   943 
       
   944       WRITE_OR_LOSE (", ");
       
   945 
       
   946       direction = arg_info_get_direction (arg);
       
   947 
       
   948       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
       
   949       if (gtype == G_TYPE_INVALID)
       
   950 	{
       
   951 	  g_set_error (error,
       
   952 		       DBUS_BINDING_TOOL_ERROR,
       
   953 		       DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
       
   954 		       _("Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\""),
       
   955 		       arg_info_get_type (arg),
       
   956 		       method_info_get_name (method),
       
   957 		       interface_info_get_name (iface));
       
   958 	  return FALSE;
       
   959 	}
       
   960       type_str = dbus_g_type_get_c_name (gtype);
       
   961       g_assert (type_str);
       
   962       /* Variants are special...*/
       
   963       if (gtype == G_TYPE_VALUE)
       
   964 	{
       
   965 	  if (direction == ARG_IN)
       
   966 	    type_suffix = "*";
       
   967 	  else
       
   968 	    type_suffix = "";
       
   969 	}
       
   970       else if ((g_type_is_a (gtype, G_TYPE_BOXED)
       
   971 	      || g_type_is_a (gtype, G_TYPE_OBJECT)
       
   972 	   || g_type_is_a (gtype, G_TYPE_POINTER)))
       
   973 	type_suffix = "*";
       
   974       else
       
   975 	type_suffix = "";
       
   976 
       
   977 
       
   978       switch (direction)
       
   979 	{
       
   980 	case ARG_IN:
       
   981 	  if (!write_printf_to_iochannel ("const %s%s IN_%s", channel, error,
       
   982 					  type_str,
       
   983 					  type_suffix,
       
   984 					  arg_info_get_name (arg)))
       
   985 	    goto io_lose;
       
   986 	  break;
       
   987 	case ARG_OUT:
       
   988 	  if (!write_printf_to_iochannel ("%s%s* OUT_%s", channel, error,
       
   989 					  type_str,
       
   990 					  type_suffix,
       
   991 					  arg_info_get_name (arg)))
       
   992 	    goto io_lose;
       
   993 	  break;
       
   994 	case ARG_INVALID:
       
   995 	  break;
       
   996 	}
       
   997     }
       
   998 
       
   999   return TRUE;
       
  1000  io_lose:
       
  1001   return FALSE;
       
  1002 }
       
  1003 
       
  1004 #define MAP_FUNDAMENTAL(NAME) \
       
  1005    case G_TYPE_ ## NAME: \
       
  1006      return g_strdup ("G_TYPE_" #NAME);
       
  1007 #define MAP_KNOWN(NAME) \
       
  1008     if (gtype == NAME) \
       
  1009       return g_strdup (#NAME)
       
  1010 static char *
       
  1011 dbus_g_type_get_lookup_function (GType gtype)
       
  1012 {
       
  1013   char *type_lookup;
       
  1014   switch (gtype)
       
  1015     {
       
  1016       MAP_FUNDAMENTAL(CHAR);
       
  1017       MAP_FUNDAMENTAL(UCHAR);
       
  1018       MAP_FUNDAMENTAL(BOOLEAN);
       
  1019       MAP_FUNDAMENTAL(LONG);
       
  1020       MAP_FUNDAMENTAL(ULONG);
       
  1021       MAP_FUNDAMENTAL(INT);
       
  1022       MAP_FUNDAMENTAL(UINT);
       
  1023       MAP_FUNDAMENTAL(INT64);
       
  1024       MAP_FUNDAMENTAL(UINT64);
       
  1025       MAP_FUNDAMENTAL(FLOAT);
       
  1026       MAP_FUNDAMENTAL(DOUBLE);
       
  1027       MAP_FUNDAMENTAL(STRING);
       
  1028     }
       
  1029   if (dbus_g_type_is_collection (gtype))
       
  1030     {
       
  1031       GType elt_gtype;
       
  1032       char *sublookup;
       
  1033 
       
  1034       elt_gtype = dbus_g_type_get_collection_specialization (gtype);
       
  1035       sublookup = dbus_g_type_get_lookup_function (elt_gtype);
       
  1036       g_assert (sublookup);
       
  1037 
       
  1038       if (_dbus_g_type_is_fixed (elt_gtype))
       
  1039         {
       
  1040           type_lookup = g_strdup_printf ("dbus_g_type_get_collection "
       
  1041               "(\"GArray\", %s)", sublookup);
       
  1042         }
       
  1043       else
       
  1044         {
       
  1045           type_lookup = g_strdup_printf ("dbus_g_type_get_collection "
       
  1046               "(\"GPtrArray\", %s)", sublookup);
       
  1047         }
       
  1048 
       
  1049       g_free (sublookup);
       
  1050 
       
  1051       return type_lookup;
       
  1052     }
       
  1053   else if (dbus_g_type_is_map (gtype))
       
  1054     {
       
  1055       GType key_gtype;
       
  1056       char *key_lookup;
       
  1057       GType value_gtype;
       
  1058       char *value_lookup;
       
  1059       
       
  1060       key_gtype = dbus_g_type_get_map_key_specialization (gtype);
       
  1061       value_gtype = dbus_g_type_get_map_value_specialization (gtype);
       
  1062       key_lookup = dbus_g_type_get_lookup_function (key_gtype);
       
  1063       g_assert (key_lookup);
       
  1064       value_lookup = dbus_g_type_get_lookup_function (value_gtype);
       
  1065       g_assert (value_lookup);
       
  1066       type_lookup = g_strdup_printf ("dbus_g_type_get_map (\"GHashTable\", %s, %s)",
       
  1067 				     key_lookup, value_lookup);
       
  1068       g_free (key_lookup);
       
  1069       g_free (value_lookup);
       
  1070       return type_lookup;
       
  1071     }
       
  1072   else if (dbus_g_type_is_struct (gtype))
       
  1073     {
       
  1074       GType value_gtype;
       
  1075       GString *string;
       
  1076       char *value_lookup = NULL;
       
  1077       guint size, i;
       
  1078 
       
  1079       string = g_string_new ("dbus_g_type_get_struct (\"GValueArray\"");
       
  1080 
       
  1081       size = dbus_g_type_get_struct_size (gtype);
       
  1082       for (i=0; i < size; i++)
       
  1083         {
       
  1084           value_gtype = dbus_g_type_get_struct_member_type(gtype, i);
       
  1085           value_lookup = dbus_g_type_get_lookup_function (value_gtype);
       
  1086           g_assert (value_lookup);
       
  1087           g_string_append_printf (string, ", %s", value_lookup);
       
  1088           g_free (value_lookup);
       
  1089         }
       
  1090       g_string_append (string, ", G_TYPE_INVALID)");
       
  1091       return g_string_free (string, FALSE);
       
  1092     }
       
  1093 
       
  1094   MAP_KNOWN(G_TYPE_VALUE);
       
  1095   MAP_KNOWN(G_TYPE_STRV);
       
  1096   MAP_KNOWN(G_TYPE_VALUE_ARRAY);
       
  1097   MAP_KNOWN(DBUS_TYPE_G_PROXY);
       
  1098   MAP_KNOWN(DBUS_TYPE_G_OBJECT_PATH);
       
  1099   return NULL;
       
  1100 }
       
  1101 #undef MAP_FUNDAMENTAL
       
  1102 #undef MAP_KNOWN
       
  1103 
       
  1104 static gboolean
       
  1105 write_args_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, int direction, GError **error)
       
  1106 {
       
  1107   GSList *args;
       
  1108 
       
  1109   for (args = method_info_get_args (method); args; args = args->next)
       
  1110     {
       
  1111       ArgInfo *arg;
       
  1112       GType gtype;
       
  1113       char *type_lookup;
       
  1114 
       
  1115       arg = args->data;
       
  1116 
       
  1117       if (direction != arg_info_get_direction (arg))
       
  1118 	continue;
       
  1119 
       
  1120       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
       
  1121       g_assert (gtype != G_TYPE_INVALID);
       
  1122       type_lookup = dbus_g_type_get_lookup_function (gtype);
       
  1123       g_assert (type_lookup != NULL);
       
  1124 
       
  1125       switch (direction)
       
  1126 	{
       
  1127 
       
  1128 	case ARG_IN:
       
  1129 	  if (!write_printf_to_iochannel ("%s, IN_%s, ", channel, error,
       
  1130 					  type_lookup,
       
  1131 					  arg_info_get_name (arg)))
       
  1132 	    goto io_lose;
       
  1133 	  break;
       
  1134 	case ARG_OUT:
       
  1135 	  if (!write_printf_to_iochannel ("%s, OUT_%s, ", channel, error,
       
  1136 					  type_lookup,
       
  1137 					  arg_info_get_name (arg)))
       
  1138 	    goto io_lose;
       
  1139 	  break;
       
  1140 	case ARG_INVALID:
       
  1141 	  break;
       
  1142 	}
       
  1143       g_free (type_lookup);
       
  1144     }
       
  1145 
       
  1146   return TRUE;
       
  1147  io_lose:
       
  1148   return FALSE;
       
  1149 }
       
  1150 
       
  1151 static gboolean
       
  1152 check_supported_parameters (MethodInfo *method)
       
  1153 {
       
  1154   GSList *args;
       
  1155 
       
  1156   for (args = method_info_get_args (method); args; args = args->next)
       
  1157     {
       
  1158       ArgInfo *arg;
       
  1159       GType gtype;
       
  1160 
       
  1161       arg = args->data;
       
  1162       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
       
  1163       if (gtype == G_TYPE_INVALID)
       
  1164 	return FALSE;
       
  1165     }
       
  1166   return TRUE;
       
  1167 }
       
  1168 
       
  1169 static gboolean
       
  1170 write_untyped_out_args (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, GError **error)
       
  1171 {
       
  1172   GSList *args;
       
  1173 
       
  1174   for (args = method_info_get_args (method); args; args = args->next)
       
  1175     {
       
  1176       ArgInfo *arg;
       
  1177 
       
  1178       arg = args->data;
       
  1179       if (arg_info_get_direction (arg) != ARG_OUT)
       
  1180         continue;
       
  1181             
       
  1182       if (!write_printf_to_iochannel ("OUT_%s, ", channel, error,
       
  1183                                       arg_info_get_name (arg)))
       
  1184         goto io_lose;
       
  1185      }
       
  1186 
       
  1187    return TRUE;
       
  1188  io_lose:
       
  1189   return FALSE;
       
  1190 }
       
  1191 
       
  1192 static gboolean
       
  1193 write_formal_declarations_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, const int direction, GError **error)
       
  1194  {
       
  1195    GSList *args;
       
  1196  
       
  1197    for (args = method_info_get_args (method); args; args = args->next)
       
  1198      {
       
  1199        ArgInfo *arg;
       
  1200       GType gtype;
       
  1201       const char *type_str, *type_suffix;
       
  1202       int dir;
       
  1203 
       
  1204        arg = args->data;
       
  1205 
       
  1206       dir = arg_info_get_direction (arg);
       
  1207 
       
  1208       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
       
  1209       type_str = dbus_g_type_get_c_name (gtype);
       
  1210 
       
  1211       if (!type_str)
       
  1212        {
       
  1213          g_set_error (error,
       
  1214                       DBUS_BINDING_TOOL_ERROR,
       
  1215                       DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
       
  1216                       _("Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\""),
       
  1217                       arg_info_get_type (arg),
       
  1218                       method_info_get_name (method),
       
  1219                       interface_info_get_name (iface));
       
  1220          return FALSE;
       
  1221        }
       
  1222 
       
  1223       /* Variants are special...*/
       
  1224       if (gtype == G_TYPE_VALUE)
       
  1225 	{
       
  1226 	  if (direction == ARG_IN)
       
  1227 	    type_suffix = "*";
       
  1228 	  else
       
  1229 	    type_suffix = "";
       
  1230 	}
       
  1231       else if ((g_type_is_a (gtype, G_TYPE_BOXED)
       
  1232 	      || g_type_is_a (gtype, G_TYPE_OBJECT)
       
  1233 	   || g_type_is_a (gtype, G_TYPE_POINTER)))
       
  1234 	type_suffix = "*";
       
  1235       else
       
  1236 	type_suffix = "";
       
  1237 
       
  1238       if (direction != dir)
       
  1239         continue;
       
  1240 
       
  1241           switch (dir)
       
  1242        {
       
  1243        case ARG_IN:
       
  1244          if (!write_printf_to_iochannel ("  %s%s IN_%s;\n", channel, error,
       
  1245                                          type_str, type_suffix,
       
  1246                                          arg_info_get_name (arg)))
       
  1247            goto io_lose;
       
  1248          break;
       
  1249        case ARG_OUT:
       
  1250          if (!write_printf_to_iochannel ("  %s%s OUT_%s;\n", channel, error,
       
  1251                                          type_str, type_suffix,
       
  1252                                          arg_info_get_name (arg)))
       
  1253            goto io_lose;
       
  1254          break;
       
  1255        case ARG_INVALID:
       
  1256          break;
       
  1257        }
       
  1258      }
       
  1259    return TRUE;
       
  1260  io_lose:
       
  1261   return FALSE;
       
  1262  }
       
  1263 
       
  1264 static gboolean
       
  1265 write_formal_parameters_for_direction (InterfaceInfo *iface, MethodInfo *method, int dir, GIOChannel *channel, GError **error)
       
  1266 {
       
  1267   GSList *args;
       
  1268 
       
  1269   for (args = method_info_get_args (method); args; args = args->next)
       
  1270     {
       
  1271       ArgInfo *arg;
       
  1272       const char *type_str;
       
  1273       const char *type_suffix;
       
  1274       GType gtype;
       
  1275       int direction;
       
  1276 
       
  1277       arg = args->data;
       
  1278 
       
  1279       direction = arg_info_get_direction (arg);
       
  1280       if (dir != direction) continue;
       
  1281       
       
  1282       WRITE_OR_LOSE (", ");
       
  1283 
       
  1284       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
       
  1285       type_str = dbus_g_type_get_c_name (gtype);
       
  1286       /* Variants are special...*/
       
  1287       if (gtype == G_TYPE_VALUE)
       
  1288 	{
       
  1289 	  if (direction == ARG_IN)
       
  1290 	    type_suffix = "*";
       
  1291 	  else
       
  1292 	    type_suffix = "";
       
  1293 	}
       
  1294       else if ((g_type_is_a (gtype, G_TYPE_BOXED)
       
  1295 	      || g_type_is_a (gtype, G_TYPE_OBJECT)
       
  1296 	   || g_type_is_a (gtype, G_TYPE_POINTER)))
       
  1297 	type_suffix = "*";
       
  1298       else
       
  1299 	type_suffix = "";
       
  1300 
       
  1301       if (!type_str)
       
  1302 	{
       
  1303 	  g_set_error (error,
       
  1304 		       DBUS_BINDING_TOOL_ERROR,
       
  1305 		       DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
       
  1306 		       _("Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\""),
       
  1307 		       arg_info_get_type (arg),
       
  1308 		       method_info_get_name (method),
       
  1309 		       interface_info_get_name (iface));
       
  1310 	  return FALSE;
       
  1311 	}
       
  1312  
       
  1313        switch (direction)
       
  1314  	{
       
  1315  	case ARG_IN:
       
  1316 	  if (!write_printf_to_iochannel ("const %s%s IN_%s", channel, error,
       
  1317 					  type_str,
       
  1318 					  type_suffix,
       
  1319 					  arg_info_get_name (arg)))
       
  1320  	    goto io_lose;
       
  1321  	  break;
       
  1322  	case ARG_OUT:
       
  1323 	  if (!write_printf_to_iochannel ("%s%s* OUT_%s", channel, error,
       
  1324 					  type_str,
       
  1325 					  type_suffix,
       
  1326 					  arg_info_get_name (arg)))
       
  1327  	    goto io_lose;
       
  1328  	  break;
       
  1329  	case ARG_INVALID:
       
  1330 	  break;
       
  1331 	}
       
  1332     }
       
  1333   return TRUE;
       
  1334  io_lose:
       
  1335   return FALSE;
       
  1336 }
       
  1337 
       
  1338 static gboolean
       
  1339 write_typed_args_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, const int direction, GError **error)
       
  1340  {
       
  1341   GSList *args;
       
  1342   
       
  1343   for (args = method_info_get_args (method); args; args = args->next)
       
  1344     {
       
  1345       ArgInfo *arg;
       
  1346       int dir;
       
  1347       GType gtype;
       
  1348       const char *type_lookup;
       
  1349       
       
  1350       arg = args->data;
       
  1351 
       
  1352       dir = arg_info_get_direction (arg);
       
  1353 
       
  1354       if (dir != direction)
       
  1355         continue;
       
  1356 
       
  1357       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
       
  1358       type_lookup = dbus_g_type_get_lookup_function (gtype);
       
  1359 
       
  1360       if (!write_printf_to_iochannel ("%s, &%s_%s, ", channel, error, type_lookup, direction == ARG_IN ? "IN" : "OUT", arg_info_get_name (arg)))
       
  1361           goto io_lose;
       
  1362     }
       
  1363   return TRUE;
       
  1364  io_lose:
       
  1365   return FALSE;
       
  1366 }
       
  1367 
       
  1368 static gboolean
       
  1369 write_async_method_client (GIOChannel *channel, InterfaceInfo *interface, MethodInfo *method, GError **error)
       
  1370 {
       
  1371   char *method_name, *iface_prefix;
       
  1372   const char *interface_c_name;
       
  1373 
       
  1374   iface_prefix = iface_to_c_prefix (interface_info_get_name (interface));
       
  1375   interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL);
       
  1376   if (interface_c_name == NULL)
       
  1377     {
       
  1378       interface_c_name = (const char *) iface_prefix;
       
  1379     }
       
  1380 
       
  1381   method_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL));
       
  1382   if (method_name == NULL)
       
  1383     {
       
  1384       method_name = compute_client_method_name (interface_c_name, method);
       
  1385     }
       
  1386   g_free(iface_prefix);
       
  1387 
       
  1388   /* Write the typedef for the client callback */
       
  1389   if (!write_printf_to_iochannel ("typedef void (*%s_reply) (DBusGProxy *proxy, ", channel, error, method_name))
       
  1390     goto io_lose;
       
  1391   {
       
  1392     GSList *args;
       
  1393     for (args = method_info_get_args (method); args; args = args->next)
       
  1394       {
       
  1395 	ArgInfo *arg;
       
  1396 	const char *type_suffix, *type_str;
       
  1397 	GType gtype;
       
  1398 	
       
  1399 	arg = args->data;
       
  1400 	
       
  1401 	if (arg_info_get_direction (arg) != ARG_OUT)
       
  1402 	  continue;
       
  1403 	gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
       
  1404 	if (gtype != G_TYPE_VALUE && (g_type_is_a (gtype, G_TYPE_BOXED)
       
  1405 	     || g_type_is_a (gtype, G_TYPE_OBJECT)
       
  1406 	     || g_type_is_a (gtype, G_TYPE_POINTER)))
       
  1407 	  type_suffix = "*";
       
  1408 	else
       
  1409 	  type_suffix = "";
       
  1410 	type_str = dbus_g_type_get_c_name (_dbus_gtype_from_signature (arg_info_get_type (arg), TRUE));
       
  1411 	if (!write_printf_to_iochannel ("%s %sOUT_%s, ", channel, error, type_str, type_suffix, arg_info_get_name (arg)))
       
  1412 	  goto io_lose;
       
  1413       }
       
  1414   }
       
  1415   WRITE_OR_LOSE ("GError *error, gpointer userdata);\n\n");
       
  1416   
       
  1417   
       
  1418   /* Write the callback when the call returns */
       
  1419   WRITE_OR_LOSE ("static void\n");
       
  1420   if (!write_printf_to_iochannel ("%s_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)\n", channel, error, method_name))
       
  1421     goto io_lose;
       
  1422   WRITE_OR_LOSE ("{\n");
       
  1423   WRITE_OR_LOSE ("  DBusGAsyncData *data = (DBusGAsyncData*) user_data;\n  GError *error = NULL;\n");
       
  1424   if (!write_formal_declarations_for_direction (interface, method, channel, ARG_OUT, error))
       
  1425     goto io_lose;
       
  1426   /* TODO: handle return boolean of end_call */
       
  1427   WRITE_OR_LOSE ("  dbus_g_proxy_end_call (proxy, call, &error, ");
       
  1428   if (!write_typed_args_for_direction (interface, method, channel, ARG_OUT, error))
       
  1429     goto io_lose;
       
  1430   WRITE_OR_LOSE("G_TYPE_INVALID);\n");
       
  1431   if (!write_printf_to_iochannel ("  (*(%s_reply)data->cb) (proxy, ", channel, error, method_name))
       
  1432     goto io_lose;
       
  1433   if (!write_untyped_out_args (interface, method, channel, error))
       
  1434     goto io_lose;
       
  1435   WRITE_OR_LOSE ("error, data->userdata);\n");
       
  1436   WRITE_OR_LOSE ("  return;\n}\n\n");
       
  1437   
       
  1438 
       
  1439   /* Write the main wrapper function */
       
  1440   WRITE_OR_LOSE ("static\n#ifdef G_HAVE_INLINE\ninline\n#endif\nDBusGProxyCall*\n");
       
  1441   if (!write_printf_to_iochannel ("%s_async (DBusGProxy *proxy", channel, error,
       
  1442                                   method_name))
       
  1443     goto io_lose;
       
  1444   if (!write_formal_parameters_for_direction (interface, method, ARG_IN, channel, error))
       
  1445     goto io_lose;
       
  1446   
       
  1447   if (!write_printf_to_iochannel (", %s_reply callback, gpointer userdata)\n\n", channel, error, method_name))
       
  1448     goto io_lose;
       
  1449   
       
  1450   WRITE_OR_LOSE ("{\n");
       
  1451   WRITE_OR_LOSE ("  DBusGAsyncData *stuff;\n  stuff = g_new (DBusGAsyncData, 1);\n  stuff->cb = G_CALLBACK (callback);\n  stuff->userdata = userdata;\n");
       
  1452   if (!write_printf_to_iochannel ("  return dbus_g_proxy_begin_call (proxy, \"%s\", %s_async_callback, stuff, g_free, ", channel, error, method_info_get_name (method), method_name))
       
  1453     goto io_lose;
       
  1454   if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
       
  1455     goto io_lose;
       
  1456   WRITE_OR_LOSE ("G_TYPE_INVALID);\n}\n");
       
  1457 
       
  1458   g_free (method_name);
       
  1459   return TRUE;
       
  1460  io_lose:
       
  1461   g_free (method_name);
       
  1462   return FALSE;
       
  1463  }
       
  1464 
       
  1465 static gboolean
       
  1466 generate_client_glue_list (GSList *list, DBusBindingToolCData *data, GError **error)
       
  1467 {
       
  1468   GSList *tmp;
       
  1469 
       
  1470   tmp = list;
       
  1471   while (tmp != NULL)
       
  1472     {
       
  1473       if (!generate_client_glue (tmp->data, data, error))
       
  1474 	return FALSE;
       
  1475       tmp = tmp->next;
       
  1476     }
       
  1477   return TRUE;
       
  1478 }
       
  1479 
       
  1480 static gboolean
       
  1481 generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
       
  1482 {
       
  1483   if (base_info_get_type (base) == INFO_TYPE_NODE)
       
  1484     {
       
  1485       if (!generate_client_glue_list (node_info_get_nodes ((NodeInfo *) base),
       
  1486 				      data, error))
       
  1487 	return FALSE;
       
  1488       if (!generate_client_glue_list (node_info_get_interfaces ((NodeInfo *) base),
       
  1489 				      data, error))
       
  1490 	return FALSE;
       
  1491     }
       
  1492   else
       
  1493     {
       
  1494       GIOChannel *channel;
       
  1495       InterfaceInfo *interface;
       
  1496       GSList *methods;
       
  1497       GSList *tmp;
       
  1498       char *iface_prefix;
       
  1499       const char *interface_c_name;
       
  1500 
       
  1501       channel = data->channel;
       
  1502 
       
  1503       interface = (InterfaceInfo *) base;
       
  1504 
       
  1505       methods = interface_info_get_methods (interface);
       
  1506 
       
  1507       iface_prefix = iface_to_c_prefix (interface_info_get_name (interface));
       
  1508       interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL);
       
  1509       if (interface_c_name == NULL)
       
  1510       {
       
  1511           interface_c_name = (const char *) iface_prefix;
       
  1512       }
       
  1513 
       
  1514       if (!write_printf_to_iochannel ("#ifndef DBUS_GLIB_CLIENT_WRAPPERS_%s\n"
       
  1515 				      "#define DBUS_GLIB_CLIENT_WRAPPERS_%s\n\n",
       
  1516 				      channel, error,
       
  1517 				      iface_prefix, iface_prefix))
       
  1518 	{
       
  1519 	  g_free (iface_prefix);
       
  1520 	  goto io_lose;
       
  1521 	}
       
  1522 
       
  1523       for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
       
  1524         {
       
  1525 	  MethodInfo *method;
       
  1526 	  char *method_c_name;
       
  1527 	  gboolean is_noreply;
       
  1528 
       
  1529           method = (MethodInfo *) tmp->data;
       
  1530 	  method_c_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_CLIENT_C_SYMBOL));
       
  1531           if (method_c_name == NULL)
       
  1532 	    {
       
  1533               method_c_name = compute_client_method_name (interface_c_name, method);
       
  1534             }
       
  1535 
       
  1536 	  is_noreply = method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_NOREPLY) != NULL;
       
  1537 
       
  1538 	  if (data->ignore_unsupported && !check_supported_parameters (method))
       
  1539 	    {
       
  1540 	      g_warning ("Ignoring unsupported signature in method \"%s\" of interface \"%s\"\n",
       
  1541 			 method_info_get_name (method),
       
  1542 			 interface_info_get_name (interface));
       
  1543 	      continue;
       
  1544 	    }
       
  1545 
       
  1546 
       
  1547 	  WRITE_OR_LOSE ("static\n#ifdef G_HAVE_INLINE\ninline\n#endif\ngboolean\n");
       
  1548 	  if (!write_printf_to_iochannel ("%s (DBusGProxy *proxy", channel, error,
       
  1549 					  method_c_name))
       
  1550 	    goto io_lose;
       
  1551 	  g_free (method_c_name);
       
  1552 
       
  1553 	  if (!write_formal_parameters (interface, method, channel, error))
       
  1554 	    goto io_lose;
       
  1555 
       
  1556 	  WRITE_OR_LOSE (", GError **error)\n\n");
       
  1557 	  
       
  1558 	  WRITE_OR_LOSE ("{\n");
       
  1559 
       
  1560 	  if (is_noreply) {
       
  1561 	    if (!write_printf_to_iochannel ("  dbus_g_proxy_call_no_reply (proxy, \"%s\", ", channel, error,
       
  1562 					    method_info_get_name (method)))
       
  1563 	      goto io_lose;
       
  1564 	    
       
  1565 	    if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
       
  1566 	      goto io_lose;
       
  1567 	    
       
  1568 	    WRITE_OR_LOSE ("G_TYPE_INVALID, ");
       
  1569 	    
       
  1570 	    if (!write_args_for_direction (interface, method, channel, ARG_OUT, error))
       
  1571 	      goto io_lose;
       
  1572 	    
       
  1573 	    WRITE_OR_LOSE ("G_TYPE_INVALID);\n");
       
  1574 	    
       
  1575 	    WRITE_OR_LOSE ("  return TRUE;\n}\n\n");
       
  1576 	  } else {
       
  1577 	    if (!write_printf_to_iochannel ("  return dbus_g_proxy_call (proxy, \"%s\", ", channel, error,
       
  1578 					    method_info_get_name (method)))
       
  1579 	      goto io_lose;
       
  1580 	    
       
  1581 	    WRITE_OR_LOSE ("error, ");
       
  1582 	    
       
  1583 	    if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
       
  1584 	      goto io_lose;
       
  1585 	    
       
  1586 	    WRITE_OR_LOSE ("G_TYPE_INVALID, ");
       
  1587 	    
       
  1588 	    if (!write_args_for_direction (interface, method, channel, ARG_OUT, error))
       
  1589 	      goto io_lose;
       
  1590 	    
       
  1591 	    WRITE_OR_LOSE ("G_TYPE_INVALID);\n}\n\n");
       
  1592 	  }
       
  1593 
       
  1594 	  write_async_method_client (channel, interface, method, error);
       
  1595 	}
       
  1596 
       
  1597       if (!write_printf_to_iochannel ("#endif /* defined DBUS_GLIB_CLIENT_WRAPPERS_%s */\n\n", channel, error, iface_prefix))
       
  1598 	{
       
  1599 	  g_free (iface_prefix);
       
  1600 	  goto io_lose;
       
  1601 	}
       
  1602 
       
  1603       g_free (iface_prefix);
       
  1604     }
       
  1605   return TRUE;
       
  1606  io_lose:
       
  1607   return FALSE;
       
  1608 }
       
  1609 
       
  1610 
       
  1611 gboolean
       
  1612 dbus_binding_tool_output_glib_client (BaseInfo *info, GIOChannel *channel, gboolean ignore_unsupported, GError **error)
       
  1613 {
       
  1614   DBusBindingToolCData data;
       
  1615   gboolean ret;
       
  1616 
       
  1617   memset (&data, 0, sizeof (data));
       
  1618   
       
  1619   data.channel = channel;
       
  1620   data.ignore_unsupported = ignore_unsupported;
       
  1621 
       
  1622   dbus_g_type_specialized_init ();
       
  1623   _dbus_g_type_specialized_builtins_init ();
       
  1624 
       
  1625   WRITE_OR_LOSE ("/* Generated by dbus-binding-tool; do not edit! */\n\n");
       
  1626   WRITE_OR_LOSE ("#include <glib/gtypes.h>\n");
       
  1627   WRITE_OR_LOSE ("#include <glib/gerror.h>\n");
       
  1628   WRITE_OR_LOSE ("#include <dbus/dbus-glib.h>\n\n");
       
  1629   WRITE_OR_LOSE ("G_BEGIN_DECLS\n\n");
       
  1630 
       
  1631   ret = generate_client_glue (info, &data, error);
       
  1632   if (!ret)
       
  1633     goto io_lose;
       
  1634   
       
  1635   WRITE_OR_LOSE ("G_END_DECLS\n");
       
  1636 
       
  1637   return ret;
       
  1638  io_lose:
       
  1639   return FALSE;
       
  1640 }