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