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