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