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