From 66f6cb0f27a74ba0ee859cffe8b1161cac8c4aa1 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Fri, 27 Sep 2013 17:02:24 +0100 Subject: [PATCH 03/22] update tools from telepathy-glib 0.99.2 --- tools/glib-client-gen.py | 598 +++++++++++++++++++++--------------- tools/glib-client-marshaller-gen.py | 20 +- tools/glib-ginterface-gen.py | 53 ++-- tools/glib-gtypes-generator.py | 14 +- tools/libglibcodegen.py | 4 +- tools/libtpcodegen.py | 22 +- tools/make-release-mail.py | 16 +- 7 files changed, 432 insertions(+), 295 deletions(-) diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py index f8465a6..7b3c67d 100644 --- a/tools/glib-client-gen.py +++ b/tools/glib-client-gen.py @@ -27,8 +27,8 @@ import os.path import xml.dom.minidom from getopt import gnu_getopt -from libtpcodegen import file_set_contents -from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \ +from libtpcodegen import file_set_contents, key_by_name, u +from libglibcodegen import Signature, type_to_gtype, \ get_docstring, xml_escape, get_deprecated @@ -41,6 +41,8 @@ class Generator(object): self.__header = [] self.__body = [] self.__docs = [] + self.__reentrant_header = [] + self.__reentrant_body = [] self.prefix_lc = prefix.lower() self.prefix_uc = prefix.upper() @@ -71,21 +73,23 @@ class Generator(object): self.deprecation_attribute = opts.get('--deprecation-attribute', 'G_GNUC_DEPRECATED') + self.split_reentrants = opts.get('--split-reentrants', False) + self.guard = opts.get('--guard', None) def h(self, s): - if isinstance(s, unicode): - s = s.encode('utf-8') self.__header.append(s) def b(self, s): - if isinstance(s, unicode): - s = s.encode('utf-8') self.__body.append(s) + def rh(self, s): + self.__reentrant_header.append(s) + + def rb(self, s): + self.__reentrant_body.append(s) + def d(self, s): - if isinstance(s, unicode): - s = s.encode('utf-8') self.__docs.append(s) def get_iface_quark(self): @@ -192,6 +196,7 @@ class Generator(object): self.b(' TpProxySignalConnection *sc)') self.b('{') + self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS') self.b(' GValueArray *args = g_value_array_new (%d);' % len(args)) self.b(' GValue blank = { 0 };') self.b(' guint i;') @@ -200,6 +205,7 @@ class Generator(object): self.b('') self.b(' for (i = 0; i < %d; i++)' % len(args)) self.b(' g_value_array_append (args, &blank);') + self.b(' G_GNUC_END_IGNORE_DEPRECATIONS') self.b('') for i, arg in enumerate(args): @@ -288,12 +294,14 @@ class Generator(object): self.b(' weak_object);') self.b('') + self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS') if len(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(' G_GNUC_END_IGNORE_DEPRECATIONS') self.b(' g_object_unref (tpproxy);') self.b('}') @@ -313,9 +321,11 @@ class Generator(object): # emitted the 'invalidated' signal, or because the weakly referenced # object has gone away. - self.d('/**') - self.d(' * %s_%s_connect_to_%s:' + connect_to = ('%s_%s_connect_to_%s' % (self.prefix_lc, iface_lc, member_lc)) + + self.d('/**') + self.d(' * %s:' % connect_to) self.d(' * @proxy: %s' % self.proxy_doc) self.d(' * @callback: Callback to be called when the signal is') self.d(' * received') @@ -340,8 +350,8 @@ class Generator(object): self.d(' */') self.d('') - self.h('TpProxySignalConnection *%s_%s_connect_to_%s (%sproxy,' - % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.h('TpProxySignalConnection *%s (%sproxy,' + % (connect_to, self.proxy_arg)) self.h(' %s callback,' % callback_name) self.h(' gpointer user_data,') self.h(' GDestroyNotify destroy,') @@ -350,8 +360,7 @@ class Generator(object): self.h('') self.b('TpProxySignalConnection *') - self.b('%s_%s_connect_to_%s (%sproxy,' - % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.b('(%s) (%sproxy,' % (connect_to, self.proxy_arg)) self.b(' %s callback,' % callback_name) self.b(' gpointer user_data,') self.b(' GDestroyNotify destroy,') @@ -368,8 +377,6 @@ class Generator(object): self.b(' G_TYPE_INVALID };') self.b('') - self.b(' g_return_val_if_fail (%s (proxy), NULL);' - % self.proxy_assert) self.b(' g_return_val_if_fail (callback != NULL, NULL);') self.b('') self.b(' return tp_proxy_signal_connection_v0_new ((TpProxy *) proxy,') @@ -387,6 +394,26 @@ class Generator(object): self.b('}') self.b('') + # Inline the type-check into the header file, so the object code + # doesn't depend on tp_channel_get_type() or whatever + self.h('#ifndef __GTK_DOC_IGNORE__') + self.h('static inline TpProxySignalConnection *') + self.h('_%s (%sproxy,' % (connect_to, self.proxy_arg)) + self.h(' %s callback,' % callback_name) + self.h(' gpointer user_data,') + self.h(' GDestroyNotify destroy,') + self.h(' GObject *weak_object,') + self.h(' GError **error)') + self.h('{') + self.h(' g_return_val_if_fail (%s (proxy), NULL);' + % self.proxy_assert) + self.h(' return %s (proxy, callback, user_data,' % connect_to) + self.h(' destroy, weak_object, error);') + self.h('}') + self.h('#define %s(...) _%s (__VA_ARGS__)' + % (connect_to, connect_to)) + self.h('#endif /* __GTK_DOC_IGNORE__ */') + def do_method(self, iface, method): iface_lc = iface.lower() @@ -500,19 +527,25 @@ class Generator(object): iface_lc, member_lc) + # This is needed by both reentrant and non-reentrant calls + if self.split_reentrants: + collector = lambda x: (self.b(x), self.rb(x)) + else: + collector = self.b + # The callback called by dbus-glib; this ends the call and collects # the results into a GValueArray. - self.b('static void') - self.b('%s (DBusGProxy *proxy,' % collect_callback) - self.b(' DBusGProxyCall *call,') - self.b(' gpointer user_data)') - self.b('{') - self.b(' GError *error = NULL;') + collector('static void') + collector('%s (DBusGProxy *proxy,' % collect_callback) + collector(' DBusGProxyCall *call,') + collector(' gpointer user_data)') + collector('{') + collector(' GError *error = NULL;') if len(out_args) > 0: - self.b(' GValueArray *args;') - self.b(' GValue blank = { 0 };') - self.b(' guint i;') + collector(' GValueArray *args;') + collector(' GValue blank = { 0 };') + collector(' guint i;') for arg in out_args: name, info, tp_type, elt = arg @@ -522,92 +555,97 @@ class Generator(object): # have already allocated storage for them". Thanks, # dbus-glib... if gtype == 'G_TYPE_VALUE': - self.b(' GValue *%s = g_new0 (GValue, 1);' % name) + collector(' GValue *%s = g_new0 (GValue, 1);' % name) else: - self.b(' %s%s;' % (ctype, name)) + collector(' %s%s;' % (ctype, name)) - self.b('') - self.b(' dbus_g_proxy_end_call (proxy, call, &error,') + collector('') + collector(' dbus_g_proxy_end_call (proxy, call, &error,') for arg in out_args: name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info if gtype == 'G_TYPE_VALUE': - self.b(' %s, %s,' % (gtype, name)) + collector(' %s, %s,' % (gtype, name)) else: - self.b(' %s, &%s,' % (gtype, name)) + collector(' %s, &%s,' % (gtype, name)) - self.b(' G_TYPE_INVALID);') + collector(' G_TYPE_INVALID);') if len(out_args) == 0: - self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,' + collector(' tp_proxy_pending_call_v0_take_results (user_data, error,' 'NULL);') else: - self.b('') - self.b(' if (error != NULL)') - self.b(' {') - self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,') - self.b(' NULL);') + collector('') + collector(' if (error != NULL)') + collector(' {') + collector(' tp_proxy_pending_call_v0_take_results (user_data, error,') + collector(' NULL);') for arg in out_args: name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info if gtype == 'G_TYPE_VALUE': - self.b(' g_free (%s);' % name) - - self.b(' return;') - self.b(' }') - self.b('') - self.b(' args = g_value_array_new (%d);' % len(out_args)) - self.b(' g_value_init (&blank, G_TYPE_INT);') - self.b('') - self.b(' for (i = 0; i < %d; i++)' % len(out_args)) - self.b(' g_value_array_append (args, &blank);') + collector(' g_free (%s);' % name) + + collector(' return;') + collector(' }') + collector('') + collector(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS') + collector('') + collector(' args = g_value_array_new (%d);' % len(out_args)) + collector(' g_value_init (&blank, G_TYPE_INT);') + collector('') + collector(' for (i = 0; i < %d; i++)' % len(out_args)) + collector(' g_value_array_append (args, &blank);') + collector('') + collector(' G_GNUC_END_IGNORE_DEPRECATIONS') for i, arg in enumerate(out_args): name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info - self.b('') - self.b(' g_value_unset (args->values + %d);' % i) - self.b(' g_value_init (args->values + %d, %s);' % (i, gtype)) + collector('') + collector(' g_value_unset (args->values + %d);' % i) + collector(' g_value_init (args->values + %d, %s);' + % (i, gtype)) if gtype == 'G_TYPE_STRING': - self.b(' g_value_take_string (args->values + %d, %s);' - % (i, name)) + collector(' g_value_take_string (args->values + %d, %s);' + % (i, name)) elif marshaller == 'BOXED': - self.b(' g_value_take_boxed (args->values + %d, %s);' - % (i, name)) + collector(' g_value_take_boxed (args->values + %d, %s);' + % (i, name)) elif gtype == 'G_TYPE_UCHAR': - self.b(' g_value_set_uchar (args->values + %d, %s);' - % (i, name)) + collector(' g_value_set_uchar (args->values + %d, %s);' + % (i, name)) elif gtype == 'G_TYPE_BOOLEAN': - self.b(' g_value_set_boolean (args->values + %d, %s);' - % (i, name)) + collector(' g_value_set_boolean (args->values + %d, %s);' + % (i, name)) elif gtype == 'G_TYPE_INT': - self.b(' g_value_set_int (args->values + %d, %s);' - % (i, name)) + collector(' g_value_set_int (args->values + %d, %s);' + % (i, name)) elif gtype == 'G_TYPE_UINT': - self.b(' g_value_set_uint (args->values + %d, %s);' - % (i, name)) + collector(' g_value_set_uint (args->values + %d, %s);' + % (i, name)) elif gtype == 'G_TYPE_INT64': - self.b(' g_value_set_int (args->values + %d, %s);' - % (i, name)) + collector(' 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);' - % (i, name)) + collector(' g_value_set_uint (args->values + %d, %s);' + % (i, name)) elif gtype == 'G_TYPE_DOUBLE': - self.b(' g_value_set_double (args->values + %d, %s);' - % (i, name)) + collector(' g_value_set_double (args->values + %d, %s);' + % (i, name)) else: assert False, ("Don't know how to put %s in a GValue" % gtype) - self.b(' tp_proxy_pending_call_v0_take_results (user_data, ' - 'NULL, args);') + collector(' tp_proxy_pending_call_v0_take_results (user_data, ' + 'NULL, args);') - self.b('}') + collector('}') self.b('static void') self.b('%s (TpProxy *self,' % invoke_callback) @@ -671,11 +709,13 @@ class Generator(object): self.b(' error, user_data, weak_object);') self.b('') + self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS') 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(' G_GNUC_END_IGNORE_DEPRECATIONS') self.b('}') self.b('') @@ -692,13 +732,15 @@ class Generator(object): # gpointer user_data, # GDestroyNotify *destructor); - self.h('TpProxyPendingCall *%s_%s_call_%s (%sproxy,' - % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + caller_name = ('%s_%s_call_%s' + % (self.prefix_lc, iface_lc, member_lc)) + + self.h('TpProxyPendingCall *%s (%sproxy,' + % (caller_name, self.proxy_arg)) self.h(' gint timeout_ms,') self.d('/**') - self.d(' * %s_%s_call_%s:' - % (self.prefix_lc, iface_lc, member_lc)) + self.d(' * %s:' % caller_name) self.d(' * @proxy: the #TpProxy') self.d(' * @timeout_ms: the timeout in milliseconds, or -1 to use the') self.d(' * default') @@ -746,8 +788,8 @@ class Generator(object): self.d(' */') self.d('') - self.b('TpProxyPendingCall *\n%s_%s_call_%s (%sproxy,' - % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.b('TpProxyPendingCall *\n(%s) (%sproxy,' + % (caller_name, self.proxy_arg)) self.b(' gint timeout_ms,') for arg in in_args: @@ -774,8 +816,6 @@ class Generator(object): self.b(' GQuark interface = %s;' % self.get_iface_quark()) self.b(' DBusGProxy *iface;') self.b('') - self.b(' g_return_val_if_fail (%s (proxy), NULL);' - % self.proxy_assert) self.b(' g_return_val_if_fail (callback != NULL || ' 'user_data == NULL, NULL);') self.b(' g_return_val_if_fail (callback != NULL || ' @@ -783,37 +823,15 @@ class Generator(object): self.b(' g_return_val_if_fail (callback != NULL || ' 'weak_object == NULL, NULL);') self.b('') - self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS') - self.b(' iface = tp_proxy_borrow_interface_by_id (') + self.b(' iface = tp_proxy_get_interface_by_id (') self.b(' (TpProxy *) proxy,') - self.b(' interface, &error);') - self.b(' G_GNUC_END_IGNORE_DEPRECATIONS') - self.b('') - self.b(' if (iface == NULL)') - self.b(' {') - self.b(' if (callback != NULL)') - self.b(' callback (proxy,') - - for arg in out_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - if pointer: - self.b(' NULL,') - else: - self.b(' 0,') - - self.b(' error, user_data, weak_object);') - self.b('') - self.b(' if (destroy != NULL)') - self.b(' destroy (user_data);') - self.b('') - self.b(' g_error_free (error);') - self.b(' return NULL;') - self.b(' }') + self.b(' interface, (callback == NULL ? NULL : &error));') self.b('') self.b(' if (callback == NULL)') self.b(' {') + self.b(' if (iface == NULL)') + self.b(' return NULL;') + self.b('') self.b(' dbus_g_proxy_call_no_reply (iface, "%s",' % member) for arg in in_args: @@ -836,6 +854,18 @@ class Generator(object): self.b(' %s,' % invoke_callback) self.b(' G_CALLBACK (callback), user_data, destroy,') self.b(' weak_object, FALSE);') + self.b('') + # If iface is NULL then the only valid thing we can do is to + # terminate the call with an error. Go through the machinery + # we'd use for dbus-glib anyway, to stop it being re-entrant. + self.b(' if (iface == NULL)') + self.b(' {') + self.b(' tp_proxy_pending_call_v0_take_results (data,') + self.b(' error, NULL);') + self.b(' tp_proxy_pending_call_v0_completed (data);') + self.b(' return data;') + self.b(' }') + self.b('') self.b(' tp_proxy_pending_call_v0_take_pending_call (data,') self.b(' dbus_g_proxy_begin_call_with_timeout (iface,') self.b(' "%s",' % member) @@ -859,6 +889,38 @@ class Generator(object): self.b('}') self.b('') + # Inline the type-check into the header file, so the object code + # doesn't depend on tp_channel_get_type() or whatever + self.h('#ifndef __GTK_DOC_IGNORE__') + self.h('static inline TpProxyPendingCall *') + self.h('_%s (%sproxy,' % (caller_name, self.proxy_arg)) + self.h(' 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.h(' %s callback,' % callback_name) + self.h(' gpointer user_data,') + self.h(' GDestroyNotify destroy,') + self.h(' GObject *weak_object)') + self.h('{') + self.h(' g_return_val_if_fail (%s (proxy), NULL);' + % self.proxy_assert) + self.h(' return %s (proxy, timeout_ms,' % caller_name) + + for arg in in_args: + name, info, tp_type, elt = arg + self.h(' %s,' % name) + + self.h(' callback, user_data, destroy, weak_object);') + self.h('}') + self.h('#define %s(...) _%s (__VA_ARGS__)' + % (caller_name, caller_name)) + self.h('#endif /* __GTK_DOC_IGNORE__ */') + self.do_method_reentrant(method, iface_lc, member, member_lc, in_args, out_args, collect_callback) @@ -880,94 +942,107 @@ class Generator(object): # GMainLoop **loop); run_method_name = '%s_%s_run_%s' % (self.prefix_lc, iface_lc, member_lc) - if run_method_name not in self.reentrant_symbols: + + b = h = d = None + + if run_method_name in self.reentrant_symbols: + b = self.b + h = self.h + d = self.d + elif self.split_reentrants: + b = self.rb + h = self.rh + d = self.rb + else: return - self.b('typedef struct {') - self.b(' GMainLoop *loop;') - self.b(' GError **error;') + b('typedef struct {') + b(' GMainLoop *loop;') + 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)) + b(' %s*%s;' % (ctype, name)) - self.b(' unsigned success:1;') - self.b(' unsigned completed:1;') - self.b('} _%s_%s_run_state_%s;' + b(' unsigned success:1;') + b(' unsigned completed:1;') + 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;' + b('static void') + b('%s (TpProxy *self G_GNUC_UNUSED,' % reentrant_invoke) + b(' GError *error,') + b(' GValueArray *args,') + b(' GCallback unused G_GNUC_UNUSED,') + b(' gpointer user_data G_GNUC_UNUSED,') + b(' GObject *unused2 G_GNUC_UNUSED)') + b('{') + 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('') + b('') + b(' state->success = (error == NULL);') + b(' state->completed = TRUE;') + b(' g_main_loop_quit (state->loop);') + b('') + b(' if (error != NULL)') + b(' {') + b(' if (state->error != NULL)') + b(' *state->error = error;') + b(' else') + b(' g_error_free (error);') + b('') + b(' return;') + b(' }') + 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) + b(' if (state->%s != NULL)' % name) if marshaller == 'BOXED': - self.b(' *state->%s = g_value_dup_boxed (' + b(' *state->%s = g_value_dup_boxed (' 'args->values + %d);' % (name, i)) elif marshaller == 'STRING': - self.b(' *state->%s = g_value_dup_string ' + 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);' + 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('') + b('') + b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS') if len(out_args) > 0: - self.b(' g_value_array_free (args);') + b(' g_value_array_free (args);') else: - self.b(' if (args != NULL)') - self.b(' g_value_array_free (args);') + b(' if (args != NULL)') + b(' g_value_array_free (args);') + b(' G_GNUC_END_IGNORE_DEPRECATIONS') - self.b('}') - self.b('') + b('}') + b('') if self.deprecate_reentrant: - self.h('#ifndef %s' % self.deprecate_reentrant) + h('#ifndef %s' % self.deprecate_reentrant) - self.h('gboolean %s (%sproxy,' + h('gboolean %s (%sproxy,' % (run_method_name, self.proxy_arg)) - self.h(' gint timeout_ms,') + h(' gint timeout_ms,') - self.d('/**') - self.d(' * %s:' % run_method_name) - self.d(' * @proxy: %s' % self.proxy_doc) - self.d(' * @timeout_ms: Timeout in milliseconds, or -1 for default') + d('/**') + d(' * %s:' % run_method_name) + d(' * @proxy: %s' % self.proxy_doc) + d(' * @timeout_ms: Timeout in milliseconds, or -1 for default') for arg in in_args: name, info, tp_type, elt = arg @@ -978,47 +1053,47 @@ class Generator(object): if ctype == 'guint ' and tp_type != '': docs += ' (#%s)' % ('Tp' + tp_type.replace('_', '')) - self.d(' * @%s: Used to pass an \'in\' argument: %s' + d(' * @%s: Used to pass an \'in\' argument: %s' % (name, docs)) for arg in out_args: name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info - self.d(' * @%s: Used to return an \'out\' argument if %%TRUE is ' + d(' * @%s: Used to return an \'out\' argument if %%TRUE is ' 'returned: %s' % (name, xml_escape(get_docstring(elt) or '(Undocumented)'))) - self.d(' * @error: If not %NULL, used to return errors if %FALSE ') - self.d(' * is returned') - self.d(' * @loop: If not %NULL, set before re-entering ') - self.d(' * the main loop, to point to a #GMainLoop ') - self.d(' * which can be used to cancel this call with ') - self.d(' * g_main_loop_quit(), causing a return of ') - self.d(' * %FALSE with @error set to %TP_DBUS_ERROR_CANCELLED') - self.d(' *') - self.d(' * Call the method %s and run the main loop' % member) - self.d(' * until it returns. Before calling this method, you must') - self.d(' * add a reference to any borrowed objects you need to keep,') - self.d(' * and generally ensure that everything is in a consistent') - self.d(' * state.') - self.d(' *') - self.d(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)')) - self.d(' *') - self.d(' * Returns: TRUE on success, FALSE and sets @error on error') + d(' * @error: If not %NULL, used to return errors if %FALSE ') + d(' * is returned') + d(' * @loop: If not %NULL, set before re-entering ') + d(' * the main loop, to point to a #GMainLoop ') + d(' * which can be used to cancel this call with ') + d(' * g_main_loop_quit(), causing a return of ') + d(' * %FALSE with @error set to %TP_DBUS_ERROR_CANCELLED') + d(' *') + d(' * Call the method %s and run the main loop' % member) + d(' * until it returns. Before calling this method, you must') + d(' * add a reference to any borrowed objects you need to keep,') + d(' * and generally ensure that everything is in a consistent') + d(' * state.') + d(' *') + d(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)')) + d(' *') + d(' * Returns: TRUE on success, FALSE and sets @error on error') deprecated = method.getElementsByTagName('tp:deprecated') if deprecated: d = deprecated[0] - self.d(' *') - self.d(' * Deprecated: %s' % xml_escape(get_deprecated(d))) + d(' *') + d(' * Deprecated: %s' % xml_escape(get_deprecated(d))) - self.d(' */') - self.d('') + d(' */') + d('') - self.b('gboolean\n%s (%sproxy,' + b('gboolean\n%s (%sproxy,' % (run_method_name, self.proxy_arg)) - self.b(' gint timeout_ms,') + b(' gint timeout_ms,') for arg in in_args: name, info, tp_type, elt = arg @@ -1026,71 +1101,69 @@ class Generator(object): const = pointer and 'const ' or '' - self.h(' %s%s%s,' % (const, ctype, name)) - self.b(' %s%s%s,' % (const, ctype, name)) + h(' %s%s%s,' % (const, ctype, name)) + 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)) + h(' %s*%s,' % (ctype, name)) + b(' %s*%s,' % (ctype, name)) - self.h(' GError **error,') + h(' GError **error,') if self.deprecate_reentrant: - self.h(' GMainLoop **loop) %s;' % self.deprecation_attribute) - self.h('#endif /* not %s */' % self.deprecate_reentrant) + h(' GMainLoop **loop) %s;' % self.deprecation_attribute) + h('#endif /* not %s */' % self.deprecate_reentrant) else: - self.h(' GMainLoop **loop);') + h(' GMainLoop **loop);') - self.h('') + 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 = {' + b(' GError **error,') + b(' GMainLoop **loop)') + b('{') + b(' DBusGProxy *iface;') + b(' GQuark interface = %s;' % self.get_iface_quark()) + b(' TpProxyPendingCall *pc;') + b(' _%s_%s_run_state_%s state = {' % (self.prefix_lc, iface_lc, member_lc)) - self.b(' NULL /* loop */, error,') + b(' NULL /* loop */, error,') for arg in out_args: name, info, tp_type, elt = arg - self.b(' %s,' % name) + b(' %s,' % name) - self.b(' FALSE /* completed */, FALSE /* success */ };') - self.b('') - self.b(' g_return_val_if_fail (%s (proxy), FALSE);' + b(' FALSE /* completed */, FALSE /* success */ };') + b('') + b(' g_return_val_if_fail (%s (proxy), FALSE);' % self.proxy_assert) - self.b('') - self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS') - self.b(' iface = tp_proxy_borrow_interface_by_id') - self.b(' ((TpProxy *) proxy, interface, error);') - self.b(' G_GNUC_END_IGNORE_DEPRECATIONS') - 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,') + b('') + b(' iface = tp_proxy_get_interface_by_id') + b(' ((TpProxy *) proxy, interface, error);') + b('') + b(' if (iface == NULL)') + b(' return FALSE;') + b('') + b(' state.loop = g_main_loop_new (NULL, FALSE);') + b('') + b(' pc = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,') + b(' interface, "%s", iface,' % member) + b(' %s,' % reentrant_invoke) + b(' NULL, &state, NULL, NULL, TRUE);') + b('') + b(' if (loop != NULL)') + b(' *loop = state.loop;') + b('') + b(' tp_proxy_pending_call_v0_take_pending_call (pc,') + b(' dbus_g_proxy_begin_call_with_timeout (iface,') + b(' "%s",' % member) + b(' %s,' % collect_callback) + b(' pc,') + b(' tp_proxy_pending_call_v0_completed,') + b(' timeout_ms,') for arg in in_args: name, info, tp_type, elt = arg @@ -1098,24 +1171,24 @@ class Generator(object): 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('') + b(' %s, %s,' % (gtype, name)) + + b(' G_TYPE_INVALID));') + b('') + b(' if (!state.completed)') + b(' g_main_loop_run (state.loop);') + b('') + b(' if (!state.completed)') + b(' tp_proxy_pending_call_cancel (pc);') + b('') + b(' if (loop != NULL)') + b(' *loop = NULL;') + b('') + b(' g_main_loop_unref (state.loop);') + b('') + b(' return state.success;') + b('}') + b('') def do_signal_add(self, signal): marshaller_items = [] @@ -1139,6 +1212,9 @@ class Generator(object): assert len(ifaces) == 1 iface = ifaces[0] name = node.getAttribute('name').replace('/', '') + # This is a hack to get rid of interface version numbers + # until we migrate to generating version-numbered code + name = name.replace('Call1_', 'Call_').rstrip('1') self.iface = name self.iface_lc = name.lower() @@ -1189,14 +1265,24 @@ class Generator(object): self.b(' * confused by seeing function definitions, so mark it as: */') self.b('/**/') self.b('') + # if we're splitting out re-entrant things, we want them marked + # private too + self.rh('/**/') + self.rb('/**/') nodes = self.dom.getElementsByTagName('node') - nodes.sort(cmp_by_name) + nodes.sort(key=key_by_name) for node in nodes: self.do_interface(node) if self.group is not None: + self.h('void %s_%s_add_signals (TpProxy *self,' + % (self.prefix_lc, self.group)) + self.h(' guint quark,') + self.h(' DBusGProxy *proxy,') + self.h(' gpointer unused);') + self.h('') self.b('/*') self.b(' * %s_%s_add_signals:' % (self.prefix_lc, self.group)) @@ -1213,7 +1299,7 @@ class Generator(object): self.b(' * This function should be used as a signal handler for') self.b(' * #TpProxy::interface-added.') self.b(' */') - self.b('static void') + self.b('void') self.b('%s_%s_add_signals (TpProxy *self G_GNUC_UNUSED,' % (self.prefix_lc, self.group)) self.b(' guint quark,') @@ -1229,6 +1315,9 @@ class Generator(object): if not signals: continue name = node.getAttribute('name').replace('/', '').lower() + # This is a hack to get rid of interface version numbers + # until we migrate to generating version-numbered code + name = name.replace('call1_', 'call_').rstrip('1') self.iface_uc = name.upper() self.b(' if (quark == %s)' % self.get_iface_quark()) self.b(' %s_add_signals_for_%s (proxy);' @@ -1244,9 +1333,13 @@ class Generator(object): self.h('#endif /* defined (%s) */' % self.guard) self.h('') - file_set_contents(self.basename + '.h', '\n'.join(self.__header)) - file_set_contents(self.basename + '-body.h', '\n'.join(self.__body)) - file_set_contents(self.basename + '-gtk-doc.h', '\n'.join(self.__docs)) + if self.split_reentrants: + file_set_contents(self.basename + '-reentrant-body.h', u('\n').join(self.__reentrant_body).encode('utf-8')) + file_set_contents(self.basename + '-reentrant.h', u('\n').join(self.__reentrant_header).encode('utf-8')) + + file_set_contents(self.basename + '.h', u('\n').join(self.__header).encode('utf-8')) + file_set_contents(self.basename + '-body.h', u('\n').join(self.__body).encode('utf-8')) + file_set_contents(self.basename + '-gtk-doc.h', u('\n').join(self.__docs).encode('utf-8')) def types_to_gtypes(types): return [type_to_gtype(t)[1] for t in types] @@ -1257,7 +1350,8 @@ if __name__ == '__main__': ['group=', 'subclass=', 'subclass-assert=', 'iface-quark-prefix=', 'tp-proxy-api=', 'generate-reentrant=', 'deprecate-reentrant=', - 'deprecation-attribute=', 'guard=']) + 'deprecation-attribute=', 'guard=', + 'split-reentrants=']) opts = {} diff --git a/tools/glib-client-marshaller-gen.py b/tools/glib-client-marshaller-gen.py index cb27d63..cd9823b 100644 --- a/tools/glib-client-marshaller-gen.py +++ b/tools/glib-client-marshaller-gen.py @@ -31,23 +31,23 @@ class Generator(object): for signal in signals: self.do_signal(signal) - print 'void' - print '%s_register_dbus_glib_marshallers (void)' % self.prefix - print '{' + print('void') + print('%s_register_dbus_glib_marshallers (void)' % self.prefix) + print('{') - all = self.marshallers.keys() + all = list(self.marshallers.keys()) all.sort() for marshaller in all: rhs = self.marshallers[marshaller] - print ' dbus_g_object_register_marshaller (' - print ' g_cclosure_marshal_generic,' - print ' G_TYPE_NONE, /* return */' + print(' dbus_g_object_register_marshaller (') + print(' g_cclosure_marshal_generic,') + print(' G_TYPE_NONE, /* return */') for type in rhs: - print ' G_TYPE_%s,' % type.replace('VOID', 'NONE') - print ' G_TYPE_INVALID);' + print(' G_TYPE_%s,' % type.replace('VOID', 'NONE')) + print(' G_TYPE_INVALID);') - print '}' + print('}') def types_to_gtypes(types): diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py index 6fec0d3..edca4a3 100644 --- a/tools/glib-ginterface-gen.py +++ b/tools/glib-ginterface-gen.py @@ -26,8 +26,8 @@ import sys import os.path import xml.dom.minidom -from libtpcodegen import file_set_contents -from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \ +from libtpcodegen import file_set_contents, key_by_name, u +from libglibcodegen import Signature, type_to_gtype, \ NS_TP, dbus_gutils_wincaps_to_uscore @@ -47,7 +47,7 @@ class Generator(object): def __init__(self, dom, prefix, basename, signal_marshal_prefix, headers, end_headers, not_implemented_func, - allow_havoc): + allow_havoc, allow_single_include): self.dom = dom self.__header = [] self.__body = [] @@ -83,24 +83,22 @@ class Generator(object): self.end_headers = end_headers self.not_implemented_func = not_implemented_func self.allow_havoc = allow_havoc + self.allow_single_include = allow_single_include def h(self, s): - if isinstance(s, unicode): - s = s.encode('utf-8') self.__header.append(s) def b(self, s): - if isinstance(s, unicode): - s = s.encode('utf-8') self.__body.append(s) def d(self, s): - if isinstance(s, unicode): - s = s.encode('utf-8') self.__docs.append(s) def do_node(self, node): node_name = node.getAttribute('name').replace('/', '') + # This is a hack to get rid of interface version numbers + # until we migrate to generating version-numbered code + node_name = node_name.replace('Call1_', 'Call_').rstrip('1') node_name_mixed = self.node_name_mixed = node_name.replace('_', '') node_name_lc = self.node_name_lc = node_name.lower() node_name_uc = self.node_name_uc = node_name.upper() @@ -733,15 +731,11 @@ class Generator(object): def __call__(self): nodes = self.dom.getElementsByTagName('node') - nodes.sort(cmp_by_name) + nodes.sort(key=key_by_name) self.h('#include ') self.h('#include ') - for header in self.headers: - self.h('#include %s' % header) - self.h('') - self.h('') self.h('G_BEGIN_DECLS') self.h('') @@ -749,6 +743,18 @@ class Generator(object): self.b('#include "%s.h"' % self.basename) self.b('') + if self.allow_single_include: + self.b('#include ') + if self.have_properties(nodes): + self.b('#include ') + else: + self.b('#include ') + self.b('') + + for header in self.headers: + self.b('#include %s' % header) + self.b('') + for node in nodes: self.do_node(node) @@ -761,12 +767,12 @@ class Generator(object): self.h('') self.b('') - file_set_contents(self.basename + '.h', '\n'.join(self.__header)) - file_set_contents(self.basename + '.c', '\n'.join(self.__body)) - file_set_contents(self.basename + '-gtk-doc.h', '\n'.join(self.__docs)) + file_set_contents(self.basename + '.h', u('\n').join(self.__header).encode('utf-8')) + file_set_contents(self.basename + '.c', u('\n').join(self.__body).encode('utf-8')) + file_set_contents(self.basename + '-gtk-doc.h', u('\n').join(self.__docs).encode('utf-8')) def cmdline_error(): - print """\ + print("""\ usage: gen-ginterface [OPTIONS] xmlfile Prefix_ options: @@ -786,7 +792,7 @@ options: void symbol (DBusGMethodInvocation *context) and return some sort of "not implemented" error via dbus_g_method_return_error (context, ...) -""" +""") sys.exit(1) @@ -797,7 +803,8 @@ if __name__ == '__main__': ['filename=', 'signal-marshal-prefix=', 'include=', 'include-end=', 'allow-unstable', - 'not-implemented-func=']) + 'not-implemented-func=', + "allow-single-include"]) try: prefix = argv[1] @@ -810,6 +817,7 @@ if __name__ == '__main__': end_headers = [] not_implemented_func = '' allow_havoc = False + allow_single_include = False for option, value in options: if option == '--filename': @@ -828,6 +836,8 @@ if __name__ == '__main__': not_implemented_func = value elif option == '--allow-unstable': allow_havoc = True + elif option == '--allow-single-include': + allow_single_include = True try: dom = xml.dom.minidom.parse(argv[0]) @@ -835,4 +845,5 @@ if __name__ == '__main__': cmdline_error() Generator(dom, prefix, basename, signal_marshal_prefix, headers, - end_headers, not_implemented_func, allow_havoc)() + end_headers, not_implemented_func, allow_havoc, + allow_single_include)() diff --git a/tools/glib-gtypes-generator.py b/tools/glib-gtypes-generator.py index 21dfc6a..1477bd3 100644 --- a/tools/glib-gtypes-generator.py +++ b/tools/glib-gtypes-generator.py @@ -23,7 +23,7 @@ import sys import xml.dom.minidom -from libtpcodegen import file_set_contents +from libtpcodegen import file_set_contents, u from libglibcodegen import escape_as_identifier, \ get_docstring, \ NS_TP, \ @@ -68,13 +68,13 @@ class GTypesGenerator(object): self.need_other_arrays = {} def h(self, code): - self.header.append(code.encode("utf-8")) + self.header.append(code) def c(self, code): - self.body.append(code.encode("utf-8")) + self.body.append(code) def d(self, code): - self.docs.append(code.encode('utf-8')) + self.docs.append(code) def do_mapping_header(self, mapping): members = mapping.getElementsByTagNameNS(NS_TP, 'member') @@ -292,9 +292,9 @@ class GTypesGenerator(object): self.c(' return t;\n') self.c('}\n\n') - file_set_contents(self.output + '.h', ''.join(self.header)) - file_set_contents(self.output + '-body.h', ''.join(self.body)) - file_set_contents(self.output + '-gtk-doc.h', ''.join(self.docs)) + file_set_contents(self.output + '.h', u('').join(self.header).encode('utf-8')) + file_set_contents(self.output + '-body.h', u('').join(self.body).encode('utf-8')) + file_set_contents(self.output + '-gtk-doc.h', u('').join(self.docs).encode('utf-8')) if __name__ == '__main__': argv = sys.argv[1:] diff --git a/tools/libglibcodegen.py b/tools/libglibcodegen.py index 6a9d214..6cd1a62 100644 --- a/tools/libglibcodegen.py +++ b/tools/libglibcodegen.py @@ -154,7 +154,7 @@ def type_to_gtype(s): return ("GHashTable *", "DBUS_TYPE_G_STRING_STRING_HASHTABLE", "BOXED", False) elif s[:2] == 'a{': #some arbitrary hash tables if s[2] not in ('y', 'b', 'n', 'q', 'i', 'u', 's', 'o', 'g'): - raise Exception, "can't index a hashtable off non-basic type " + s + raise Exception("can't index a hashtable off non-basic type " + s) first = type_to_gtype(s[2]) second = type_to_gtype(s[3:-1]) return ("GHashTable *", "(dbus_g_type_get_map (\"GHashTable\", " + first[1] + ", " + second[1] + "))", "BOXED", False) @@ -169,4 +169,4 @@ def type_to_gtype(s): return ("GValueArray *", gtype, "BOXED", True) # we just don't know .. - raise Exception, "don't know the GType for " + s + raise Exception("don't know the GType for " + s) diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py index 7e9eb9a..99de663 100644 --- a/tools/libtpcodegen.py +++ b/tools/libtpcodegen.py @@ -21,6 +21,7 @@ please make any changes there. # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA import os +import sys from string import ascii_letters, digits @@ -28,6 +29,20 @@ NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" _ASCII_ALNUM = ascii_letters + digits +if sys.version_info[0] >= 3: + def u(s): + """Return s, which must be a str literal with no non-ASCII characters. + This is like a more restricted form of the Python 2 u'' syntax. + """ + return s.encode('ascii').decode('ascii') +else: + def u(s): + """Return a Unicode version of s, which must be a str literal + (a bytestring) in which each byte is an ASCII character. + This is like a more restricted form of the u'' syntax. + """ + return s.decode('ascii') + def file_set_contents(filename, contents): try: os.remove(filename) @@ -38,13 +53,15 @@ def file_set_contents(filename, contents): except OSError: pass - open(filename + '.tmp', 'w').write(contents) + open(filename + '.tmp', 'wb').write(contents) os.rename(filename + '.tmp', filename) def cmp_by_name(node1, node2): return cmp(node1.getAttributeNode("name").nodeValue, node2.getAttributeNode("name").nodeValue) +def key_by_name(node): + return node.getAttributeNode("name").nodeValue def escape_as_identifier(identifier): """Escape the given string to be a valid D-Bus object path or service @@ -168,6 +185,9 @@ class _SignatureIter: self.remaining = string def next(self): + return self.__next__() + + def __next__(self): if self.remaining == '': raise StopIteration diff --git a/tools/make-release-mail.py b/tools/make-release-mail.py index 2bd7c2b..b03ebd2 100644 --- a/tools/make-release-mail.py +++ b/tools/make-release-mail.py @@ -6,6 +6,15 @@ # to . I hope that you enjoy your stay. import sys +import re + +def looks_like_a_header(line, package, version=None): + if version is None: + pattern = "^%s .* \(.*\)$" % package + else: + pattern = "^%s %s \(.*\)$" % (package, version) + + return re.match(pattern, line) is not None def extract_description(package, version, news_path): release_name = [] @@ -15,7 +24,7 @@ def extract_description(package, version, news_path): lines = (line for line in f.readlines()) for line in lines: # Find the 'telepathy-foo 0.1.2' header - if line.startswith("%s %s" % (package, version)): + if looks_like_a_header(line, package, version): break # Skip the ====== line, and the first blank line @@ -27,7 +36,7 @@ def extract_description(package, version, news_path): for line in lines: line = line.rstrip() # If we hit the next version header, we're done - if line.startswith(package): + if looks_like_a_header(line, package): break # Else, if we hit a blank line and we're still reading the release # name, we're done with the release name. @@ -45,6 +54,7 @@ def extract_description(package, version, news_path): return ('\n'.join(release_name), '\n'.join(details).rstrip()) BASE_URL = 'http://telepathy.freedesktop.org/releases' +GIT_URL = 'http://cgit.freedesktop.org/telepathy' def main(package, version, news_path): release_name, details = extract_description(package, version, news_path) @@ -54,9 +64,11 @@ def main(package, version, news_path): tarball: %(base_url)s/%(package)s/%(package)s-%(version)s.tar.gz signature: %(base_url)s/%(package)s/%(package)s-%(version)s.tar.gz.asc +git: %(git_url)s/%(package)s %(details)s""".strip().rstrip() % { 'base_url': BASE_URL, + 'git_url': GIT_URL, 'package': package, 'version': version, 'release_name': release_name, -- 1.8.4.rc3