Main Page | Modules | Data Structures | Directories | File List | Data Fields | Related Pages

dbus-binding-tool-glib.c

00001 /* -*- mode: C; c-file-style: "gnu" -*- */
00002 /* dbus-binding-tool-glib.c: Output C glue
00003  *
00004  * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
00005  * Copyright (C) 2005 Nokia
00006  *
00007  * Licensed under the Academic Free License version 2.1
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022  *
00023  */
00024 
00025 #include <config.h>
00026 #include "dbus/dbus-glib.h"
00027 #include "dbus-gidl.h"
00028 #include "dbus-gparser.h"
00029 #include "dbus-gutils.h"
00030 #include "dbus-gtype-specialized.h"
00031 #include "dbus-gsignature.h"
00032 #include "dbus-gvalue-utils.h"
00033 #include "dbus-glib-tool.h"
00034 #include "dbus-binding-tool-glib.h"
00035 #include <glib/gi18n.h>
00036 #include <stdio.h>
00037 #include <stdlib.h>
00038 #include <string.h>
00039 #include <unistd.h>
00040 
00041 #define MARSHAL_PREFIX "dbus_glib_marshal_"
00042 
00043 typedef struct
00044 {
00045   gboolean ignore_unsupported;
00046   const char* prefix;
00047   GIOChannel *channel;
00048   
00049   GError **error;
00050   
00051   GHashTable *generated;
00052   GString *blob;
00053   GString *signal_blob;
00054   GString *property_blob;
00055   guint count;
00056 } DBusBindingToolCData;
00057 
00058 static gboolean gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error);
00059 static gboolean generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error);
00060 static gboolean generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error);
00061 
00062 static const char *
00063 dbus_g_type_get_marshal_name (GType gtype)
00064 {
00065   switch (G_TYPE_FUNDAMENTAL (gtype))
00066     {
00067     case G_TYPE_NONE:
00068       return "NONE";
00069     case G_TYPE_BOOLEAN:
00070       return "BOOLEAN";
00071     case G_TYPE_UCHAR:
00072       return "UCHAR";
00073     case G_TYPE_INT:
00074       return "INT";
00075     case G_TYPE_UINT:
00076       return "UINT";
00077     case G_TYPE_INT64:
00078       return "INT64";
00079     case G_TYPE_UINT64:
00080       return "UINT64";
00081     case G_TYPE_DOUBLE:
00082       return "DOUBLE";
00083     case G_TYPE_STRING:
00084       return "STRING";
00085     case G_TYPE_POINTER:
00086       return "POINTER";
00087     case G_TYPE_BOXED:
00088       return "BOXED";
00089     case G_TYPE_OBJECT:
00090       return "OBJECT";
00091     default:
00092       return NULL;
00093     }
00094 }
00095 
00096 /* This entire function is kind of...ugh. */
00097 static const char *
00098 dbus_g_type_get_c_name (GType gtype)
00099 {
00100   if (dbus_g_type_is_collection (gtype))
00101     return "GArray";
00102   if (dbus_g_type_is_map (gtype))
00103     return "GHashTable";
00104   
00105   if (g_type_is_a (gtype, G_TYPE_STRING))
00106     return "char *";
00107 
00108   /* This one is even more hacky...we get an extra *
00109    * because G_TYPE_STRV is a G_TYPE_BOXED
00110    */
00111   if (g_type_is_a (gtype, G_TYPE_STRV))
00112     return "char *";
00113   if (g_type_is_a (gtype, DBUS_TYPE_G_OBJECT_PATH))
00114     return "char";
00115   
00116   return g_type_name (gtype);
00117 }
00118 
00119 static gboolean
00120 compute_gsignature (MethodInfo *method, GType *rettype, GArray **params, GError **error)
00121 {
00122   GSList *elt;
00123   GType retval_type;
00124   GArray *ret;
00125   gboolean is_async;
00126   const char *arg_type;
00127   gboolean retval_signals_error;
00128   
00129   is_async = method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL;
00130   retval_signals_error = FALSE;
00131 
00132   ret = g_array_new (TRUE, TRUE, sizeof (GType));
00133 
00134   if (is_async)
00135     retval_type = G_TYPE_NONE;
00136   else
00137     {
00138       gboolean found_retval;
00139 
00140       /* Look for return value */
00141       found_retval = FALSE;
00142       for (elt = method_info_get_args (method); elt; elt = elt->next)
00143         {
00144           ArgInfo *arg = elt->data;
00145           const char *returnval_annotation;
00146       
00147           returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL);
00148           if (returnval_annotation != NULL)
00149             {
00150               arg_type = arg_info_get_type (arg);
00151               retval_type = _dbus_gtype_from_signature (arg_type, FALSE);
00152               if (retval_type == G_TYPE_INVALID)
00153                 goto invalid_type;
00154               found_retval = TRUE;
00155               if (!strcmp (returnval_annotation, "error"))
00156                 retval_signals_error = TRUE;
00157               break;
00158             }
00159         }
00160       if (!found_retval)
00161         {
00162           retval_type = G_TYPE_BOOLEAN;
00163           retval_signals_error = TRUE;
00164         }
00165     }
00166 
00167   *rettype = retval_type;
00168 
00169   /* Handle all input arguments */
00170   for (elt = method_info_get_args (method); elt; elt = elt->next)
00171     {
00172       ArgInfo *arg = elt->data;
00173       if (arg_info_get_direction (arg) == ARG_IN)
00174         {
00175           GType gtype;
00176           
00177           arg_type = arg_info_get_type (arg);
00178           gtype = _dbus_gtype_from_signature (arg_type, FALSE);
00179           if (gtype == G_TYPE_INVALID)
00180             goto invalid_type;
00181           
00182           g_array_append_val (ret, gtype);
00183         }
00184     }
00185 
00186   if (!is_async)
00187     {
00188       /* Append pointer for each out arg storage */
00189       for (elt = method_info_get_args (method); elt; elt = elt->next)
00190         {
00191           ArgInfo *arg = elt->data;
00192 
00193           /* Skip return value */
00194           if (arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL) != NULL)
00195             continue;
00196       
00197           if (arg_info_get_direction (arg) == ARG_OUT)
00198             {
00199               GType gtype;
00200               arg_type = arg_info_get_type (arg);
00201               gtype = _dbus_gtype_from_signature (arg_type, FALSE);
00202               if (gtype == G_TYPE_INVALID)
00203                 goto invalid_type;
00204               /* We actually just need a pointer for the return value
00205                  storage */
00206               gtype = G_TYPE_POINTER;
00207               g_array_append_val (ret, gtype);
00208             }
00209         }
00210 
00211       if (retval_signals_error)
00212         {
00213           /* Final GError parameter */
00214           GType gtype = G_TYPE_POINTER;
00215           g_array_append_val (ret, gtype);
00216         }
00217     }
00218   else
00219     {
00220       /* Context pointer */
00221       GType gtype = G_TYPE_POINTER;
00222       g_array_append_val (ret, gtype);
00223     }
00224 
00225   *params = ret;
00226   return TRUE;
00227 
00228  invalid_type:
00229   g_set_error (error,
00230                DBUS_BINDING_TOOL_ERROR,
00231                DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
00232                _("Unsupported conversion from D-BUS type %s to glib-genmarshal type"),
00233                arg_type);
00234   return FALSE;
00235 }
00236   
00237 
00238 static char *
00239 compute_marshaller (MethodInfo *method, GError **error)
00240 {
00241   GArray *signature;
00242   GType rettype;
00243   const char *marshal_name;
00244   GString *ret;
00245   guint i;
00246 
00247   if (!compute_gsignature (method, &rettype, &signature, error))
00248     return NULL;
00249 
00250   ret = g_string_new ("");
00251   marshal_name = dbus_g_type_get_marshal_name (rettype);
00252   g_assert (marshal_name != NULL);
00253   g_string_append (ret, marshal_name);
00254   g_string_append_c (ret, ':');
00255   for (i = 0; i < signature->len; i++)
00256     {
00257       marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i));
00258       g_assert (marshal_name != NULL);
00259       g_string_append (ret, marshal_name);
00260       if (i < signature->len - 1)
00261         g_string_append_c (ret, ',');
00262     }
00263   if (signature->len == 0)
00264     {
00265       marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE);
00266       g_assert (marshal_name != NULL);
00267       g_string_append (ret, marshal_name);
00268     }
00269   g_array_free (signature, TRUE);
00270   return g_string_free (ret, FALSE);
00271 }
00272 
00273 static char *
00274 compute_marshaller_name (MethodInfo *method, const char *prefix, GError **error)
00275 {
00276   GString *ret;
00277   GArray *signature;
00278   GType rettype;
00279   const char *marshal_name;
00280   guint i;
00281 
00282   if (!compute_gsignature (method, &rettype, &signature, error))
00283     return NULL;
00284 
00285   ret = g_string_new (MARSHAL_PREFIX);
00286   g_string_append (ret, prefix);
00287   g_string_append_c (ret, '_');
00288 
00289   marshal_name = dbus_g_type_get_marshal_name (rettype);
00290   g_assert (marshal_name != NULL);
00291   g_string_append (ret, marshal_name);
00292   g_string_append (ret, "__");
00293   for (i = 0; i < signature->len; i++)
00294     {
00295       marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i));
00296       g_assert (marshal_name != NULL);
00297       g_string_append (ret, marshal_name);
00298       if (i < signature->len - 1)
00299         g_string_append_c (ret, '_');
00300     }
00301   if (signature->len == 0)
00302     {
00303       marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE);
00304       g_assert (marshal_name != NULL);
00305       g_string_append (ret, marshal_name);
00306     }
00307   g_array_free (signature, TRUE);
00308   return g_string_free (ret, FALSE);
00309 }
00310 
00311 static gboolean
00312 gather_marshallers_list (GSList *list, DBusBindingToolCData *data, GError **error)
00313 {
00314   GSList *tmp;
00315 
00316   tmp = list;
00317   while (tmp != NULL)
00318     {
00319       if (!gather_marshallers (tmp->data, data, error))
00320         return FALSE;
00321       tmp = tmp->next;
00322     }
00323   return TRUE;
00324 }
00325 
00326 static gboolean
00327 gather_marshallers (BaseInfo *base, DBusBindingToolCData *data, GError **error)
00328 {
00329   if (base_info_get_type (base) == INFO_TYPE_NODE)
00330     {
00331       if (!gather_marshallers_list (node_info_get_nodes ((NodeInfo *) base),
00332                                     data, error))
00333         return FALSE;
00334       if (!gather_marshallers_list (node_info_get_interfaces ((NodeInfo *) base),
00335                                     data, error))
00336         return FALSE;
00337     }
00338   else
00339     {
00340       InterfaceInfo *interface;
00341       GSList *methods;
00342       GSList *tmp;
00343       const char *interface_c_name;
00344 
00345       interface = (InterfaceInfo *) base;
00346       interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_C_SYMBOL);
00347       if (interface_c_name == NULL)
00348         {
00349           if (!data->prefix)
00350             return TRUE;
00351         }
00352 
00353       methods = interface_info_get_methods (interface);
00354 
00355       /* Generate the necessary marshallers for the methods. */
00356 
00357       for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
00358         {
00359           MethodInfo *method;
00360           char *marshaller_name;
00361 
00362           method = (MethodInfo *) tmp->data;
00363 
00364           marshaller_name = compute_marshaller (method, error);
00365           if (!marshaller_name)
00366             return FALSE;
00367 
00368           if (g_hash_table_lookup (data->generated, marshaller_name))
00369             {
00370               g_free (marshaller_name);
00371               continue;
00372             }
00373 
00374           g_hash_table_insert (data->generated, marshaller_name, NULL);
00375         }
00376 
00377     }
00378   return TRUE;
00379 }
00380 
00381 static gboolean
00382 generate_glue_list (GSList *list, DBusBindingToolCData *data, GError **error)
00383 {
00384   GSList *tmp;
00385 
00386   tmp = list;
00387   while (tmp != NULL)
00388     {
00389       if (!generate_glue (tmp->data, data, error))
00390         return FALSE;
00391       tmp = tmp->next;
00392     }
00393   return TRUE;
00394 }
00395 
00396 #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)
00397 
00398 static gboolean
00399 write_printf_to_iochannel (const char *fmt, GIOChannel *channel, GError **error, ...)
00400 {
00401   char *str;
00402   va_list args;
00403   GIOStatus status;
00404   gsize written;
00405   gboolean ret;
00406 
00407   va_start (args, error);
00408 
00409   str = g_strdup_vprintf (fmt, args);
00410   if ((status = g_io_channel_write_chars (channel, str, -1, &written, error)) == G_IO_STATUS_NORMAL)
00411     ret = TRUE;
00412   else
00413     ret = FALSE;
00414 
00415   g_free (str);
00416 
00417   va_end (args);
00418 
00419   return ret;
00420 }
00421 
00422 static gboolean
00423 write_quoted_string (GIOChannel *channel, GString *string, GError **error)
00424 {
00425   guint i;
00426 
00427   WRITE_OR_LOSE ("\"");
00428   for (i = 0; i < string->len; i++)
00429     {
00430       if (string->str[i] != '\0')
00431         {
00432           if (!g_io_channel_write_chars (channel, string->str + i, 1, NULL, error))
00433             return FALSE;
00434         }
00435       else
00436         {
00437           if (!g_io_channel_write_chars (channel, "\\0", -1, NULL, error))
00438             return FALSE;
00439         }
00440     }
00441   WRITE_OR_LOSE ("\\0\"");
00442   return TRUE;
00443  io_lose:
00444   return FALSE;
00445 }
00446 
00447 static gboolean
00448 generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
00449 {
00450   if (base_info_get_type (base) == INFO_TYPE_NODE)
00451     {
00452       GString *object_introspection_data_blob;
00453       GIOChannel *channel;
00454 
00455       channel = data->channel;
00456       
00457       object_introspection_data_blob = g_string_new_len ("", 0);
00458       
00459       data->blob = object_introspection_data_blob;
00460       data->count = 0;
00461 
00462       data->signal_blob = g_string_new_len ("", 0);
00463       data->property_blob = g_string_new_len ("", 0);
00464 
00465       if (!write_printf_to_iochannel ("static const DBusGMethodInfo dbus_glib_%s_methods[] = {\n", channel, error, data->prefix))
00466         goto io_lose;
00467 
00468       if (!generate_glue_list (node_info_get_nodes ((NodeInfo *) base),
00469                                data, error))
00470         return FALSE;
00471       if (!generate_glue_list (node_info_get_interfaces ((NodeInfo *) base),
00472                                data, error))
00473         return FALSE;
00474 
00475       WRITE_OR_LOSE ("};\n\n");
00476 
00477       /* Information about the object. */
00478 
00479       if (!write_printf_to_iochannel ("const DBusGObjectInfo dbus_glib_%s_object_info = {\n",
00480                                       channel, error, data->prefix))
00481         goto io_lose;
00482       WRITE_OR_LOSE ("  0,\n");
00483       if (!write_printf_to_iochannel ("  dbus_glib_%s_methods,\n", channel, error, data->prefix))
00484         goto io_lose;
00485       if (!write_printf_to_iochannel ("  %d,\n", channel, error, data->count))
00486         goto io_lose;
00487 
00488       if (!write_quoted_string (channel, object_introspection_data_blob, error))
00489         goto io_lose;
00490       WRITE_OR_LOSE (",\n");
00491       if (!write_quoted_string (channel, data->signal_blob, error))
00492         goto io_lose;
00493       WRITE_OR_LOSE (",\n");
00494       if (!write_quoted_string (channel, data->property_blob, error))
00495         goto io_lose;
00496       WRITE_OR_LOSE ("\n};\n\n");
00497 
00498       g_string_free (object_introspection_data_blob, TRUE);
00499       g_string_free (data->signal_blob, TRUE);
00500       g_string_free (data->property_blob, TRUE);
00501     }
00502   else
00503     {
00504       GIOChannel *channel;
00505       InterfaceInfo *interface;
00506       GSList *methods;
00507       GSList *signals;
00508       GSList *properties;
00509       GSList *tmp;
00510       const char *interface_c_name;
00511       GString *object_introspection_data_blob;
00512 
00513       channel = data->channel;
00514       object_introspection_data_blob = data->blob;
00515 
00516       interface = (InterfaceInfo *) base;
00517       interface_c_name = interface_info_get_annotation (interface, DBUS_GLIB_ANNOTATION_C_SYMBOL);
00518       if (interface_c_name == NULL)
00519         {
00520           if (data->prefix == NULL)
00521             return TRUE;
00522           interface_c_name = data->prefix;
00523         }
00524 
00525       methods = interface_info_get_methods (interface);
00526 
00527       /* Table of marshalled methods. */
00528 
00529       for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
00530         {
00531           MethodInfo *method;
00532           char *marshaller_name;
00533           char *method_c_name;
00534           gboolean async = FALSE;
00535           GSList *args;
00536           gboolean found_retval = FALSE;
00537 
00538           method = (MethodInfo *) tmp->data;
00539           method_c_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_C_SYMBOL));
00540           if (method_c_name == NULL)
00541             {
00542               char *method_name_uscored;
00543               method_name_uscored = _dbus_gutils_wincaps_to_uscore (method_info_get_name (method));
00544               method_c_name = g_strdup_printf ("%s_%s",
00545                                                interface_c_name,
00546                                                method_name_uscored);
00547               g_free (method_name_uscored);
00548             }
00549 
00550           if (!write_printf_to_iochannel ("  { (GCallback) %s, ", channel, error,
00551                                           method_c_name))
00552             goto io_lose;
00553 
00554           marshaller_name = compute_marshaller_name (method, data->prefix, error);
00555           if (!marshaller_name)
00556             goto io_lose;
00557 
00558           if (!write_printf_to_iochannel ("%s, %d },\n", channel, error,
00559                                           marshaller_name,
00560                                           object_introspection_data_blob->len))
00561             {
00562               g_free (marshaller_name);
00563               goto io_lose;
00564             }
00565 
00566           if (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL)
00567             async = TRUE;
00568 
00569           /* Object method data blob format:
00570            * <iface>\0<name>\0(<argname>\0<argdirection>\0<argtype>\0)*\0
00571            */
00572 
00573           g_string_append (object_introspection_data_blob, interface_info_get_name (interface));
00574           g_string_append_c (object_introspection_data_blob, '\0');
00575 
00576           g_string_append (object_introspection_data_blob, method_info_get_name (method));
00577           g_string_append_c (object_introspection_data_blob, '\0');
00578 
00579           g_string_append_c (object_introspection_data_blob, async ? 'A' : 'S');
00580           g_string_append_c (object_introspection_data_blob, '\0');
00581 
00582           for (args = method_info_get_args (method); args; args = args->next)
00583             {
00584               ArgInfo *arg;
00585               char direction;
00586               const char *returnval_annotation;
00587 
00588               arg = args->data;
00589 
00590               g_string_append (object_introspection_data_blob, arg_info_get_name (arg));
00591               g_string_append_c (object_introspection_data_blob, '\0');
00592 
00593               switch (arg_info_get_direction (arg))
00594                 {
00595                 case ARG_IN:
00596                   direction = 'I';
00597                   break;
00598                 case ARG_OUT:
00599                   direction = 'O';
00600                   break;
00601                 case ARG_INVALID:
00602                 default:
00603                   g_assert_not_reached ();
00604                   direction = 0; /* silence gcc */
00605                   break;
00606                 }
00607               g_string_append_c (object_introspection_data_blob, direction);
00608               g_string_append_c (object_introspection_data_blob, '\0');
00609 
00610               if (arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_CONST) != NULL)
00611                 {
00612                   if (arg_info_get_direction (arg) == ARG_IN)
00613                     {
00614                       g_set_error (error,
00615                                    DBUS_BINDING_TOOL_ERROR,
00616                                    DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
00617                                    "Input argument \"%s\" cannot have const annotation in method \"%s\" of interface \"%s\"\n",
00618                                    arg_info_get_name (arg),
00619                                    method_info_get_name (method),
00620                                    interface_info_get_name (interface));
00621                       return FALSE;
00622                     }
00623                   g_string_append_c (object_introspection_data_blob, 'C');
00624                   g_string_append_c (object_introspection_data_blob, '\0');
00625                 }
00626               else if (arg_info_get_direction (arg) == ARG_OUT)
00627                 {
00628                   g_string_append_c (object_introspection_data_blob, 'F');
00629                   g_string_append_c (object_introspection_data_blob, '\0');
00630                 }
00631 
00632               returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL);
00633               if (returnval_annotation != NULL)
00634                 {
00635                   GType gtype;
00636 
00637                   if (found_retval)
00638                     {
00639                       g_set_error (error,
00640                                    DBUS_BINDING_TOOL_ERROR,
00641                                    DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
00642                                    "Multiple arguments with return value annotation in method \"%s\" of interface \"%s\"\n",
00643                                    method_info_get_name (method),
00644                                    interface_info_get_name (interface));
00645                       return FALSE;
00646                     }
00647                   found_retval = TRUE;
00648                   if (arg_info_get_direction (arg) == ARG_IN)
00649                     {
00650                       g_set_error (error,
00651                                    DBUS_BINDING_TOOL_ERROR,
00652                                    DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
00653                                    "Input argument \"%s\" cannot have return value annotation in method \"%s\" of interface \"%s\"\n",
00654                                    arg_info_get_name (arg),
00655                                    method_info_get_name (method),
00656                                    interface_info_get_name (interface));
00657                       return FALSE;
00658                     }
00659                   if (!strcmp ("", returnval_annotation))
00660                     g_string_append_c (object_introspection_data_blob, 'R');
00661                   else if (!strcmp ("error", returnval_annotation))
00662                     {
00663                       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
00664                       if (!_dbus_gtype_can_signal_error (gtype))
00665                         {
00666                           g_set_error (error,
00667                                        DBUS_BINDING_TOOL_ERROR,
00668                                        DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
00669                                        "Output argument \"%s\" cannot signal error with type \"%s\" in method \"%s\" of interface \"%s\"\n",
00670                                        arg_info_get_name (arg),
00671                                        g_type_name (gtype),
00672                                        method_info_get_name (method),
00673                                        interface_info_get_name (interface));
00674                           return FALSE;
00675                         }
00676                       g_string_append_c (object_introspection_data_blob, 'E');
00677                     }
00678                   else
00679                     {
00680                       g_set_error (error,
00681                                    DBUS_BINDING_TOOL_ERROR,
00682                                    DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION,
00683                                    "Invalid ReturnVal annotation for argument \"%s\" in method \"%s\" of interface \"%s\"\n",
00684                                    arg_info_get_name (arg),
00685                                    method_info_get_name (method),
00686                                    interface_info_get_name (interface));
00687                       return FALSE;
00688                     }
00689                       
00690                   g_string_append_c (object_introspection_data_blob, '\0');
00691                 }
00692               else if (arg_info_get_direction (arg) == ARG_OUT)
00693                 {
00694                   g_string_append_c (object_introspection_data_blob, 'N');
00695                   g_string_append_c (object_introspection_data_blob, '\0');
00696                 }
00697 
00698               g_string_append (object_introspection_data_blob, arg_info_get_type (arg));
00699               g_string_append_c (object_introspection_data_blob, '\0');
00700             }
00701 
00702           g_string_append_c (object_introspection_data_blob, '\0');
00703 
00704           data->count++;
00705         }
00706 
00707       signals = interface_info_get_signals (interface);
00708 
00709       for (tmp = signals; tmp != NULL; tmp = g_slist_next (tmp))
00710         {
00711           SignalInfo *sig;
00712           
00713           sig = tmp->data;
00714 
00715           g_string_append (data->signal_blob, interface_info_get_name (interface));
00716           g_string_append_c (data->signal_blob, '\0');
00717           g_string_append (data->signal_blob, signal_info_get_name (sig));
00718           g_string_append_c (data->signal_blob, '\0');
00719         }
00720 
00721       properties = interface_info_get_properties (interface);
00722 
00723       for (tmp = properties; tmp != NULL; tmp = g_slist_next (tmp))
00724         {
00725           PropertyInfo *prop;
00726           
00727           prop = tmp->data;
00728 
00729           g_string_append (data->property_blob, interface_info_get_name (interface));
00730           g_string_append_c (data->property_blob, '\0');
00731           g_string_append (data->property_blob, property_info_get_name (prop));
00732           g_string_append_c (data->property_blob, '\0');
00733         }
00734     }
00735   return TRUE;
00736  io_lose:
00737   return FALSE;
00738 }
00739 
00740 static void
00741 write_marshaller (gpointer key, gpointer value, gpointer user_data)
00742 {
00743   DBusBindingToolCData *data;
00744   const char *marshaller;
00745   gsize bytes_written;
00746 
00747   data = user_data;
00748   marshaller = key;
00749 
00750   if (data->error && *data->error)
00751     return;
00752 
00753   if (g_io_channel_write_chars (data->channel, marshaller, -1, &bytes_written, data->error) == G_IO_STATUS_NORMAL)
00754     g_io_channel_write_chars (data->channel, "\n", -1, &bytes_written, data->error);
00755 }
00756 
00757 gboolean
00758 dbus_binding_tool_output_glib_server (BaseInfo *info, GIOChannel *channel, const char *prefix, GError **error)
00759 {
00760   gboolean ret;
00761   GPtrArray *argv;
00762   gint child_stdout;
00763   GIOChannel *genmarshal_stdout;
00764   GPid child_pid;
00765   DBusBindingToolCData data;
00766   char *tempfile_name;
00767   gint tempfile_fd;
00768   GIOStatus iostatus;
00769   char buf[4096];
00770   gsize bytes_read, bytes_written;
00771 
00772   memset (&data, 0, sizeof (data));
00773 
00774   dbus_g_type_specialized_init ();
00775   _dbus_g_type_specialized_builtins_init ();
00776 
00777   data.prefix = prefix;
00778   data.generated = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
00779   data.error = error;
00780   genmarshal_stdout = NULL;
00781   tempfile_name = NULL;
00782 
00783   if (!gather_marshallers (info, &data, error))
00784     goto io_lose;
00785 
00786   tempfile_fd = g_file_open_tmp ("dbus-binding-tool-c-marshallers.XXXXXX",
00787                                  &tempfile_name, error);
00788   if (tempfile_fd < 0)
00789     goto io_lose;
00790 
00791   data.channel = g_io_channel_unix_new (tempfile_fd);
00792   if (!g_io_channel_set_encoding (data.channel, NULL, error))
00793     goto io_lose;
00794   g_hash_table_foreach (data.generated, write_marshaller, &data); 
00795   if (error && *error != NULL)
00796     {
00797       ret = FALSE;
00798       g_io_channel_close (data.channel);
00799       g_io_channel_unref (data.channel);
00800       goto io_lose;
00801     }
00802 
00803   g_io_channel_close (data.channel);
00804   g_io_channel_unref (data.channel);
00805   
00806   /* Now spawn glib-genmarshal to insert all our required marshallers */
00807   argv = g_ptr_array_new ();
00808   g_ptr_array_add (argv, "glib-genmarshal");
00809   g_ptr_array_add (argv, "--header");
00810   g_ptr_array_add (argv, "--body");
00811   g_ptr_array_add (argv, g_strdup_printf ("--prefix=%s%s", MARSHAL_PREFIX, prefix));
00812   g_ptr_array_add (argv, tempfile_name);
00813   g_ptr_array_add (argv, NULL);
00814   if (!g_spawn_async_with_pipes (NULL, (char**)argv->pdata, NULL,
00815                                  G_SPAWN_SEARCH_PATH,
00816                                  NULL, NULL,
00817                                  &child_pid,
00818                                  NULL,
00819                                  &child_stdout, NULL, error))
00820     {
00821       g_ptr_array_free (argv, TRUE);
00822       goto io_lose;
00823     }
00824   g_ptr_array_free (argv, TRUE);
00825 
00826   genmarshal_stdout = g_io_channel_unix_new (child_stdout);
00827   if (!g_io_channel_set_encoding (genmarshal_stdout, NULL, error))
00828     goto io_lose;
00829 
00830   WRITE_OR_LOSE ("/* Generated by dbus-binding-tool; do not edit! */\n\n");
00831 
00832   while ((iostatus = g_io_channel_read_chars (genmarshal_stdout, buf, sizeof (buf),
00833                                               &bytes_read, error)) == G_IO_STATUS_NORMAL)
00834     if (g_io_channel_write_chars (channel, buf, bytes_read, &bytes_written, error) != G_IO_STATUS_NORMAL)
00835       goto io_lose;
00836   if (iostatus != G_IO_STATUS_EOF)
00837     goto io_lose;
00838 
00839   g_io_channel_close (genmarshal_stdout);
00840 
00841   WRITE_OR_LOSE ("#include <dbus/dbus-glib.h>\n");
00842 
00843   data.channel = channel;
00844   g_io_channel_ref (data.channel);
00845   if (!generate_glue (info, &data, error))
00846     goto io_lose;
00847   
00848   ret = TRUE;
00849  cleanup:
00850   if (tempfile_name)
00851     unlink (tempfile_name);
00852   g_free (tempfile_name);
00853   if (genmarshal_stdout)
00854     g_io_channel_unref (genmarshal_stdout);
00855   if (data.channel)
00856     g_io_channel_unref (data.channel);
00857   g_hash_table_destroy (data.generated);
00858 
00859   return ret;
00860  io_lose:
00861   ret = FALSE;
00862   goto cleanup;
00863 }
00864 
00865 static char *
00866 iface_to_c_prefix (const char *iface)
00867 {
00868   char **components;
00869   char **component;
00870   GString *ret;
00871   gboolean first;
00872   
00873   components = g_strsplit (iface, ".", 0);
00874 
00875   first = TRUE;
00876   ret = g_string_new ("");
00877   for (component = components; *component; component++)
00878     {
00879       if (!first)
00880         g_string_append_c (ret, '_');
00881       else
00882         first = FALSE;
00883       g_string_append (ret, *component);
00884     }
00885   g_strfreev (components);
00886   return g_string_free (ret, FALSE);
00887 }
00888 
00889 static char *
00890 compute_client_method_name (const char *iface_prefix, MethodInfo *method)
00891 {
00892   GString *ret;
00893   char *method_name_uscored;
00894 
00895   ret = g_string_new (iface_prefix);
00896   
00897   method_name_uscored = _dbus_gutils_wincaps_to_uscore (method_info_get_name (method));
00898   g_string_append_c (ret, '_');
00899   g_string_append (ret, method_name_uscored);
00900   g_free (method_name_uscored);
00901   return g_string_free (ret, FALSE);
00902 }
00903 
00904 static gboolean
00905 write_formal_parameters (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, GError **error)
00906 {
00907   GSList *args;
00908 
00909   for (args = method_info_get_args (method); args; args = args->next)
00910     {
00911       ArgInfo *arg;
00912       const char *type_str;
00913       const char *type_suffix;
00914       GType gtype;
00915       int direction;
00916 
00917       arg = args->data;
00918 
00919       WRITE_OR_LOSE (", ");
00920 
00921       direction = arg_info_get_direction (arg);
00922 
00923       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
00924       if (gtype == G_TYPE_INVALID)
00925         {
00926           g_set_error (error,
00927                        DBUS_BINDING_TOOL_ERROR,
00928                        DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
00929                        _("Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\""),
00930                        arg_info_get_type (arg),
00931                        method_info_get_name (method),
00932                        interface_info_get_name (iface));
00933           return FALSE;
00934         }
00935       type_str = dbus_g_type_get_c_name (gtype);
00936       g_assert (type_str);
00937       /* Variants are special...*/
00938       if (gtype == G_TYPE_VALUE)
00939         {
00940           if (direction == ARG_IN)
00941             type_suffix = "*";
00942           else
00943             type_suffix = "";
00944         }
00945       else if ((g_type_is_a (gtype, G_TYPE_BOXED)
00946               || g_type_is_a (gtype, G_TYPE_OBJECT)
00947            || g_type_is_a (gtype, G_TYPE_POINTER)))
00948         type_suffix = "*";
00949       else
00950         type_suffix = "";
00951 
00952 
00953       switch (direction)
00954         {
00955         case ARG_IN:
00956           if (!write_printf_to_iochannel ("const %s%s IN_%s", channel, error,
00957                                           type_str,
00958                                           type_suffix,
00959                                           arg_info_get_name (arg)))
00960             goto io_lose;
00961           break;
00962         case ARG_OUT:
00963           if (!write_printf_to_iochannel ("%s%s* OUT_%s", channel, error,
00964                                           type_str,
00965                                           type_suffix,
00966                                           arg_info_get_name (arg)))
00967             goto io_lose;
00968           break;
00969         case ARG_INVALID:
00970           break;
00971         }
00972     }
00973 
00974   return TRUE;
00975  io_lose:
00976   return FALSE;
00977 }
00978 
00979 #define MAP_FUNDAMENTAL(NAME) \
00980    case G_TYPE_ ## NAME: \
00981      return g_strdup ("G_TYPE_" #NAME);
00982 #define MAP_KNOWN(NAME) \
00983     if (gtype == NAME) \
00984       return g_strdup (#NAME)
00985 static char *
00986 dbus_g_type_get_lookup_function (GType gtype)
00987 {
00988   char *type_lookup;
00989   switch (gtype)
00990     {
00991       MAP_FUNDAMENTAL(CHAR);
00992       MAP_FUNDAMENTAL(UCHAR);
00993       MAP_FUNDAMENTAL(BOOLEAN);
00994       MAP_FUNDAMENTAL(LONG);
00995       MAP_FUNDAMENTAL(ULONG);
00996       MAP_FUNDAMENTAL(INT);
00997       MAP_FUNDAMENTAL(UINT);
00998       MAP_FUNDAMENTAL(INT64);
00999       MAP_FUNDAMENTAL(UINT64);
01000       MAP_FUNDAMENTAL(FLOAT);
01001       MAP_FUNDAMENTAL(DOUBLE);
01002       MAP_FUNDAMENTAL(STRING);
01003     }
01004   if (dbus_g_type_is_collection (gtype))
01005     {
01006       GType elt_gtype;
01007       char *sublookup;
01008       
01009       elt_gtype = dbus_g_type_get_collection_specialization (gtype);
01010       sublookup = dbus_g_type_get_lookup_function (elt_gtype);
01011       g_assert (sublookup);
01012       type_lookup = g_strdup_printf ("dbus_g_type_get_collection (\"GArray\", %s)",
01013                                      sublookup);
01014       g_free (sublookup);
01015       return type_lookup;
01016     }
01017   else if (dbus_g_type_is_map (gtype))
01018     {
01019       GType key_gtype;
01020       char *key_lookup;
01021       GType value_gtype;
01022       char *value_lookup;
01023       
01024       key_gtype = dbus_g_type_get_map_key_specialization (gtype);
01025       value_gtype = dbus_g_type_get_map_value_specialization (gtype);
01026       key_lookup = dbus_g_type_get_lookup_function (key_gtype);
01027       g_assert (key_lookup);
01028       value_lookup = dbus_g_type_get_lookup_function (value_gtype);
01029       g_assert (value_lookup);
01030       type_lookup = g_strdup_printf ("dbus_g_type_get_map (\"GHashTable\", %s, %s)",
01031                                      key_lookup, value_lookup);
01032       g_free (key_lookup);
01033       g_free (value_lookup);
01034       return type_lookup;
01035     }
01036   MAP_KNOWN(G_TYPE_VALUE);
01037   MAP_KNOWN(G_TYPE_STRV);
01038   MAP_KNOWN(G_TYPE_VALUE_ARRAY);
01039   MAP_KNOWN(DBUS_TYPE_G_PROXY);
01040   MAP_KNOWN(DBUS_TYPE_G_OBJECT_PATH);
01041   return NULL;
01042 }
01043 #undef MAP_FUNDAMENTAL
01044 #undef MAP_KNOWN
01045 
01046 static gboolean
01047 write_args_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, int direction, GError **error)
01048 {
01049   GSList *args;
01050 
01051   for (args = method_info_get_args (method); args; args = args->next)
01052     {
01053       ArgInfo *arg;
01054       GType gtype;
01055       char *type_lookup;
01056 
01057       arg = args->data;
01058 
01059       if (direction != arg_info_get_direction (arg))
01060         continue;
01061 
01062       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
01063       g_assert (gtype != G_TYPE_INVALID);
01064       type_lookup = dbus_g_type_get_lookup_function (gtype);
01065       g_assert (type_lookup != NULL);
01066 
01067       switch (direction)
01068         {
01069 
01070         case ARG_IN:
01071           if (!write_printf_to_iochannel ("%s, IN_%s, ", channel, error,
01072                                           type_lookup,
01073                                           arg_info_get_name (arg)))
01074             goto io_lose;
01075           break;
01076         case ARG_OUT:
01077           if (!write_printf_to_iochannel ("%s, OUT_%s, ", channel, error,
01078                                           type_lookup,
01079                                           arg_info_get_name (arg)))
01080             goto io_lose;
01081           break;
01082         case ARG_INVALID:
01083           break;
01084         }
01085       g_free (type_lookup);
01086     }
01087 
01088   return TRUE;
01089  io_lose:
01090   return FALSE;
01091 }
01092 
01093 static gboolean
01094 check_supported_parameters (MethodInfo *method)
01095 {
01096   GSList *args;
01097 
01098   for (args = method_info_get_args (method); args; args = args->next)
01099     {
01100       ArgInfo *arg;
01101       GType gtype;
01102 
01103       arg = args->data;
01104       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
01105       if (gtype == G_TYPE_INVALID)
01106         return FALSE;
01107     }
01108   return TRUE;
01109 }
01110 
01111 static gboolean
01112 write_untyped_out_args (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, GError **error)
01113 {
01114   GSList *args;
01115 
01116   for (args = method_info_get_args (method); args; args = args->next)
01117     {
01118       ArgInfo *arg;
01119 
01120       arg = args->data;
01121       if (arg_info_get_direction (arg) != ARG_OUT)
01122         continue;
01123             
01124       if (!write_printf_to_iochannel ("OUT_%s, ", channel, error,
01125                                       arg_info_get_name (arg)))
01126         goto io_lose;
01127      }
01128 
01129    return TRUE;
01130  io_lose:
01131   return FALSE;
01132 }
01133 
01134 static gboolean
01135 write_formal_declarations_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, const int direction, GError **error)
01136  {
01137    GSList *args;
01138  
01139    for (args = method_info_get_args (method); args; args = args->next)
01140      {
01141        ArgInfo *arg;
01142       GType gtype;
01143       const char *type_str, *type_suffix;
01144       int dir;
01145 
01146        arg = args->data;
01147 
01148       dir = arg_info_get_direction (arg);
01149 
01150       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
01151       type_str = dbus_g_type_get_c_name (gtype);
01152 
01153       if (!type_str)
01154        {
01155          g_set_error (error,
01156                       DBUS_BINDING_TOOL_ERROR,
01157                       DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
01158                       _("Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\""),
01159                       arg_info_get_type (arg),
01160                       method_info_get_name (method),
01161                       interface_info_get_name (iface));
01162          return FALSE;
01163        }
01164 
01165       /* Variants are special...*/
01166       if (gtype == G_TYPE_VALUE)
01167         {
01168           if (direction == ARG_IN)
01169             type_suffix = "*";
01170           else
01171             type_suffix = "";
01172         }
01173       else if ((g_type_is_a (gtype, G_TYPE_BOXED)
01174               || g_type_is_a (gtype, G_TYPE_OBJECT)
01175            || g_type_is_a (gtype, G_TYPE_POINTER)))
01176         type_suffix = "*";
01177       else
01178         type_suffix = "";
01179 
01180       if (direction != dir)
01181         continue;
01182 
01183           switch (dir)
01184        {
01185        case ARG_IN:
01186          if (!write_printf_to_iochannel ("  %s%s IN_%s;\n", channel, error,
01187                                          type_str, type_suffix,
01188                                          arg_info_get_name (arg)))
01189            goto io_lose;
01190          break;
01191        case ARG_OUT:
01192          if (!write_printf_to_iochannel ("  %s%s OUT_%s;\n", channel, error,
01193                                          type_str, type_suffix,
01194                                          arg_info_get_name (arg)))
01195            goto io_lose;
01196          break;
01197        case ARG_INVALID:
01198          break;
01199        }
01200      }
01201    return TRUE;
01202  io_lose:
01203   return FALSE;
01204  }
01205 
01206 static gboolean
01207 write_formal_parameters_for_direction (InterfaceInfo *iface, MethodInfo *method, int dir, GIOChannel *channel, GError **error)
01208 {
01209   GSList *args;
01210 
01211   for (args = method_info_get_args (method); args; args = args->next)
01212     {
01213       ArgInfo *arg;
01214       const char *type_str;
01215       const char *type_suffix;
01216       GType gtype;
01217       int direction;
01218 
01219       arg = args->data;
01220 
01221       direction = arg_info_get_direction (arg);
01222       if (dir != direction) continue;
01223       
01224       WRITE_OR_LOSE (", ");
01225 
01226       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
01227       type_str = dbus_g_type_get_c_name (gtype);
01228       /* Variants are special...*/
01229       if (gtype == G_TYPE_VALUE)
01230         {
01231           if (direction == ARG_IN)
01232             type_suffix = "*";
01233           else
01234             type_suffix = "";
01235         }
01236       else if ((g_type_is_a (gtype, G_TYPE_BOXED)
01237               || g_type_is_a (gtype, G_TYPE_OBJECT)
01238            || g_type_is_a (gtype, G_TYPE_POINTER)))
01239         type_suffix = "*";
01240       else
01241         type_suffix = "";
01242 
01243       if (!type_str)
01244         {
01245           g_set_error (error,
01246                        DBUS_BINDING_TOOL_ERROR,
01247                        DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION,
01248                        _("Unsupported conversion from D-BUS type signature \"%s\" to glib C type in method \"%s\" of interface \"%s\""),
01249                        arg_info_get_type (arg),
01250                        method_info_get_name (method),
01251                        interface_info_get_name (iface));
01252           return FALSE;
01253         }
01254  
01255        switch (direction)
01256         {
01257         case ARG_IN:
01258           if (!write_printf_to_iochannel ("const %s%s IN_%s", channel, error,
01259                                           type_str,
01260                                           type_suffix,
01261                                           arg_info_get_name (arg)))
01262             goto io_lose;
01263           break;
01264         case ARG_OUT:
01265           if (!write_printf_to_iochannel ("%s%s* OUT_%s", channel, error,
01266                                           type_str,
01267                                           type_suffix,
01268                                           arg_info_get_name (arg)))
01269             goto io_lose;
01270           break;
01271         case ARG_INVALID:
01272           break;
01273         }
01274     }
01275   return TRUE;
01276  io_lose:
01277   return FALSE;
01278 }
01279 
01280 static gboolean
01281 write_typed_args_for_direction (InterfaceInfo *iface, MethodInfo *method, GIOChannel *channel, const int direction, GError **error)
01282  {
01283   GSList *args;
01284   
01285   for (args = method_info_get_args (method); args; args = args->next)
01286     {
01287       ArgInfo *arg;
01288       int dir;
01289       GType gtype;
01290       const char *type_lookup;
01291       
01292       arg = args->data;
01293 
01294       dir = arg_info_get_direction (arg);
01295 
01296       if (dir != direction)
01297         continue;
01298 
01299       gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
01300       type_lookup = dbus_g_type_get_lookup_function (gtype);
01301 
01302       if (!write_printf_to_iochannel ("%s, &%s_%s, ", channel, error, type_lookup, direction == ARG_IN ? "IN" : "OUT", arg_info_get_name (arg)))
01303           goto io_lose;
01304     }
01305   return TRUE;
01306  io_lose:
01307   return FALSE;
01308 }
01309 
01310 static gboolean
01311 write_async_method_client (GIOChannel *channel, InterfaceInfo *interface, MethodInfo *method, GError **error)
01312 {
01313   char *method_name, *iface_prefix;
01314   iface_prefix = iface_to_c_prefix (interface_info_get_name (interface));
01315   method_name = compute_client_method_name (iface_prefix, method);
01316   
01317   /* Write the typedef for the client callback */
01318   if (!write_printf_to_iochannel ("typedef void (*%s_reply) (DBusGProxy *proxy, ", channel, error, method_name))
01319     goto io_lose;
01320   {
01321     GSList *args;
01322     for (args = method_info_get_args (method); args; args = args->next)
01323       {
01324         ArgInfo *arg;
01325         const char *type_suffix, *type_str;
01326         GType gtype;
01327         
01328         arg = args->data;
01329         
01330         if (arg_info_get_direction (arg) != ARG_OUT)
01331           continue;
01332         gtype = _dbus_gtype_from_signature (arg_info_get_type (arg), TRUE);
01333         if (gtype != G_TYPE_VALUE && (g_type_is_a (gtype, G_TYPE_BOXED)
01334              || g_type_is_a (gtype, G_TYPE_OBJECT)
01335              || g_type_is_a (gtype, G_TYPE_POINTER)))
01336           type_suffix = "*";
01337         else
01338           type_suffix = "";
01339         type_str = dbus_g_type_get_c_name (_dbus_gtype_from_signature (arg_info_get_type (arg), TRUE));
01340         if (!write_printf_to_iochannel ("%s %sOUT_%s, ", channel, error, type_str, type_suffix, arg_info_get_name (arg)))
01341           goto io_lose;
01342       }
01343   }
01344   WRITE_OR_LOSE ("GError *error, gpointer userdata);\n\n");
01345   
01346   
01347   /* Write the callback when the call returns */
01348   WRITE_OR_LOSE ("static void\n");
01349   if (!write_printf_to_iochannel ("%s_async_callback (DBusGProxy *proxy, DBusGProxyCall *call, void *user_data)\n", channel, error, method_name))
01350     goto io_lose;
01351   WRITE_OR_LOSE ("{\n");
01352   WRITE_OR_LOSE ("  DBusGAsyncData *data = user_data;\n  GError *error = NULL;\n");
01353   if (!write_formal_declarations_for_direction (interface, method, channel, ARG_OUT, error))
01354     goto io_lose;
01355   /* TODO: handle return boolean of end_call */
01356   WRITE_OR_LOSE ("  dbus_g_proxy_end_call (proxy, call, &error, ");
01357   if (!write_typed_args_for_direction (interface, method, channel, ARG_OUT, error))
01358     goto io_lose;
01359   WRITE_OR_LOSE("G_TYPE_INVALID);\n");
01360   if (!write_printf_to_iochannel ("  (*(%s_reply)data->cb) (proxy, ", channel, error, method_name))
01361     goto io_lose;
01362   if (!write_untyped_out_args (interface, method, channel, error))
01363     goto io_lose;
01364   WRITE_OR_LOSE ("error, data->userdata);\n");
01365   WRITE_OR_LOSE ("  return;\n}\n\n");
01366   
01367 
01368   /* Write the main wrapper function */
01369   WRITE_OR_LOSE ("static\n#ifdef G_HAVE_INLINE\ninline\n#endif\nDBusGProxyCall*\n");
01370   if (!write_printf_to_iochannel ("%s_async (DBusGProxy *proxy", channel, error,
01371                                   method_name))
01372     goto io_lose;
01373   if (!write_formal_parameters_for_direction (interface, method, ARG_IN, channel, error))
01374     goto io_lose;
01375   
01376   if (!write_printf_to_iochannel (", %s_reply callback, gpointer userdata)\n\n", channel, error, method_name))
01377     goto io_lose;
01378   
01379   WRITE_OR_LOSE ("{\n");
01380   WRITE_OR_LOSE ("  DBusGAsyncData *stuff;\n  stuff = g_new (DBusGAsyncData, 1);\n  stuff->cb = G_CALLBACK (callback);\n  stuff->userdata = userdata;\n");
01381   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))
01382     goto io_lose;
01383   if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
01384     goto io_lose;
01385   WRITE_OR_LOSE ("G_TYPE_INVALID);\n}\n");
01386 
01387   g_free (method_name);
01388   return TRUE;
01389  io_lose:
01390   return FALSE;
01391  }
01392 
01393 static gboolean
01394 generate_client_glue_list (GSList *list, DBusBindingToolCData *data, GError **error)
01395 {
01396   GSList *tmp;
01397 
01398   tmp = list;
01399   while (tmp != NULL)
01400     {
01401       if (!generate_client_glue (tmp->data, data, error))
01402         return FALSE;
01403       tmp = tmp->next;
01404     }
01405   return TRUE;
01406 }
01407 
01408 static gboolean
01409 generate_client_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error)
01410 {
01411   if (base_info_get_type (base) == INFO_TYPE_NODE)
01412     {
01413       if (!generate_client_glue_list (node_info_get_nodes ((NodeInfo *) base),
01414                                       data, error))
01415         return FALSE;
01416       if (!generate_client_glue_list (node_info_get_interfaces ((NodeInfo *) base),
01417                                       data, error))
01418         return FALSE;
01419     }
01420   else
01421     {
01422       GIOChannel *channel;
01423       InterfaceInfo *interface;
01424       GSList *methods;
01425       GSList *tmp;
01426       int count;
01427       char *iface_prefix;
01428 
01429       channel = data->channel;
01430 
01431       interface = (InterfaceInfo *) base;
01432 
01433       methods = interface_info_get_methods (interface);
01434       count = 0;
01435 
01436       iface_prefix = iface_to_c_prefix (interface_info_get_name (interface));
01437 
01438       if (!write_printf_to_iochannel ("#ifndef DBUS_GLIB_CLIENT_WRAPPERS_%s\n"
01439                                       "#define DBUS_GLIB_CLIENT_WRAPPERS_%s\n\n",
01440                                       channel, error,
01441                                       iface_prefix, iface_prefix))
01442         {
01443           g_free (iface_prefix);
01444           goto io_lose;
01445         }
01446 
01447       for (tmp = methods; tmp != NULL; tmp = g_slist_next (tmp))
01448         {
01449           MethodInfo *method;
01450           char *method_name;
01451 
01452           method = (MethodInfo *) tmp->data;
01453 
01454           if (data->ignore_unsupported && !check_supported_parameters (method))
01455             {
01456               g_warning ("Ignoring unsupported signature in method \"%s\" of interface \"%s\"\n",
01457                          method_info_get_name (method),
01458                          interface_info_get_name (interface));
01459               continue;
01460             }
01461 
01462           method_name = compute_client_method_name (iface_prefix, method);
01463 
01464           WRITE_OR_LOSE ("static\n#ifdef G_HAVE_INLINE\ninline\n#endif\ngboolean\n");
01465           if (!write_printf_to_iochannel ("%s (DBusGProxy *proxy", channel, error,
01466                                           method_name))
01467             goto io_lose;
01468           g_free (method_name);
01469 
01470           if (!write_formal_parameters (interface, method, channel, error))
01471             goto io_lose;
01472 
01473           WRITE_OR_LOSE (", GError **error)\n\n");
01474           
01475           WRITE_OR_LOSE ("{\n");
01476           
01477           if (!write_printf_to_iochannel ("  return dbus_g_proxy_call (proxy, \"%s\", ", channel, error,
01478                                           method_info_get_name (method)))
01479             goto io_lose;
01480 
01481           WRITE_OR_LOSE ("error, ");
01482 
01483           if (!write_args_for_direction (interface, method, channel, ARG_IN, error))
01484             goto io_lose;
01485 
01486           WRITE_OR_LOSE ("G_TYPE_INVALID, ");
01487 
01488           if (!write_args_for_direction (interface, method, channel, ARG_OUT, error))
01489             goto io_lose;
01490 
01491           WRITE_OR_LOSE ("G_TYPE_INVALID);\n}\n\n");
01492 
01493           write_async_method_client (channel, interface, method, error);
01494         }
01495 
01496       if (!write_printf_to_iochannel ("#endif /* defined DBUS_GLIB_CLIENT_WRAPPERS_%s */\n\n", channel, error, iface_prefix))
01497         {
01498           g_free (iface_prefix);
01499           goto io_lose;
01500         }
01501     }
01502   return TRUE;
01503  io_lose:
01504   return FALSE;
01505 }
01506 
01507 
01508 gboolean
01509 dbus_binding_tool_output_glib_client (BaseInfo *info, GIOChannel *channel, gboolean ignore_unsupported, GError **error)
01510 {
01511   DBusBindingToolCData data;
01512   gboolean ret;
01513 
01514   memset (&data, 0, sizeof (data));
01515   
01516   data.channel = channel;
01517   data.ignore_unsupported = ignore_unsupported;
01518 
01519   dbus_g_type_specialized_init ();
01520   _dbus_g_type_specialized_builtins_init ();
01521 
01522   WRITE_OR_LOSE ("/* Generated by dbus-binding-tool; do not edit! */\n\n");
01523   WRITE_OR_LOSE ("#include <glib/gtypes.h>\n");
01524   WRITE_OR_LOSE ("#include <glib/gerror.h>\n");
01525   WRITE_OR_LOSE ("#include <dbus/dbus-glib.h>\n\n");
01526   WRITE_OR_LOSE ("G_BEGIN_DECLS\n\n");
01527 
01528   ret = generate_client_glue (info, &data, error);
01529   if (!ret)
01530     goto io_lose;
01531   
01532   WRITE_OR_LOSE ("G_END_DECLS\n");
01533 
01534   return ret;
01535  io_lose:
01536   return FALSE;
01537 }

Generated on Tue Aug 30 16:35:49 2005 for D-BUS by  doxygen 1.4.3