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

Generated on Tue Sep 13 01:28:06 2005 for D-BUS by  doxygen 1.4.4