summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorAlberto Mardegan <alberto.mardegan@nokia.com>2008-12-01 15:55:39 +0200
committerAlberto Mardegan <alberto.mardegan@nokia.com>2008-12-01 15:56:17 +0200
commit3826f394b9faf2e69b4021eec4cd99f37bbd621e (patch)
tree1f83e0a4d079bea1611008285544518e03a35667 /tools
parent8eea48836d009aeecf53d3e7b57e1ec09518024a (diff)
Update generator tool
Diffstat (limited to 'tools')
-rw-r--r--tools/glib-client-gen.py357
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 = {}