From 865233c76e437711cde0d2aee8b0b237b4e6b160 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 8 Jan 2014 17:16:41 +0000 Subject: [PATCH 1/8] Update tools from telepathy-glib --- tools/c-constants-gen.py | 31 +- tools/glib-client-gen.py | 682 ++++++++++++++++++++---------------- tools/glib-client-marshaller-gen.py | 19 +- tools/glib-ginterface-gen.py | 78 +++-- tools/glib-gtypes-generator.py | 28 +- tools/glib-interfaces-gen.py | 22 +- tools/libglibcodegen.py | 27 +- tools/libtpcodegen.py | 34 +- tools/telepathy.am | 23 +- tools/xincludator.py | 13 +- 10 files changed, 577 insertions(+), 380 deletions(-) diff --git a/tools/c-constants-gen.py b/tools/c-constants-gen.py index 09608c2..2b92dc6 100644 --- a/tools/c-constants-gen.py +++ b/tools/c-constants-gen.py @@ -3,6 +3,7 @@ from sys import argv, stdout, stderr import xml.dom.minidom +from libtpcodegen import file_set_contents, u from libglibcodegen import NS_TP, get_docstring, \ get_descendant_text, get_by_path @@ -11,19 +12,23 @@ class Generator(object): self.prefix = prefix + '_' self.spec = get_by_path(dom, "spec")[0] - self.__header = open(output_base + '.h', 'w') - self.__docs = open(output_base + '-gtk-doc.h', 'w') + self.output_base = output_base + self.__header = [] + self.__docs = [] def __call__(self): self.do_header() self.do_body() self.do_footer() + file_set_contents(self.output_base + '.h', u('').join(self.__header).encode('utf-8')) + file_set_contents(self.output_base + '-gtk-doc.h', u('').join(self.__docs).encode('utf-8')) + def write(self, code): - self.__header.write(code.encode('utf-8')) + self.__header.append(code) def d(self, code): - self.__docs.write(code.encode('utf-8')) + self.__docs.append(code) # Header def do_header(self): @@ -62,8 +67,7 @@ extern "C" { flags.getAttribute('name') self.d("""\ /** - * -%s: + * %s: """ % (self.prefix + name).replace('_', '')) for flag in get_by_path(flags, 'flag'): self.do_gtkdoc(flag, value_prefix) @@ -79,7 +83,7 @@ extern "C" { */ """) - self.write("typedef enum {\n") + self.write("typedef enum /*< flags >*/ {\n") for flag in get_by_path(flags, 'flag'): self.do_val(flag, value_prefix) @@ -97,8 +101,7 @@ extern "C" { enum.getAttribute('name') + 's' self.d("""\ /** - * -%s: + * %s: """ % (self.prefix + name).replace('_', '')) vals = get_by_path(enum, 'enumvalue') for val in vals: @@ -123,19 +126,21 @@ extern "C" { self.d("""\ /** - * NUM_%(upper-plural)s: + * %(upper-prefix)sNUM_%(upper-plural)s: * * 1 higher than the highest valid value of #%(mixed-name)s. */ """ % {'mixed-name' : (self.prefix + name).replace('_', ''), - 'upper-plural' : (self.prefix + name_plural).upper(), + 'upper-prefix' : self.prefix.upper(), + 'upper-plural' : name_plural.upper(), 'last-val' : vals[-1].getAttribute('value')}) self.write("""\ -#define NUM_%(upper-plural)s (%(last-val)s+1) +#define %(upper-prefix)sNUM_%(upper-plural)s (%(last-val)s+1) """ % {'mixed-name' : (self.prefix + name).replace('_', ''), - 'upper-plural' : (self.prefix + name_plural).upper(), + 'upper-prefix' : self.prefix.upper(), + 'upper-plural' : name_plural.upper(), 'last-val' : vals[-1].getAttribute('value')}) def do_val(self, val, value_prefix): diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py index 6b0bdeb..cd420a1 100644 --- a/tools/glib-client-gen.py +++ b/tools/glib-client-gen.py @@ -27,8 +27,9 @@ import os.path import xml.dom.minidom from getopt import gnu_getopt -from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \ - get_docstring, xml_escape, get_deprecated +from libtpcodegen import file_set_contents, key_by_name, u +from libglibcodegen import (Signature, type_to_gtype, + get_docstring, xml_escape, get_deprecated, copy_into_gvalue) NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" @@ -40,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() @@ -56,25 +59,37 @@ class Generator(object): % opts.get('--subclass', 'TpProxy')) if self.proxy_arg == 'void *': self.proxy_arg = 'gpointer ' - self.generate_reentrant = ('--generate-reentrant' in opts or - '--deprecate-reentrant' in opts) + + self.reentrant_symbols = set() + try: + filename = opts['--generate-reentrant'] + with open(filename, 'r') as f: + for line in f.readlines(): + self.reentrant_symbols.add(line.strip()) + except KeyError: + pass + self.deprecate_reentrant = opts.get('--deprecate-reentrant', None) 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): @@ -139,8 +154,12 @@ class Generator(object): name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info - self.d(' * @%s: %s' % (name, - xml_escape(get_docstring(elt) or '(Undocumented)'))) + docs = get_docstring(elt) or '(Undocumented)' + + if ctype == 'guint ' and tp_type != '': + docs += ' (#%s)' % ('Tp' + tp_type.replace('_', '')) + + self.d(' * @%s: %s' % (name, xml_escape(docs))) self.d(' * @user_data: User-supplied data') self.d(' * @weak_object: User-supplied weakly referenced object') @@ -177,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;') @@ -185,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): @@ -194,36 +215,8 @@ class Generator(object): self.b(' g_value_unset (args->values + %d);' % i) self.b(' g_value_init (args->values + %d, %s);' % (i, gtype)) - if gtype == 'G_TYPE_STRING': - self.b(' g_value_set_string (args->values + %d, %s);' - % (i, name)) - elif marshaller == 'BOXED': - self.b(' g_value_set_boxed (args->values + %d, %s);' - % (i, name)) - elif gtype == 'G_TYPE_UCHAR': - self.b(' 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)) - elif gtype == 'G_TYPE_INT': - self.b(' 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)) - elif gtype == 'G_TYPE_INT64': - self.b(' g_value_set_int (args->values + %d, %s);' - % (i, name)) - elif gtype == 'G_TYPE_UINT64': - 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);' - % (i, name)) - else: - assert False, ("Don't know how to put %s in a GValue" - % gtype) + self.b(' ' + copy_into_gvalue('args->values + %d' % i, + gtype, marshaller, name)) self.b('') self.b(' tp_proxy_signal_connection_v0_take_results (sc, args);') @@ -273,12 +266,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('}') @@ -298,9 +293,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') @@ -325,8 +322,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,') @@ -335,8 +332,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,') @@ -353,8 +349,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,') @@ -372,6 +366,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() @@ -432,9 +446,14 @@ class Generator(object): name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info + docs = xml_escape(get_docstring(elt) or '(Undocumented)') + + if ctype == 'guint ' and tp_type != '': + docs += ' (#%s)' % ('Tp' + tp_type.replace('_', '')) + self.d(' * @%s: Used to return an \'out\' argument if @error is ' '%%NULL: %s' - % (name, xml_escape(get_docstring(elt) or '(Undocumented)'))) + % (name, docs)) self.d(' * @error: %NULL on success, or an error on failure') self.d(' * @user_data: user-supplied data') @@ -480,19 +499,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 @@ -502,92 +527,68 @@ 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)) - - if gtype == 'G_TYPE_STRING': - self.b(' 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)) - elif gtype == 'G_TYPE_UCHAR': - self.b(' 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)) - elif gtype == 'G_TYPE_INT': - self.b(' 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)) - elif gtype == 'G_TYPE_INT64': - 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);' - % (i, name)) - elif gtype == 'G_TYPE_DOUBLE': - self.b(' g_value_set_double (args->values + %d, %s);' - % (i, name)) - else: - assert False, ("Don't know how to put %s in a GValue" - % gtype) + collector('') + collector(' g_value_unset (args->values + %d);' % i) + collector(' g_value_init (args->values + %d, %s);' + % (i, gtype)) + collector(' ' + copy_into_gvalue('args->values + %d' % i, + gtype, marshaller, name)) - 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) @@ -651,11 +652,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('') @@ -672,13 +675,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') @@ -687,8 +692,13 @@ class Generator(object): name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info + docs = xml_escape(get_docstring(elt) or '(Undocumented)') + + if ctype == 'guint ' and tp_type != '': + docs += ' (#%s)' % ('Tp' + tp_type.replace('_', '')) + self.d(' * @%s: Used to pass an \'in\' argument: %s' - % (name, xml_escape(get_docstring(elt) or '(Undocumented)'))) + % (name, docs)) self.d(' * @callback: called when the method call succeeds or fails;') self.d(' * may be %NULL to make a "fire and forget" call with no ') @@ -721,8 +731,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: @@ -749,8 +759,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 || ' @@ -758,35 +766,15 @@ class Generator(object): self.b(' g_return_val_if_fail (callback != NULL || ' 'weak_object == NULL, NULL);') self.b('') - 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('') - 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: @@ -809,6 +797,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) @@ -832,9 +832,40 @@ 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) + # 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) # leave a gap for the end of the method self.d('') @@ -853,137 +884,159 @@ class Generator(object): # GError **error, # GMainLoop **loop); - self.b('typedef struct {') - self.b(' GMainLoop *loop;') - self.b(' GError **error;') + run_method_name = '%s_%s_run_%s' % (self.prefix_lc, iface_lc, member_lc) + + 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 + + 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_%s_run_%s (%sproxy,' - % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) - self.h(' gint timeout_ms,') + h('gboolean %s (%sproxy,' + % (run_method_name, self.proxy_arg)) + h(' gint timeout_ms,') - self.d('/**') - self.d(' * %s_%s_run_%s:' % (self.prefix_lc, iface_lc, member_lc)) - 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 ctype, gtype, marshaller, pointer = info - self.d(' * @%s: Used to pass an \'in\' argument: %s' - % (name, xml_escape(get_docstring(elt) or '(Undocumented)'))) + docs = xml_escape(get_docstring(elt) or '(Undocumented)') + + if ctype == 'guint ' and tp_type != '': + docs += ' (#%s)' % ('Tp' + tp_type.replace('_', '')) + + 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_%s_run_%s (%sproxy,' - % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) - self.b(' gint timeout_ms,') + b('gboolean\n%s (%sproxy,' + % (run_method_name, self.proxy_arg)) + b(' gint timeout_ms,') for arg in in_args: name, info, tp_type, elt = arg @@ -991,69 +1044,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(' 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,') + 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 @@ -1061,24 +1114,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 = [] @@ -1140,6 +1193,11 @@ class Generator(object): def __call__(self): + if self.guard is not None: + self.h('#ifndef %s' % self.guard) + self.h('#define %s' % self.guard) + self.h('') + self.h('G_BEGIN_DECLS') self.h('') @@ -1147,14 +1205,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)) @@ -1171,7 +1239,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,') @@ -1198,10 +1266,17 @@ class Generator(object): self.h('G_END_DECLS') self.h('') - open(self.basename + '.h', 'w').write('\n'.join(self.__header)) - open(self.basename + '-body.h', 'w').write('\n'.join(self.__body)) - open(self.basename + '-gtk-doc.h', 'w').write('\n'.join(self.__docs)) + if self.guard is not None: + self.h('#endif /* defined (%s) */' % self.guard) + self.h('') + + 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] @@ -1211,8 +1286,9 @@ if __name__ == '__main__': options, argv = gnu_getopt(sys.argv[1:], '', ['group=', 'subclass=', 'subclass-assert=', 'iface-quark-prefix=', 'tp-proxy-api=', - 'generate-reentrant', 'deprecate-reentrant=', - 'deprecation-attribute=']) + 'generate-reentrant=', 'deprecate-reentrant=', + 'deprecation-attribute=', 'guard=', + 'split-reentrants=']) opts = {} diff --git a/tools/glib-client-marshaller-gen.py b/tools/glib-client-marshaller-gen.py index 5444725..cd9823b 100644 --- a/tools/glib-client-marshaller-gen.py +++ b/tools/glib-client-marshaller-gen.py @@ -31,22 +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 (%s,' % marshaller - 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 04509fd..6ef9f4a 100644 --- a/tools/glib-ginterface-gen.py +++ b/tools/glib-ginterface-gen.py @@ -26,18 +26,28 @@ import sys import os.path import xml.dom.minidom -from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \ - NS_TP, dbus_gutils_wincaps_to_uscore, \ - signal_to_marshal_name, method_to_glue_marshal_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 NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" +def get_emits_changed(node): + try: + return [ + annotation.getAttribute('value') + for annotation in node.getElementsByTagName('annotation') + if annotation.getAttribute('name') == 'org.freedesktop.DBus.Property.EmitsChangedSignal' + ][0] + except IndexError: + return None + 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 = [] @@ -73,20 +83,15 @@ 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): @@ -108,6 +113,8 @@ class Generator(object): if tmp and not self.allow_havoc: raise AssertionError('%s is %s' % (self.iface_name, tmp)) + iface_emits_changed = get_emits_changed(interface) + self.b('static const DBusGObjectInfo _%s%s_object_info;' % (self.prefix_, node_name_lc)) self.b('') @@ -270,6 +277,16 @@ class Generator(object): flags = ('TP_DBUS_PROPERTIES_MIXIN_FLAG_READ | ' 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE') + prop_emits_changed = get_emits_changed(m) + + if prop_emits_changed is None: + prop_emits_changed = iface_emits_changed + + if prop_emits_changed == 'true': + flags += ' | TP_DBUS_PROPERTIES_MIXIN_FLAG_EMITS_CHANGED' + elif prop_emits_changed == 'invalidates': + flags += ' | TP_DBUS_PROPERTIES_MIXIN_FLAG_EMITS_INVALIDATED' + self.b(' { 0, %s, "%s", 0, NULL, NULL }, /* %s */' % (flags, m.getAttribute('type'), m.getAttribute('name'))) @@ -399,8 +416,7 @@ class Generator(object): 'not match' % (method.getAttribute('name'), lc_name)) lc_name = lc_name.lower() - marshaller = method_to_glue_marshal_name(method, - self.signal_marshal_prefix) + marshaller = 'g_cclosure_marshal_generic' wrapper = self.prefix_ + self.node_name_lc + '_' + lc_name self.b(" { (GCallback) %s, %s, %d }," % (wrapper, marshaller, offset)) @@ -678,6 +694,7 @@ class Generator(object): self.d('/**') self.d(' * %s%s::%s:' % (self.Prefix, self.node_name_mixed, signal_name)) + self.d(' * @self: an object') for (ctype, name, gtype) in args: self.d(' * @%s: %s (FIXME, generate documentation)' % (name, ctype)) @@ -694,8 +711,7 @@ class Generator(object): in_base_init.append(' G_SIGNAL_RUN_LAST|G_SIGNAL_DETAILED,') in_base_init.append(' 0,') in_base_init.append(' NULL, NULL,') - in_base_init.append(' %s,' - % signal_to_marshal_name(signal, self.signal_marshal_prefix)) + in_base_init.append(' g_cclosure_marshal_generic,') in_base_init.append(' G_TYPE_NONE,') tmp = ['%d' % len(args)] + [gtype for (ctype, name, gtype) in args] in_base_init.append(' %s);' % ',\n '.join(tmp)) @@ -712,20 +728,26 @@ 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 ') - if self.have_properties(nodes): - self.h('#include ') - self.h('') self.h('G_BEGIN_DECLS') self.h('') 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('') @@ -742,13 +764,12 @@ class Generator(object): self.h('') self.b('') - open(self.basename + '.h', 'w').write('\n'.join(self.__header)) - open(self.basename + '.c', 'w').write('\n'.join(self.__body)) - open(self.basename + '-gtk-doc.h', 'w').write('\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: @@ -768,7 +789,7 @@ options: void symbol (DBusGMethodInvocation *context) and return some sort of "not implemented" error via dbus_g_method_return_error (context, ...) -""" +""") sys.exit(1) @@ -779,7 +800,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] @@ -792,6 +814,7 @@ if __name__ == '__main__': end_headers = [] not_implemented_func = '' allow_havoc = False + allow_single_include = False for option, value in options: if option == '--filename': @@ -810,6 +833,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]) @@ -817,4 +842,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 a49c36e..1477bd3 100644 --- a/tools/glib-gtypes-generator.py +++ b/tools/glib-gtypes-generator.py @@ -23,6 +23,7 @@ import sys import xml.dom.minidom +from libtpcodegen import file_set_contents, u from libglibcodegen import escape_as_identifier, \ get_docstring, \ NS_TP, \ @@ -42,15 +43,16 @@ class GTypesGenerator(object): self.PREFIX_ = self.Prefix.upper() + '_' self.prefix_ = self.Prefix.lower() + '_' - self.header = open(output + '.h', 'w') - self.body = open(output + '-body.h', 'w') - self.docs = open(output + '-gtk-doc.h', 'w') + self.header = [] + self.body = [] + self.docs = [] + self.output = output for f in (self.header, self.body, self.docs): - f.write('/* Auto-generated, do not edit.\n *\n' - ' * This file may be distributed under the same terms\n' - ' * as the specification from which it was generated.\n' - ' */\n\n') + f.append('/* Auto-generated, do not edit.\n *\n' + ' * This file may be distributed under the same terms\n' + ' * as the specification from which it was generated.\n' + ' */\n\n') # keys are e.g. 'sv', values are the key escaped self.need_mappings = {} @@ -66,13 +68,13 @@ class GTypesGenerator(object): self.need_other_arrays = {} def h(self, code): - self.header.write(code.encode("utf-8")) + self.header.append(code) def c(self, code): - self.body.write(code.encode("utf-8")) + self.body.append(code) def d(self, code): - self.docs.write(code.encode('utf-8')) + self.docs.append(code) def do_mapping_header(self, mapping): members = mapping.getElementsByTagNameNS(NS_TP, 'member') @@ -89,7 +91,7 @@ class GTypesGenerator(object): docstring = get_docstring(mapping) or '(Undocumented)' - self.d('/**\n * %s:\n *\n' % name) + self.d('/**\n * %s:\n *\n' % name.strip()) self.d(' * %s\n' % xml_escape(docstring)) self.d(' *\n') self.d(' * This macro expands to a call to a function\n') @@ -290,6 +292,10 @@ class GTypesGenerator(object): self.c(' return t;\n') self.c('}\n\n') + 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/glib-interfaces-gen.py b/tools/glib-interfaces-gen.py index 69c721b..b67d7b4 100644 --- a/tools/glib-interfaces-gen.py +++ b/tools/glib-interfaces-gen.py @@ -3,6 +3,7 @@ from sys import argv, stdout, stderr import xml.dom.minidom +from libtpcodegen import file_set_contents, u from libglibcodegen import NS_TP, get_docstring, \ get_descendant_text, get_by_path @@ -13,25 +14,33 @@ class Generator(object): assert declfile.endswith('.h') docfile = declfile[:-2] + '-gtk-doc.h' - self.impls = open(implfile, 'w') - self.decls = open(declfile, 'w') - self.docs = open(docfile, 'w') + self.implfile = implfile + self.declfile = declfile + self.docfile = docfile + + self.impls = [] + self.decls = [] + self.docs = [] self.spec = get_by_path(dom, "spec")[0] def h(self, code): - self.decls.write(code.encode('utf-8')) + self.decls.append(code) def c(self, code): - self.impls.write(code.encode('utf-8')) + self.impls.append(code) def d(self, code): - self.docs.write(code.encode('utf-8')) + self.docs.append(code) def __call__(self): for f in self.h, self.c: self.do_header(f) self.do_body() + file_set_contents(self.implfile, u('').join(self.impls).encode('utf-8')) + file_set_contents(self.declfile, u('').join(self.decls).encode('utf-8')) + file_set_contents(self.docfile, u('').join(self.docs).encode('utf-8')) + # Header def do_header(self, f): f('/* Generated from: ') @@ -49,6 +58,7 @@ class Generator(object): f(""" */ +#include """) # Body diff --git a/tools/libglibcodegen.py b/tools/libglibcodegen.py index 6a9d214..0b703a5 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,27 @@ 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) + + +def copy_into_gvalue(gvaluep, gtype, marshaller, name): + if gtype == 'G_TYPE_STRING': + return 'g_value_set_string (%s, %s);' % (gvaluep, name) + elif marshaller == 'BOXED': + return 'g_value_set_boxed (%s, %s);' % (gvaluep, name) + elif gtype == 'G_TYPE_UCHAR': + return 'g_value_set_uchar (%s, %s);' % (gvaluep, name) + elif gtype == 'G_TYPE_BOOLEAN': + return 'g_value_set_boolean (%s, %s);' % (gvaluep, name) + elif gtype == 'G_TYPE_INT': + return 'g_value_set_int (%s, %s);' % (gvaluep, name) + elif gtype == 'G_TYPE_UINT': + return 'g_value_set_uint (%s, %s);' % (gvaluep, name) + elif gtype == 'G_TYPE_INT64': + return 'g_value_set_int (%s, %s);' % (gvaluep, name) + elif gtype == 'G_TYPE_UINT64': + return 'g_value_set_uint64 (%s, %s);' % (gvaluep, name) + elif gtype == 'G_TYPE_DOUBLE': + return 'g_value_set_double (%s, %s);' % (gvaluep, name) + else: + raise AssertionError("Don't know how to put %s in a GValue" % gtype) diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py index 837ff2f..99de663 100644 --- a/tools/libtpcodegen.py +++ b/tools/libtpcodegen.py @@ -20,7 +20,8 @@ please make any changes there. # License along with this library; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - +import os +import sys from string import ascii_letters, digits @@ -28,11 +29,39 @@ 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) + except OSError: + pass + try: + os.remove(filename + '.tmp') + except OSError: + pass + + 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 @@ -156,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/telepathy.am b/tools/telepathy.am index d080afe..20ff0be 100644 --- a/tools/telepathy.am +++ b/tools/telepathy.am @@ -3,7 +3,7 @@ dist-hook: chmod u+w ${distdir}/ChangeLog if test -d ${top_srcdir}/.git; then \ - git log --date=iso $(CHANGELOG_RANGE) > ${distdir}/ChangeLog; \ + ( cd ${top_srcdir} && git log --date=iso $(CHANGELOG_RANGE) ) > ${distdir}/ChangeLog; \ fi distcheck-hook: @@ -26,11 +26,13 @@ _is-release-check: exit 2; \ ;; \ esac - @if ! git diff --no-ext-diff --quiet --exit-code; then \ + @cd ${top_srcdir} && \ + if ! git diff --no-ext-diff --quiet --exit-code; then \ echo "Hey! Your tree is dirty! No release for you." >&2; \ exit 2; \ fi - @if ! git diff --cached --no-ext-diff --quiet --exit-code; then \ + @cd ${top_srcdir} && \ + if ! git diff --cached --no-ext-diff --quiet --exit-code; then \ echo "Hey! You have changes staged! No release for you." >&2; \ exit 2; \ fi @@ -43,9 +45,16 @@ endif %.tar.gz.asc: %.tar.gz $(AM_V_GEN)gpg --detach-sign --armor $@ -@PACKAGE@-@VERSION@.tar.gz: _is-release-check check distcheck +@PACKAGE@-@VERSION@.tar.gz: + $(MAKE) _is-release-check + $(MAKE) check + $(MAKE) distcheck -maintainer-prepare-release: _is-release-check all distcheck release-mail +maintainer-prepare-release: + $(MAKE) _is-release-check + $(MAKE) all + $(MAKE) distcheck + $(MAKE) release-mail git tag -s @PACKAGE@-@VERSION@ -m @PACKAGE@' '@VERSION@ gpg --detach-sign --armor @PACKAGE@-@VERSION@.tar.gz @@ -65,7 +74,9 @@ _maintainer-upload-release: _maintainer-upload-release-check rsync -vzP @PACKAGE@-@VERSION@.tar.gz telepathy.freedesktop.org:/srv/telepathy.freedesktop.org/www/releases/@PACKAGE@/@PACKAGE@-@VERSION@.tar.gz rsync -vzP @PACKAGE@-@VERSION@.tar.gz.asc telepathy.freedesktop.org:/srv/telepathy.freedesktop.org/www/releases/@PACKAGE@/@PACKAGE@-@VERSION@.tar.gz.asc -maintainer-make-release: maintainer-prepare-release maintainer-upload-release +maintainer-make-release: + $(MAKE) maintainer-prepare-release + $(MAKE) maintainer-upload-release @echo "Now:" @echo " • bump the nano-version;" @echo " • push the branch and tags upstream; and" diff --git a/tools/xincludator.py b/tools/xincludator.py index 63e106a..f9ed49c 100644 --- a/tools/xincludator.py +++ b/tools/xincludator.py @@ -1,17 +1,19 @@ #!/usr/bin/python +import sys from sys import argv, stdout, stderr import codecs, locale import os import xml.dom.minidom -stdout = codecs.getwriter('utf-8')(stdout) +if sys.version_info[0] < 3: + stdout = codecs.getwriter('utf-8')(stdout) NS_XI = 'http://www.w3.org/2001/XInclude' def xincludate(dom, base, dropns = []): remove_attrs = [] - for i in xrange(dom.documentElement.attributes.length): + for i in range(dom.documentElement.attributes.length): attr = dom.documentElement.attributes.item(i) if attr.prefix == 'xmlns': if attr.localName in dropns: @@ -34,6 +36,11 @@ if __name__ == '__main__': argv = argv[1:] dom = xml.dom.minidom.parse(argv[0]) xincludate(dom, argv[0]) - xml = dom.toxml() + + if sys.version_info[0] >= 3: + xml = dom.toxml(encoding=None) + else: + xml = dom.toxml() + stdout.write(xml) stdout.write('\n') -- 1.8.5.2