diff options
author | Alberto Mardegan <alberto.mardegan@nokia.com> | 2008-12-01 15:55:39 +0200 |
---|---|---|
committer | Alberto Mardegan <alberto.mardegan@nokia.com> | 2008-12-01 15:56:17 +0200 |
commit | 3826f394b9faf2e69b4021eec4cd99f37bbd621e (patch) | |
tree | 1f83e0a4d079bea1611008285544518e03a35667 /tools | |
parent | 8eea48836d009aeecf53d3e7b57e1ec09518024a (diff) |
Update generator tool
Diffstat (limited to 'tools')
-rw-r--r-- | tools/glib-client-gen.py | 357 |
1 files changed, 355 insertions, 2 deletions
diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py index 34a18c0e..b4e9de32 100644 --- a/tools/glib-client-gen.py +++ b/tools/glib-client-gen.py @@ -55,6 +55,8 @@ class Generator(object): % opts.get('--subclass', 'TpProxy')) if self.proxy_arg == 'void *': self.proxy_arg = 'gpointer ' + self.generate_reentrant = '--generate-reentrant' in opts + self.generate_blocking = '--generate-blocking' in opts def h(self, s): if isinstance(s, unicode): @@ -199,7 +201,7 @@ class Generator(object): self.b(' g_value_set_int (args->values + %d, %s);' % (i, name)) elif gtype == 'G_TYPE_UINT64': - self.b(' g_value_set_uint (args->values + %d, %s);' + self.b(' g_value_set_uint64 (args->values + %d, %s);' % (i, name)) elif gtype == 'G_TYPE_DOUBLE': self.b(' g_value_set_double (args->values + %d, %s);' @@ -354,6 +356,348 @@ class Generator(object): self.h('') + def do_method_reentrant(self, method, iface_lc, member, member_lc, + in_args, out_args, collect_callback): + # Reentrant blocking calls + # Example: + # gboolean tp_cli_properties_interface_run_get_properties + # (gpointer proxy, + # gint timeout_ms, + # const GArray *in_properties, + # GPtrArray **out0, + # GError **error, + # GMainLoop **loop); + + self.b('typedef struct {') + self.b(' GMainLoop *loop;') + self.b(' GError **error;') + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' %s*%s;' % (ctype, name)) + + self.b(' unsigned success:1;') + self.b(' unsigned completed:1;') + self.b('} _%s_%s_run_state_%s;' + % (self.prefix_lc, iface_lc, member_lc)) + + reentrant_invoke = '_%s_%s_finish_running_%s' % (self.prefix_lc, + iface_lc, + member_lc) + + self.b('static void') + self.b('%s (TpProxy *self G_GNUC_UNUSED,' % reentrant_invoke) + self.b(' GError *error,') + self.b(' GValueArray *args,') + self.b(' GCallback unused G_GNUC_UNUSED,') + self.b(' gpointer user_data G_GNUC_UNUSED,') + self.b(' GObject *unused2 G_GNUC_UNUSED)') + self.b('{') + self.b(' _%s_%s_run_state_%s *state = user_data;' + % (self.prefix_lc, iface_lc, member_lc)) + self.b('') + self.b(' state->success = (error == NULL);') + self.b(' state->completed = TRUE;') + self.b(' g_main_loop_quit (state->loop);') + self.b('') + self.b(' if (error != NULL)') + self.b(' {') + self.b(' if (state->error != NULL)') + self.b(' *state->error = error;') + self.b(' else') + self.b(' g_error_free (error);') + self.b('') + self.b(' return;') + self.b(' }') + self.b('') + + for i, arg in enumerate(out_args): + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' if (state->%s != NULL)' % name) + if marshaller == 'BOXED': + self.b(' *state->%s = g_value_dup_boxed (' + 'args->values + %d);' % (name, i)) + elif marshaller == 'STRING': + self.b(' *state->%s = g_value_dup_string ' + '(args->values + %d);' % (name, i)) + elif marshaller in ('UCHAR', 'BOOLEAN', 'INT', 'UINT', + 'INT64', 'UINT64', 'DOUBLE'): + self.b(' *state->%s = g_value_get_%s (args->values + %d);' + % (name, marshaller.lower(), i)) + else: + assert False, "Don't know how to copy %s" % gtype + + self.b('') + + if len(out_args) > 0: + self.b(' g_value_array_free (args);') + else: + self.b(' if (args != NULL)') + self.b(' g_value_array_free (args);') + + self.b('}') + self.b('') + + self.h('gboolean %s_%s_run_%s (%sproxy,' + % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.h(' gint timeout_ms,') + + self.b('/**') + self.b(' * %s_%s_run_%s:' % (self.prefix_lc, iface_lc, member_lc)) + self.b(' * @proxy: %s' % self.proxy_doc) + self.b(' * @timeout_ms: Timeout in milliseconds, or -1 for default') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' * @%s: Used to pass an \'in\' argument: %s' + % (name, xml_escape(get_docstring(elt) or '(Undocumented)'))) + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' * @%s: Used to return an \'out\' argument if %%TRUE is ' + 'returned: %s' + % (name, xml_escape(get_docstring(elt) or '(Undocumented)'))) + + self.b(' * @error: If not %NULL, used to return errors if %FALSE ') + self.b(' * is returned') + self.b(' * @loop: If not %NULL, set before re-entering ') + self.b(' * the main loop, to point to a #GMainLoop ') + self.b(' * which can be used to cancel this call with ') + self.b(' * g_main_loop_quit(), causing a return of ') + self.b(' * %FALSE with @error set to %TP_DBUS_ERROR_CANCELLED') + self.b(' *') + self.b(' * Call the method %s and run the main loop' % member) + self.b(' * until it returns. Before calling this method, you must') + self.b(' * add a reference to any borrowed objects you need to keep,') + self.b(' * and generally ensure that everything is in a consistent') + self.b(' * state.') + self.b(' *') + self.b(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)')) + self.b(' *') + self.b(' * Returns: TRUE on success, FALSE and sets @error on error') + self.b(' */') + self.b('gboolean\n%s_%s_run_%s (%sproxy,' + % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.b(' gint timeout_ms,') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.h(' %s%s%s,' % (const, ctype, name)) + self.b(' %s%s%s,' % (const, ctype, name)) + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.h(' %s*%s,' % (ctype, name)) + self.b(' %s*%s,' % (ctype, name)) + + self.h(' GError **error,') + self.h(' GMainLoop **loop);') + self.h('') + + self.b(' GError **error,') + self.b(' GMainLoop **loop)') + self.b('{') + self.b(' DBusGProxy *iface;') + self.b(' GQuark interface = %s;' % self.get_iface_quark()) + self.b(' TpProxyPendingCall *pc;') + self.b(' _%s_%s_run_state_%s state = {' + % (self.prefix_lc, iface_lc, member_lc)) + self.b(' NULL /* loop */, error,') + + for arg in out_args: + name, info, tp_type, elt = arg + + self.b(' %s,' % name) + + self.b(' FALSE /* completed */, FALSE /* success */ };') + self.b('') + self.b(' g_return_val_if_fail (%s (proxy), FALSE);' + % self.proxy_assert) + self.b('') + self.b(' iface = tp_proxy_borrow_interface_by_id') + self.b(' ((TpProxy *) proxy, interface, error);') + self.b('') + self.b(' if (iface == NULL)') + self.b(' return FALSE;') + self.b('') + self.b(' state.loop = g_main_loop_new (NULL, FALSE);') + self.b('') + self.b(' pc = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,') + self.b(' interface, "%s", iface,' % member) + self.b(' %s,' % reentrant_invoke) + self.b(' NULL, &state, NULL, NULL, TRUE);') + self.b('') + self.b(' if (loop != NULL)') + self.b(' *loop = state.loop;') + self.b('') + self.b(' tp_proxy_pending_call_v0_take_pending_call (pc,') + self.b(' dbus_g_proxy_begin_call_with_timeout (iface,') + self.b(' "%s",' % member) + self.b(' %s,' % collect_callback) + self.b(' pc,') + self.b(' tp_proxy_pending_call_v0_completed,') + self.b(' timeout_ms,') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.b(' %s, %s,' % (gtype, name)) + + self.b(' G_TYPE_INVALID));') + self.b('') + self.b(' if (!state.completed)') + self.b(' g_main_loop_run (state.loop);') + self.b('') + self.b(' if (!state.completed)') + self.b(' tp_proxy_pending_call_cancel (pc);') + self.b('') + self.b(' if (loop != NULL)') + self.b(' *loop = NULL;') + self.b('') + self.b(' g_main_loop_unref (state.loop);') + self.b('') + self.b(' return state.success;') + self.b('}') + self.b('') + + def do_method_blocking(self, method, iface_lc, member, member_lc, + in_args, out_args): + # Non reentrant blocking calls + # Example: + # gboolean tp_cli_properties_interface_do_get_properties + # (gpointer proxy, + # gint timeout_ms, + # const GArray *in_properties, + # GPtrArray **out0, + # GError **error); + + self.h('gboolean %s_%s_do_%s (%sproxy,' + % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.h(' gint timeout_ms,') + + self.b('/**') + self.b(' * %s_%s_do_%s:' % (self.prefix_lc, iface_lc, member_lc)) + self.b(' * @proxy: %s' % self.proxy_doc) + self.b(' * @timeout_ms: Timeout in milliseconds, or -1 for default') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' * @%s: Used to pass an \'in\' argument: %s' + % (name, xml_escape(get_docstring(elt) or '(Undocumented)'))) + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' * @%s: Used to return an \'out\' argument if %%TRUE is ' + 'returned: %s' + % (name, xml_escape(get_docstring(elt) or '(Undocumented)'))) + + self.b(' * @error: If not %NULL, used to return errors if %FALSE ') + self.b(' * is returned') + self.b(' *') + self.b(' * Call the method %s and block' % member) + self.b(' * until it returns.') + self.b(' *') + self.b(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)')) + self.b(' *') + self.b(' * Returns: TRUE on success, FALSE and sets @error on error') + self.b(' */') + self.b('gboolean\n%s_%s_do_%s (%sproxy,' + % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.b(' gint timeout_ms,') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.h(' %s%s%s,' % (const, ctype, name)) + self.b(' %s%s%s,' % (const, ctype, name)) + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.h(' %s*%s,' % (ctype, name)) + self.b(' %s*%s,' % (ctype, name)) + + self.h(' GError **error);') + self.h('') + + self.b(' GError **error)') + self.b('{') + self.b(' DBusGProxy *iface;') + self.b(' GQuark interface = %s;' % self.get_iface_quark()) + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' %si_%s;' % (ctype, name)) + self.b('') + self.b(' g_return_val_if_fail (%s (proxy), FALSE);' + % self.proxy_assert) + self.b('') + self.b(' iface = tp_proxy_borrow_interface_by_id') + self.b(' ((TpProxy *) proxy, interface, error);') + self.b('') + self.b(' if (iface == NULL)') + self.b(' return FALSE;') + self.b('') + self.b(' if (dbus_g_proxy_call_with_timeout (iface,') + self.b(' "%s",' % member) + self.b(' timeout_ms,') + self.b(' error,') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.b(' %s, %s,' % (gtype, name)) + + self.b(' G_TYPE_INVALID,') + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' %s, &i_%s,' % (gtype, name)) + self.b(' G_TYPE_INVALID))') + self.b(' {') + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' *%s = i_%s;' % (name, name)) + self.b(' return TRUE;') + self.b(' }') + self.b(' else') + self.b(' return FALSE;') + self.b('}') + self.b('') + def do_method(self, iface, method): iface_lc = iface.lower() @@ -793,6 +1137,14 @@ class Generator(object): self.b('}') self.b('') + if self.generate_reentrant: + self.do_method_reentrant(method, iface_lc, member, member_lc, + in_args, out_args, collect_callback) + + if self.generate_blocking: + self.do_method_blocking(method, iface_lc, member, member_lc, + in_args, out_args) + # leave a gap for the end of the method self.b('') self.h('') @@ -926,7 +1278,8 @@ def types_to_gtypes(types): if __name__ == '__main__': options, argv = gnu_getopt(sys.argv[1:], '', ['group=', 'subclass=', 'subclass-assert=', - 'iface-quark-prefix=', 'tp-proxy-api=']) + 'iface-quark-prefix=', 'tp-proxy-api=', + 'generate-reentrant', 'generate-blocking']) opts = {} |