diff options
Diffstat (limited to 'glib/dbus-binding-tool-glib.c')
-rw-r--r-- | glib/dbus-binding-tool-glib.c | 324 |
1 files changed, 222 insertions, 102 deletions
diff --git a/glib/dbus-binding-tool-glib.c b/glib/dbus-binding-tool-glib.c index f161c638..43b23c6d 100644 --- a/glib/dbus-binding-tool-glib.c +++ b/glib/dbus-binding-tool-glib.c @@ -62,6 +62,8 @@ dbus_g_type_get_marshal_name (GType gtype) { switch (G_TYPE_FUNDAMENTAL (gtype)) { + case G_TYPE_NONE: + return "NONE"; case G_TYPE_BOOLEAN: return "BOOLEAN"; case G_TYPE_UCHAR: @@ -112,148 +114,195 @@ dbus_g_type_get_c_name (GType gtype) return g_type_name (gtype); } -static char * -compute_marshaller (MethodInfo *method, GError **error) +static gboolean +compute_gsignature (MethodInfo *method, GType *rettype, GArray **params, GError **error) { GSList *elt; - GString *ret; - gboolean first; + GType retval_type; + GArray *ret; + gboolean is_async; + const char *arg_type; + gboolean retval_signals_error; + + is_async = method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL; + retval_signals_error = FALSE; - /* All methods required to return boolean for now; - * will be conditional on method info later */ - ret = g_string_new ("BOOLEAN:"); + ret = g_array_new (TRUE, TRUE, sizeof (GType)); - first = TRUE; - /* Append input arguments */ - for (elt = method_info_get_args (method); elt; elt = elt->next) + if (is_async) + retval_type = G_TYPE_NONE; + else { - ArgInfo *arg = elt->data; + gboolean found_retval; - if (arg_info_get_direction (arg) == ARG_IN) + /* Look for return value */ + found_retval = FALSE; + for (elt = method_info_get_args (method); elt; elt = elt->next) { - const char *marshal_name; - GType gtype; - - gtype = dbus_gtype_from_signature (arg_info_get_type (arg), FALSE); - if (gtype == G_TYPE_INVALID) + ArgInfo *arg = elt->data; + const char *returnval_annotation; + + returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL); + if (returnval_annotation != NULL) { - g_set_error (error, - DBUS_BINDING_TOOL_ERROR, - DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION, - _("Unsupported conversion from D-BUS type %s to glib-genmarshal type"), - arg_info_get_type (arg)); - g_string_free (ret, TRUE); - return NULL; + arg_type = arg_info_get_type (arg); + retval_type = dbus_gtype_from_signature (arg_type, FALSE); + if (retval_type == G_TYPE_INVALID) + goto invalid_type; + found_retval = TRUE; + if (!strcmp (returnval_annotation, "error")) + retval_signals_error = TRUE; + break; } - - marshal_name = dbus_g_type_get_marshal_name (gtype); - g_assert (marshal_name); - - if (!first) - g_string_append (ret, ","); - else - first = FALSE; - g_string_append (ret, marshal_name); + } + if (!found_retval) + { + retval_type = G_TYPE_BOOLEAN; + retval_signals_error = TRUE; } } - if (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL) + *rettype = retval_type; + + /* Handle all input arguments */ + for (elt = method_info_get_args (method); elt; elt = elt->next) { - if (!first) - g_string_append (ret, ","); - g_string_append (ret, "POINTER"); - first = FALSE; + ArgInfo *arg = elt->data; + if (arg_info_get_direction (arg) == ARG_IN) + { + GType gtype; + + arg_type = arg_info_get_type (arg); + gtype = dbus_gtype_from_signature (arg_type, FALSE); + if (gtype == G_TYPE_INVALID) + goto invalid_type; + + g_array_append_val (ret, gtype); + } } - else + + if (!is_async) { /* Append pointer for each out arg storage */ for (elt = method_info_get_args (method); elt; elt = elt->next) { ArgInfo *arg = elt->data; + /* Skip return value */ + if (arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL) != NULL) + continue; + if (arg_info_get_direction (arg) == ARG_OUT) { - if (!first) - g_string_append (ret, ","); - else - first = FALSE; - g_string_append (ret, "POINTER"); + GType gtype; + arg_type = arg_info_get_type (arg); + gtype = dbus_gtype_from_signature (arg_type, FALSE); + if (gtype == G_TYPE_INVALID) + goto invalid_type; + /* We actually just need a pointer for the return value + storage */ + gtype = G_TYPE_POINTER; + g_array_append_val (ret, gtype); } } - /* Final GError parameter */ - if (!first) - g_string_append (ret, ","); - g_string_append (ret, "POINTER"); + if (retval_signals_error) + { + /* Final GError parameter */ + GType gtype = G_TYPE_POINTER; + g_array_append_val (ret, gtype); + } + } + else + { + /* Context pointer */ + GType gtype = G_TYPE_POINTER; + g_array_append_val (ret, gtype); } - return g_string_free (ret, FALSE); + *params = ret; + return TRUE; + invalid_type: + g_set_error (error, + DBUS_BINDING_TOOL_ERROR, + DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION, + _("Unsupported conversion from D-BUS type %s to glib-genmarshal type"), + arg_type); + return FALSE; } + static char * -compute_marshaller_name (MethodInfo *method, const char *prefix, GError **error) +compute_marshaller (MethodInfo *method, GError **error) { - GSList *elt; + GArray *signature; + GType rettype; + const char *marshal_name; GString *ret; + guint i; - /* All methods required to return boolean for now; - * will be conditional on method info later */ - ret = g_string_new (MARSHAL_PREFIX); - g_string_append (ret, prefix); - g_string_append (ret, "_BOOLEAN_"); + if (!compute_gsignature (method, &rettype, &signature, error)) + return NULL; - /* Append input arguments */ - for (elt = method_info_get_args (method); elt; elt = elt->next) + ret = g_string_new (""); + marshal_name = dbus_g_type_get_marshal_name (rettype); + g_assert (marshal_name != NULL); + g_string_append (ret, marshal_name); + g_string_append_c (ret, ':'); + for (i = 0; i < signature->len; i++) { - ArgInfo *arg = elt->data; + marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i)); + g_assert (marshal_name != NULL); + g_string_append (ret, marshal_name); + if (i < signature->len - 1) + g_string_append_c (ret, ','); + } + if (signature->len == 0) + { + marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE); + g_assert (marshal_name != NULL); + g_string_append (ret, marshal_name); + } + g_array_free (signature, TRUE); + return g_string_free (ret, FALSE); +} - if (arg_info_get_direction (arg) == ARG_IN) - { - const char *marshal_name; - const char *type; - GType gtype; +static char * +compute_marshaller_name (MethodInfo *method, const char *prefix, GError **error) +{ + GString *ret; + GArray *signature; + GType rettype; + const char *marshal_name; + guint i; - type = arg_info_get_type (arg); - gtype = dbus_gtype_from_signature (type, FALSE); - if (gtype == G_TYPE_INVALID) - { - g_set_error (error, - DBUS_BINDING_TOOL_ERROR, - DBUS_BINDING_TOOL_ERROR_UNSUPPORTED_CONVERSION, - _("Unsupported conversion from D-BUS type %s to glib type"), - type); - g_string_free (ret, TRUE); - return NULL; - } - marshal_name = dbus_g_type_get_marshal_name (gtype); - g_assert (marshal_name != NULL); + if (!compute_gsignature (method, &rettype, &signature, error)) + return NULL; - g_string_append (ret, "_"); - g_string_append (ret, marshal_name); - } - } + ret = g_string_new (MARSHAL_PREFIX); + g_string_append (ret, prefix); + g_string_append_c (ret, '_'); - if (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_ASYNC) != NULL) + marshal_name = dbus_g_type_get_marshal_name (rettype); + g_assert (marshal_name != NULL); + g_string_append (ret, marshal_name); + g_string_append (ret, "__"); + for (i = 0; i < signature->len; i++) { - g_string_append (ret, "_POINTER"); + marshal_name = dbus_g_type_get_marshal_name (g_array_index (signature, GType, i)); + g_assert (marshal_name != NULL); + g_string_append (ret, marshal_name); + if (i < signature->len - 1) + g_string_append_c (ret, '_'); } - else + if (signature->len == 0) { - /* Append pointer for each out arg storage */ - for (elt = method_info_get_args (method); elt; elt = elt->next) - { - ArgInfo *arg = elt->data; - - if (arg_info_get_direction (arg) == ARG_OUT) - { - g_string_append (ret, "_POINTER"); - } - } - /* Final GError parameter */ - g_string_append (ret, "_POINTER"); + marshal_name = dbus_g_type_get_marshal_name (G_TYPE_NONE); + g_assert (marshal_name != NULL); + g_string_append (ret, marshal_name); } - + g_array_free (signature, TRUE); return g_string_free (ret, FALSE); } @@ -482,6 +531,7 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error) char *method_c_name; gboolean async = FALSE; GSList *args; + gboolean found_retval = FALSE; method = (MethodInfo *) tmp->data; method_c_name = g_strdup (method_info_get_annotation (method, DBUS_GLIB_ANNOTATION_C_SYMBOL)); @@ -531,6 +581,7 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error) { ArgInfo *arg; char direction; + const char *returnval_annotation; arg = args->data; @@ -561,17 +612,86 @@ generate_glue (BaseInfo *base, DBusBindingToolCData *data, GError **error) g_set_error (error, DBUS_BINDING_TOOL_ERROR, DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION, - "Input argument \"%s\" has const annotation in method \"%s\" of interface \"%s\"\n", + "Input argument \"%s\" cannot have const annotation in method \"%s\" of interface \"%s\"\n", arg_info_get_name (arg), method_info_get_name (method), interface_info_get_name (interface)); return FALSE; } g_string_append_c (object_introspection_data_blob, 'C'); + g_string_append_c (object_introspection_data_blob, '\0'); + } + else if (arg_info_get_direction (arg) == ARG_OUT) + { + g_string_append_c (object_introspection_data_blob, 'F'); + g_string_append_c (object_introspection_data_blob, '\0'); + } + + returnval_annotation = arg_info_get_annotation (arg, DBUS_GLIB_ANNOTATION_RETURNVAL); + if (returnval_annotation != NULL) + { + GType gtype; + + if (found_retval) + { + g_set_error (error, + DBUS_BINDING_TOOL_ERROR, + DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION, + "Multiple arguments with return value annotation in method \"%s\" of interface \"%s\"\n", + method_info_get_name (method), + interface_info_get_name (interface)); + return FALSE; + } + found_retval = TRUE; + if (arg_info_get_direction (arg) == ARG_IN) + { + g_set_error (error, + DBUS_BINDING_TOOL_ERROR, + DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION, + "Input argument \"%s\" cannot have return value annotation in method \"%s\" of interface \"%s\"\n", + arg_info_get_name (arg), + method_info_get_name (method), + interface_info_get_name (interface)); + return FALSE; + } + if (!strcmp ("", returnval_annotation)) + g_string_append_c (object_introspection_data_blob, 'R'); + else if (!strcmp ("error", returnval_annotation)) + { + gtype = dbus_gtype_from_signature (arg_info_get_type (arg), TRUE); + if (!_dbus_gtype_can_signal_error (gtype)) + { + g_set_error (error, + DBUS_BINDING_TOOL_ERROR, + DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION, + "Output argument \"%s\" cannot signal error with type \"%s\" in method \"%s\" of interface \"%s\"\n", + arg_info_get_name (arg), + g_type_name (gtype), + method_info_get_name (method), + interface_info_get_name (interface)); + return FALSE; + } + g_string_append_c (object_introspection_data_blob, 'E'); + } + else + { + g_set_error (error, + DBUS_BINDING_TOOL_ERROR, + DBUS_BINDING_TOOL_ERROR_INVALID_ANNOTATION, + "Invalid ReturnVal annotation for argument \"%s\" in method \"%s\" of interface \"%s\"\n", + arg_info_get_name (arg), + method_info_get_name (method), + interface_info_get_name (interface)); + return FALSE; + } + + g_string_append_c (object_introspection_data_blob, '\0'); + } + else if (arg_info_get_direction (arg) == ARG_OUT) + { + g_string_append_c (object_introspection_data_blob, 'N'); + g_string_append_c (object_introspection_data_blob, '\0'); } - else - g_string_append_c (object_introspection_data_blob, 'F'); - g_string_append_c (object_introspection_data_blob, '\0'); g_string_append (object_introspection_data_blob, arg_info_get_type (arg)); g_string_append_c (object_introspection_data_blob, '\0'); |