diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2014-03-18 18:44:13 +0000 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2014-03-27 15:59:19 +0000 |
commit | 63e329ee90820f9d75bd9d2ecf3335cdbd4681bc (patch) | |
tree | f10cae669cf84e9a37c1d09f1b00a4d76d6c0b5a | |
parent | 1c94485115cf0f71dbfa0d5d44cb66c6b776007d (diff) |
Sync codegen from telepathy-glib gdbus branch
-rw-r--r-- | tools/c-constants-gen.py | 8 | ||||
-rw-r--r-- | tools/doc-generator.xsl | 2 | ||||
-rw-r--r-- | tools/glib-client-gen.py | 830 | ||||
-rw-r--r-- | tools/glib-errors-check-gen.py | 1 | ||||
-rw-r--r-- | tools/glib-ginterface-gen.py | 371 | ||||
-rw-r--r-- | tools/libglibcodegen.py | 287 | ||||
-rw-r--r-- | tools/libtpcodegen.py | 10 |
7 files changed, 734 insertions, 775 deletions
diff --git a/tools/c-constants-gen.py b/tools/c-constants-gen.py index a08afee06..2b92dc6d9 100644 --- a/tools/c-constants-gen.py +++ b/tools/c-constants-gen.py @@ -130,13 +130,6 @@ extern "C" { * * 1 higher than the highest valid value of #%(mixed-name)s. */ - -/** - * NUM_%(upper-prefix)s%(upper-plural)s: (skip) - * - * 1 higher than the highest valid value of #%(mixed-name)s. - * In new code, use %(upper-prefix)sNUM_%(upper-plural)s instead. - */ """ % {'mixed-name' : (self.prefix + name).replace('_', ''), 'upper-prefix' : self.prefix.upper(), 'upper-plural' : name_plural.upper(), @@ -144,7 +137,6 @@ extern "C" { self.write("""\ #define %(upper-prefix)sNUM_%(upper-plural)s (%(last-val)s+1) -#define NUM_%(upper-prefix)s%(upper-plural)s %(upper-prefix)sNUM_%(upper-plural)s """ % {'mixed-name' : (self.prefix + name).replace('_', ''), 'upper-prefix' : self.prefix.upper(), diff --git a/tools/doc-generator.xsl b/tools/doc-generator.xsl index 90090d290..76fc96964 100644 --- a/tools/doc-generator.xsl +++ b/tools/doc-generator.xsl @@ -276,7 +276,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <xsl:when test="tp:property"> <h2 xmlns="http://www.w3.org/1999/xhtml">Telepathy Properties:</h2> <p xmlns="http://www.w3.org/1999/xhtml">Accessed using the - <a href="#im.telepathy1.Properties">Telepathy + <a href="#org.freedesktop.Telepathy.Properties">Telepathy Properties</a> interface.</p> <dl xmlns="http://www.w3.org/1999/xhtml"> <xsl:apply-templates select="tp:property"/> diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py index a0fecf083..bc117c5d8 100644 --- a/tools/glib-client-gen.py +++ b/tools/glib-client-gen.py @@ -29,8 +29,8 @@ from getopt import gnu_getopt 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) - + get_docstring, xml_escape, get_deprecated, + value_getter) NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" @@ -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,6 +73,8 @@ 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): @@ -79,6 +83,12 @@ class Generator(object): def b(self, s): 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): self.__docs.append(s) @@ -103,7 +113,7 @@ class Generator(object): arg_count = 0 args = [] - out_args = [] + arg_sig = [] for arg in signal.getElementsByTagName('arg'): name = arg.getAttribute('name') @@ -118,11 +128,10 @@ class Generator(object): info = type_to_gtype(type) args.append((name, info, tp_type, arg)) + arg_sig.append(type) callback_name = ('%s_%s_signal_callback_%s' % (self.prefix_lc, iface_lc, member_lc)) - collect_name = ('_%s_%s_collect_args_of_%s' - % (self.prefix_lc, iface_lc, member_lc)) invoke_name = ('_%s_%s_invoke_callback_for_%s' % (self.prefix_lc, iface_lc, member_lc)) @@ -172,98 +181,41 @@ class Generator(object): self.h(' gpointer user_data, GObject *weak_object);') - if args: - self.b('static void') - self.b('%s (DBusGProxy *proxy G_GNUC_UNUSED,' % collect_name) - - for arg in args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - const = pointer and 'const ' or '' - - self.b(' %s%s%s,' % (const, ctype, name)) - - 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;') - self.b('') - self.b(' g_value_init (&blank, G_TYPE_INT);') - 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): - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - self.b(' g_value_unset (args->values + %d);' % i) - self.b(' g_value_init (args->values + %d, %s);' % (i, 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);') - self.b('}') - self.b('static void') self.b('%s (TpProxy *tpproxy,' % invoke_name) - self.b(' GError *error G_GNUC_UNUSED,') - self.b(' GValueArray *args,') + self.b(' const GError *error G_GNUC_UNUSED,') + self.b(' GVariant *variant,') self.b(' GCallback generic_callback,') self.b(' gpointer user_data,') self.b(' GObject *weak_object)') self.b('{') self.b(' %s callback =' % callback_name) self.b(' (%s) generic_callback;' % callback_name) + + if args: + self.b(' GValue args_val = G_VALUE_INIT;') + self.b(' GValueArray *args_va;') + self.b('') + self.b(' dbus_g_value_parse_g_variant (variant, &args_val);') + self.b(' args_va = g_value_get_boxed (&args_val);') + self.b('') self.b(' if (callback != NULL)') self.b(' callback (g_object_ref (tpproxy),') - # FIXME: factor out into a function for i, arg in enumerate(args): name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info - if marshaller == 'BOXED': - self.b(' g_value_get_boxed (args->values + %d),' % i) - elif gtype == 'G_TYPE_STRING': - self.b(' g_value_get_string (args->values + %d),' % i) - elif gtype == 'G_TYPE_UCHAR': - self.b(' g_value_get_uchar (args->values + %d),' % i) - elif gtype == 'G_TYPE_BOOLEAN': - self.b(' g_value_get_boolean (args->values + %d),' % i) - elif gtype == 'G_TYPE_UINT': - self.b(' g_value_get_uint (args->values + %d),' % i) - elif gtype == 'G_TYPE_INT': - self.b(' g_value_get_int (args->values + %d),' % i) - elif gtype == 'G_TYPE_UINT64': - self.b(' g_value_get_uint64 (args->values + %d),' % i) - elif gtype == 'G_TYPE_INT64': - self.b(' g_value_get_int64 (args->values + %d),' % i) - elif gtype == 'G_TYPE_DOUBLE': - self.b(' g_value_get_double (args->values + %d),' % i) - else: - assert False, "Don't know how to get %s from a GValue" % gtype + getter = value_getter(gtype, marshaller) + self.b(' %s (args_va->values + %d),' % (getter, i)) self.b(' user_data,') 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') + if args: + self.b(' g_value_unset (&args_val);') self.b(' g_object_unref (tpproxy);') self.b('}') @@ -283,9 +235,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') @@ -310,8 +264,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,') @@ -320,43 +274,44 @@ 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,') self.b(' GObject *weak_object,') self.b(' GError **error)') self.b('{') - self.b(' GType expected_types[%d] = {' % (len(args) + 1)) - - for arg in args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - self.b(' %s,' % gtype) - - 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,') + self.b(' return tp_proxy_signal_connection_v1_new ((TpProxy *) proxy,') self.b(' %s, \"%s\",' % (self.get_iface_quark(), member)) - self.b(' expected_types,') - - if args: - self.b(' G_CALLBACK (%s),' % collect_name) - else: - self.b(' NULL, /* no args => no collector function */') - + self.b(' G_VARIANT_TYPE ("(%s)"),' % ''.join(arg_sig)) self.b(' %s,' % invoke_name) self.b(' G_CALLBACK (callback), user_data, destroy,') self.b(' weak_object, error);') 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() @@ -372,6 +327,8 @@ class Generator(object): ret_count = 0 in_args = [] out_args = [] + in_sig = [] + out_sig = [] for arg in method.getElementsByTagName('arg'): name = arg.getAttribute('name') @@ -396,6 +353,7 @@ class Generator(object): if direction != 'out': in_args.append((name, info, tp_type, arg)) else: + out_sig.append(type) out_args.append((name, info, tp_type, arg)) # Async reply callback type @@ -466,101 +424,19 @@ class Generator(object): iface_lc, member_lc) - collect_callback = '_%s_%s_collect_callback_%s' % (self.prefix_lc, - iface_lc, - member_lc) - - # 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;') - - if len(out_args) > 0: - self.b(' GValueArray *args;') - self.b(' GValue blank = { 0 };') - self.b(' guint i;') - - for arg in out_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - # "We handle variants specially; the caller is expected to - # have already allocated storage for them". Thanks, - # dbus-glib... - if gtype == 'G_TYPE_VALUE': - self.b(' GValue *%s = g_new0 (GValue, 1);' % name) - else: - self.b(' %s%s;' % (ctype, name)) - - self.b('') - self.b(' 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)) - else: - self.b(' %s, &%s,' % (gtype, name)) - - self.b(' G_TYPE_INVALID);') - - if len(out_args) == 0: - self.b(' 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);') - - 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(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS') - 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);') - self.b(' 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)) - - self.b(' ' + copy_into_gvalue('args->values + %d' % i, - gtype, marshaller, name)) - - self.b(' tp_proxy_pending_call_v0_take_results (user_data, ' - 'NULL, args);') - - self.b('}') - self.b('static void') self.b('%s (TpProxy *self,' % invoke_callback) - self.b(' GError *error,') - self.b(' GValueArray *args,') + self.b(' const GError *error,') + self.b(' GVariant *args,') self.b(' GCallback generic_callback,') self.b(' gpointer user_data,') self.b(' GObject *weak_object)') self.b('{') + + if out_args: + self.b(' GValue args_val = G_VALUE_INIT;') + self.b(' GValueArray *args_va;') + self.b(' %s callback = (%s) generic_callback;' % (callback_name, callback_name)) self.b('') @@ -580,48 +456,29 @@ class Generator(object): self.b(' 0,') self.b(' error, user_data, weak_object);') - self.b(' g_error_free (error);') self.b(' return;') self.b(' }') + self.b('') + + if out_args: + self.b(' dbus_g_value_parse_g_variant (args, &args_val);') + self.b(' args_va = g_value_get_boxed (&args_val);') + self.b('') self.b(' callback ((%s) self,' % self.proxy_cls) - # FIXME: factor out into a function for i, arg in enumerate(out_args): name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info - if marshaller == 'BOXED': - self.b(' g_value_get_boxed (args->values + %d),' % i) - elif gtype == 'G_TYPE_STRING': - self.b(' g_value_get_string (args->values + %d),' % i) - elif gtype == 'G_TYPE_UCHAR': - self.b(' g_value_get_uchar (args->values + %d),' % i) - elif gtype == 'G_TYPE_BOOLEAN': - self.b(' g_value_get_boolean (args->values + %d),' % i) - elif gtype == 'G_TYPE_UINT': - self.b(' g_value_get_uint (args->values + %d),' % i) - elif gtype == 'G_TYPE_INT': - self.b(' g_value_get_int (args->values + %d),' % i) - elif gtype == 'G_TYPE_UINT64': - self.b(' g_value_get_uint64 (args->values + %d),' % i) - elif gtype == 'G_TYPE_INT64': - self.b(' g_value_get_int64 (args->values + %d),' % i) - elif gtype == 'G_TYPE_DOUBLE': - self.b(' g_value_get_double (args->values + %d),' % i) - else: - assert False, "Don't know how to get %s from a GValue" % gtype + getter = value_getter(gtype, marshaller) + self.b(' %s (args_va->values + %d),' % (getter, i)) 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') + if out_args: + self.b('') + self.b(' g_value_unset (&args_val);') self.b('}') self.b('') @@ -638,13 +495,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') @@ -692,8 +551,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: @@ -716,97 +575,79 @@ class Generator(object): self.b(' GDestroyNotify destroy,') self.b(' GObject *weak_object)') self.b('{') - self.b(' GError *error = NULL;') - 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 || ' - 'destroy == NULL, NULL);') - 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(' (TpProxy *) proxy,') - self.b(' interface, &error);') - self.b(' G_GNUC_END_IGNORE_DEPRECATIONS') + self.b(' TpProxyPendingCall *ret;') + self.b(' GValue args_val = G_VALUE_INIT;') self.b('') - self.b(' if (iface == NULL)') - self.b(' {') - self.b(' if (callback != NULL)') - self.b(' callback (proxy,') + self.b(' g_value_init (&args_val, ' + 'dbus_g_type_get_struct ("GValueArray",') - for arg in out_args: + for arg in in_args: name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info + self.b(' %s,' % gtype) - 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('') - self.b(' if (callback == NULL)') - self.b(' {') - self.b(' dbus_g_proxy_call_no_reply (iface, "%s",' % member) + self.b(' G_TYPE_INVALID));') + self.b(' g_value_take_boxed (&args_val,') + self.b(' tp_value_array_build (%d,' % len(in_args)) for arg in in_args: name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info - - const = pointer and 'const ' or '' - self.b(' %s, %s,' % (gtype, name)) - self.b(' G_TYPE_INVALID);') - self.b(' return NULL;') - self.b(' }') - self.b(' else') - self.b(' {') - self.b(' TpProxyPendingCall *data;') + self.b(' G_TYPE_INVALID));') self.b('') - self.b(' data = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,') - self.b(' interface, "%s", iface,' % member) - self.b(' %s,' % invoke_callback) - self.b(' G_CALLBACK (callback), user_data, destroy,') - self.b(' weak_object, FALSE);') - 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) - self.b(' %s,' % collect_callback) - self.b(' data,') - self.b(' tp_proxy_pending_call_v0_completed,') - self.b(' timeout_ms,') + self.b(' ret = tp_proxy_pending_call_v1_new ((TpProxy *) proxy,') + self.b(' timeout_ms,') + self.b(' %s,' % self.get_iface_quark()) + self.b(' "%s",' % member) + self.b(' /* consume floating ref */') + self.b(' dbus_g_value_build_g_variant (&args_val),') + self.b(' G_VARIANT_TYPE ("(%s)"),' % (''.join(out_sig))) + self.b(' %s,' % invoke_callback) + self.b(' G_CALLBACK (callback),') + self.b(' user_data,') + self.b(' destroy,') + self.b(' weak_object);') + self.b(' g_value_unset (&args_val);') + self.b(' return ret;') + 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.b(' %s, %s,' % (gtype, 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) - self.b(' G_TYPE_INVALID));') - self.b('') - self.b(' return data;') - self.b(' }') - self.b('}') - self.b('') + 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) + in_args, out_args, out_sig) # leave a gap for the end of the method self.d('') @@ -814,7 +655,7 @@ class Generator(object): self.h('') def do_method_reentrant(self, method, iface_lc, member, member_lc, in_args, - out_args, collect_callback): + out_args, out_sig): # Reentrant blocking calls # Example: # gboolean tp_cli_properties_interface_run_get_properties @@ -826,96 +667,110 @@ 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(' const GError *error,') + b(' GVariant *args_variant,') + b(' GCallback dummy G_GNUC_UNUSED,') + b(' gpointer user_data,') + b(' GObject *weak_object G_GNUC_UNUSED)') + b('{') + + if out_args: + b(' GValue args_val = G_VALUE_INIT;') + b(' GValueArray *args;') + 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 = g_error_copy (error);') + b('') + b(' return;') + b(' }') + b('') + + if out_args: + b(' dbus_g_value_parse_g_variant (args_variant, &args_val);') + b(' args = g_value_get_boxed (&args_val);') 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('') - 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') + if out_args: + b(' g_value_unset (&args_val);') - 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 @@ -926,47 +781,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 @@ -974,113 +829,102 @@ 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(' 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);' - % 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(' FALSE /* completed */, FALSE /* success */ };') + b(' GValue args_val = G_VALUE_INIT;') + b('') + b(' g_value_init (&args_val, dbus_g_type_get_struct ("GValueArray",') for arg in in_args: name, info, tp_type, elt = arg ctype, gtype, marshaller, pointer = info + b(' %s,' % gtype) - const = pointer and 'const ' or '' + b(' G_TYPE_INVALID));') - self.b(' %s, %s,' % (gtype, name)) + b(' g_value_take_boxed (&args_val,') + b(' tp_value_array_build (%d,' % len(in_args)) - self.b(' G_TYPE_INVALID));') - self.b('') - self.b(' if (!state.completed)') - self.b(' g_main_loop_run (state.loop);') - self.b('') - self.b(' if (!state.completed)') - self.b(' tp_proxy_pending_call_cancel (pc);') - self.b('') - self.b(' if (loop != NULL)') - self.b(' *loop = NULL;') - self.b('') - self.b(' g_main_loop_unref (state.loop);') - self.b('') - self.b(' return state.success;') - self.b('}') - self.b('') - - def do_signal_add(self, signal): - marshaller_items = [] - gtypes = [] - - for i in signal.getElementsByTagName('arg'): - name = i.getAttribute('name') - type = i.getAttribute('type') - info = type_to_gtype(type) - # type, GType, STRING, is a pointer - gtypes.append(info[1]) + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + b(' %s, %s,' % (gtype, name)) - self.b(' dbus_g_proxy_add_signal (proxy, "%s",' - % signal.getAttribute('name')) - for gtype in gtypes: - self.b(' %s,' % gtype) - self.b(' G_TYPE_INVALID);') + b(' G_TYPE_INVALID));') + b('') + b(' g_return_val_if_fail (%s (proxy), FALSE);' + % self.proxy_assert) + b('') + b(' if (!tp_proxy_check_interface_by_id') + b(' ((TpProxy *) proxy, interface, error))') + b(' return FALSE;') + b('') + b(' state.loop = g_main_loop_new (NULL, FALSE);') + b('') + b(' if (loop != NULL)') + b(' *loop = state.loop;') + b('') + b(' pc = tp_proxy_pending_call_v1_new ((TpProxy *) proxy,') + b(' timeout_ms,') + b(' interface,') + b(' "%s",' % member) + b(' /* consume floating ref */') + b(' dbus_g_value_build_g_variant (&args_val),') + b(' G_VARIANT_TYPE ("(%s)"),' % (''.join(out_sig))) + b(' %s,' % reentrant_invoke) + b(' (void *) 1, /* any non-NULL pointer */') + b(' &state,') + b(' NULL,') + b(' NULL);') + b(' g_value_unset (&args_val);') + 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_interface(self, node): ifaces = node.getElementsByTagName('interface') @@ -1097,24 +941,6 @@ class Generator(object): signals = node.getElementsByTagName('signal') methods = node.getElementsByTagName('method') - if signals: - self.b('static inline void') - self.b('%s_add_signals_for_%s (DBusGProxy *proxy)' - % (self.prefix_lc, name.lower())) - self.b('{') - - if self.tp_proxy_api >= (0, 7, 6): - self.b(' if (!tp_proxy_dbus_g_proxy_claim_for_signal_adding ' - '(proxy))') - self.b(' return;') - - for signal in signals: - self.do_signal_add(signal) - - self.b('}') - self.b('') - self.b('') - for signal in signals: self.do_signal(name, signal) @@ -1137,6 +963,10 @@ class Generator(object): self.b(' * confused by seeing function definitions, so mark it as: */') self.b('/*<private_header>*/') self.b('') + # if we're splitting out re-entrant things, we want them marked + # private too + self.rh('/*<private_header>*/') + self.rb('/*<private_header>*/') nodes = self.dom.getElementsByTagName('node') nodes.sort(key=key_by_name) @@ -1144,47 +974,6 @@ class Generator(object): for node in nodes: self.do_interface(node) - if self.group is not None: - - self.b('/*') - self.b(' * %s_%s_add_signals:' % (self.prefix_lc, self.group)) - self.b(' * @self: the #TpProxy') - self.b(' * @quark: a quark whose string value is the interface') - self.b(' * name whose signals should be added') - self.b(' * @proxy: the D-Bus proxy to which to add the signals') - self.b(' * @unused: not used for anything') - self.b(' *') - self.b(' * Tell dbus-glib that @proxy has the signatures of all') - self.b(' * signals on the given interface, if it\'s one we') - self.b(' * support.') - self.b(' *') - 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('%s_%s_add_signals (TpProxy *self G_GNUC_UNUSED,' - % (self.prefix_lc, self.group)) - self.b(' guint quark,') - self.b(' DBusGProxy *proxy,') - self.b(' gpointer unused G_GNUC_UNUSED)') - - self.b('{') - - for node in nodes: - iface = node.getElementsByTagName('interface')[0] - self.iface_dbus = iface.getAttribute('name') - signals = node.getElementsByTagName('signal') - if not signals: - continue - name = node.getAttribute('name').replace('/', '').lower() - self.iface_uc = name.upper() - self.b(' if (quark == %s)' % self.get_iface_quark()) - self.b(' %s_add_signals_for_%s (proxy);' - % (self.prefix_lc, name)) - - self.b('}') - self.b('') - self.h('G_END_DECLS') self.h('') @@ -1192,6 +981,10 @@ class Generator(object): 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')) @@ -1205,7 +998,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-errors-check-gen.py b/tools/glib-errors-check-gen.py index fad261ece..3cc8a5afb 100644 --- a/tools/glib-errors-check-gen.py +++ b/tools/glib-errors-check-gen.py @@ -17,7 +17,6 @@ class Generator(object): print(' GEnumValue *value_by_name;') print(' GEnumValue *value_by_nick;') print('') - print(' g_type_init ();') print(' klass = g_type_class_ref (TP_TYPE_ERROR);') for error in self.errors.getElementsByTagNameNS(NS_TP, 'error'): diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py index c0ce20ddc..d5a786f35 100644 --- a/tools/glib-ginterface-gen.py +++ b/tools/glib-ginterface-gen.py @@ -26,28 +26,19 @@ import sys import os.path import xml.dom.minidom -from libtpcodegen import file_set_contents, key_by_name, u -from libglibcodegen import Signature, type_to_gtype, \ - NS_TP, dbus_gutils_wincaps_to_uscore +from libtpcodegen import file_set_contents, key_by_name, u, get_emits_changed +from libglibcodegen import (Signature, type_to_gtype, + NS_TP, dbus_gutils_wincaps_to_uscore, value_getter, + GDBusInterfaceInfo) 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 = [] @@ -83,6 +74,7 @@ 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): self.__header.append(s) @@ -114,15 +106,9 @@ class Generator(object): iface_emits_changed = get_emits_changed(interface) - self.b('static const DBusGObjectInfo _%s%s_object_info;' - % (self.prefix_, node_name_lc)) - self.b('') - methods = interface.getElementsByTagName('method') signals = interface.getElementsByTagName('signal') properties = interface.getElementsByTagName('property') - # Don't put properties in dbus-glib glue - glue_properties = [] self.b('struct _%s%sClass {' % (self.Prefix, node_name_mixed)) self.b(' GTypeInterface parent_class;') @@ -245,16 +231,75 @@ class Generator(object): ' (G_TYPE_INSTANCE_GET_INTERFACE((obj), %s, %sClass))' % (self.PREFIX_, node_name_uc, gtype, classname)) self.h('') - self.h('') base_init_code = [] + method_call_code = [] for method in methods: - self.do_method(method) + self.do_method(method, method_call_code) + + signal_table = [ + 'static const gchar * const _gsignals_%s[] = {' % + self.node_name_lc + ] for signal in signals: - base_init_code.extend(self.do_signal(signal)) + # we rely on this being in the same order as the interface info + self.do_signal(signal, in_base_init=base_init_code, + in_signal_table=signal_table) + + signal_table.append(' NULL') + signal_table.append('};') + signal_table.append('') + for line in signal_table: + self.b(line) + + # e.g. _interface_info_connection_interface_contact_info1 + for line in GDBusInterfaceInfo(node_name, interface, + '_interface_info_%s' % node_name_lc).to_lines(linkage='static'): + self.b(line) + self.b('') + self.b('static void') + self.b('_method_call_%s (GDBusConnection *connection,' % node_name_lc) + self.b(' const gchar *sender,') + self.b(' const gchar *object_path,') + self.b(' const gchar *interface_name,') + self.b(' const gchar *method_name,') + self.b(' GVariant *parameters,') + self.b(' GDBusMethodInvocation *invocation,') + self.b(' gpointer user_data)') + self.b('{') + + for line in method_call_code: + self.b(line) + + # Deliberately not using self.not_implemented_func here so that callers + # can distinguish between "you called Protocol.NormalizeContact() but + # that isn't implemented here" and "you called Protocol.Badger() + # which isn't even in the spec" if required. + self.b(' g_dbus_method_invocation_return_error (invocation,') + self.b(' G_DBUS_ERROR,') + self.b(' G_DBUS_ERROR_UNKNOWN_METHOD,') + self.b(' "Method not implemented");') + self.b('}') + self.b('') + self.b('static const GDBusInterfaceVTable _vtable_%s = {' % + node_name_lc) + self.b(' _method_call_%s,' % node_name_lc) + self.b(' NULL, /* get property */') + self.b(' NULL /* set property */') + self.b('};') + self.b('') + self.b('static const TpSvcInterfaceInfo _tp_interface_info_%s = {' % + node_name_lc) + self.b(' -1,') + self.b(' (GDBusInterfaceInfo *) &_interface_info_%s,' % node_name_lc) + self.b(' (GDBusInterfaceVTable *) &_vtable_%s,' % node_name_lc) + self.b(' (gchar **) _gsignals_%s' % node_name_lc) + self.b(' /* _future is implicitly zero-filled */') + self.b('};') + self.b('') self.b('static inline void') self.b('%s%s_base_init_once (gpointer klass G_GNUC_UNUSED)' % (self.prefix_, node_name_lc)) @@ -295,13 +340,6 @@ class Generator(object): self.b(' { 0, properties, NULL, NULL };') self.b('') - - self.b(' dbus_g_object_type_install_info (%s%s_get_type (),' - % (self.prefix_, node_name_lc)) - self.b(' &_%s%s_object_info);' - % (self.prefix_, node_name_lc)) - self.b('') - if properties: self.b(' interface.dbus_interface = g_quark_from_static_string ' '("%s");' % self.iface_name) @@ -317,6 +355,10 @@ class Generator(object): self.b('') + self.b(' tp_svc_interface_set_dbus_interface_info (%s,' + % (self.current_gtype)) + self.b(' &_tp_interface_info_%s);' % node_name_lc) + for s in base_init_code: self.b(s) self.b('}') @@ -338,100 +380,10 @@ class Generator(object): self.h('') - self.b('static const DBusGMethodInfo _%s%s_methods[] = {' - % (self.prefix_, node_name_lc)) - - method_blob, offsets = self.get_method_glue(methods) - - for method, offset in zip(methods, offsets): - self.do_method_glue(method, offset) - - if len(methods) == 0: - # empty arrays are a gcc extension, so put in a dummy member - self.b(" { NULL, NULL, 0 }") - - self.b('};') - self.b('') - - self.b('static const DBusGObjectInfo _%s%s_object_info = {' - % (self.prefix_, node_name_lc)) - self.b(' 0,') # version - self.b(' _%s%s_methods,' % (self.prefix_, node_name_lc)) - self.b(' %d,' % len(methods)) - self.b('"' + method_blob.replace('\0', '\\0') + '",') - self.b('"' + self.get_signal_glue(signals).replace('\0', '\\0') + '",') - self.b('"' + - self.get_property_glue(glue_properties).replace('\0', '\\0') + - '",') - self.b('};') - self.b('') - self.node_name_mixed = None self.node_name_lc = None self.node_name_uc = None - def get_method_glue(self, methods): - info = [] - offsets = [] - - for method in methods: - offsets.append(len(''.join(info))) - - info.append(self.iface_name + '\0') - info.append(method.getAttribute('name') + '\0') - - info.append('A\0') # async - - counter = 0 - for arg in method.getElementsByTagName('arg'): - out = arg.getAttribute('direction') == 'out' - - name = arg.getAttribute('name') - if not name: - assert out - name = 'arg%u' % counter - counter += 1 - - info.append(name + '\0') - - if out: - info.append('O\0') - else: - info.append('I\0') - - if out: - info.append('F\0') # not const - info.append('N\0') # not error or return - info.append(arg.getAttribute('type') + '\0') - - info.append('\0') - - return ''.join(info) + '\0', offsets - - def do_method_glue(self, method, offset): - lc_name = method.getAttribute('tp:name-for-bindings') - if method.getAttribute('name') != lc_name.replace('_', ''): - raise AssertionError('Method %s tp:name-for-bindings (%s) does ' - 'not match' % (method.getAttribute('name'), lc_name)) - lc_name = lc_name.lower() - - marshaller = 'g_cclosure_marshal_generic' - wrapper = self.prefix_ + self.node_name_lc + '_' + lc_name - - self.b(" { (GCallback) %s, %s, %d }," % (wrapper, marshaller, offset)) - - def get_signal_glue(self, signals): - info = [] - - for signal in signals: - info.append(self.iface_name) - info.append(signal.getAttribute('name')) - - return '\0'.join(info) + '\0\0' - - # the implementation can be the same - get_property_glue = get_signal_glue - def get_method_impl_names(self, method): dbus_method_name = method.getAttribute('name') @@ -445,11 +397,9 @@ class Generator(object): class_member_name) return (stub_name + '_impl', class_member_name + '_cb') - def do_method(self, method): + def do_method(self, method, method_call_code): assert self.node_name_mixed is not None - in_class = [] - # Examples refer to Thing.DoStuff (su) -> ii # DoStuff @@ -461,20 +411,20 @@ class Generator(object): 'not match' % (dbus_method_name, class_member_name)) class_member_name = class_member_name.lower() - # void tp_svc_thing_do_stuff (TpSvcThing *, const char *, guint, - # DBusGMethodInvocation *); + # tp_svc_thing_do_stuff (signature of GDBusInterfaceMethodCallFunc) stub_name = (self.prefix_ + self.node_name_lc + '_' + class_member_name) # typedef void (*tp_svc_thing_do_stuff_impl) (TpSvcThing *, - # const char *, guint, DBusGMethodInvocation); + # const char *, guint, GDBusMethodInvocation); impl_name = stub_name + '_impl' - # void tp_svc_thing_return_from_do_stuff (DBusGMethodInvocation *, + # void tp_svc_thing_return_from_do_stuff (GDBusMethodInvocation *, # gint, gint); ret_name = (self.prefix_ + self.node_name_lc + '_return_from_' + class_member_name) # Gather arguments in_args = [] + in_arg_value_getters = [] out_args = [] for i in method.getElementsByTagName('arg'): name = i.getAttribute('name') @@ -498,9 +448,22 @@ class Generator(object): struct = (ctype, name) if direction == 'in': - in_args.append(struct) + in_args.append((ctype, name)) + in_arg_value_getters.append(value_getter(gtype, marshaller)) else: - out_args.append(struct) + out_args.append((gtype, ctype, name)) + + # bits of _method_call_myiface + method_call_code.extend([ + ' if (g_strcmp0 (method_name, "%s") == 0)' % dbus_method_name, + ' {', + ' %s (connection, sender, object_path, interface_name, ' % + stub_name, + ' method_name, parameters, invocation, user_data);', + ' return;', + ' }', + '' + ]) # Implementation type declaration (in header, docs separated) self.d('/**') @@ -509,7 +472,7 @@ class Generator(object): for (ctype, name) in in_args: self.d(' * @%s: %s (FIXME, generate documentation)' % (name, ctype)) - self.d(' * @context: Used to return values or throw an error') + self.d(' * @invocation: Used to return values or throw an error') self.d(' *') self.d(' * The signature of an implementation of the D-Bus method') self.d(' * %s on interface %s.' % (dbus_method_name, self.iface_name)) @@ -519,37 +482,59 @@ class Generator(object): % (impl_name, self.Prefix, self.node_name_mixed)) for (ctype, name) in in_args: self.h(' %s%s,' % (ctype, name)) - self.h(' DBusGMethodInvocation *context);') - - # Class member (in class definition) - in_class.append(' %s %s;' % (impl_name, class_member_name)) + self.h(' GDBusMethodInvocation *invocation);') # Stub definition (in body only - it's static) self.b('static void') - self.b('%s (%s%s *self,' - % (stub_name, self.Prefix, self.node_name_mixed)) - for (ctype, name) in in_args: - self.b(' %s%s,' % (ctype, name)) - self.b(' DBusGMethodInvocation *context)') + self.b('%s (GDBusConnection *connection,' % stub_name) + self.b(' const gchar *sender,') + self.b(' const gchar *object_path,') + self.b(' const gchar *interface_name,') + self.b(' const gchar *method_name,') + self.b(' GVariant *parameters,') + self.b(' GDBusMethodInvocation *invocation,') + self.b(' gpointer user_data)') self.b('{') - self.b(' %s impl = (%s%s_GET_CLASS (self)->%s_cb);' - % (impl_name, self.PREFIX_, self.node_name_uc, class_member_name)) + self.b(' %s%s *self = %s%s (user_data);' + % (self.Prefix, self.node_name_mixed, self.PREFIX_, + self.node_name_uc)) + self.b(' %s%sClass *cls = %s%s_GET_CLASS (self);' + % (self.Prefix, self.node_name_mixed, self.PREFIX_, + self.node_name_uc)) + self.b(' %s impl = cls->%s_cb;' % (impl_name, class_member_name)) self.b('') self.b(' if (impl != NULL)') - tmp = ['self'] + [name for (ctype, name) in in_args] + ['context'] + tmp = ['self'] + [name for (ctype, name) in in_args] + ['invocation'] self.b(' {') - self.b(' (impl) (%s);' % ',\n '.join(tmp)) + + if in_args: + self.b(' GValue args_val = G_VALUE_INIT;') + self.b(' GValueArray *va;') + self.b('') + self.b(' dbus_g_value_parse_g_variant (parameters, &args_val);') + self.b(' va = g_value_get_boxed (&args_val);') + self.b('') + + self.b(' (impl) (self,') + + for i, getter in enumerate(in_arg_value_getters): + self.b(' %s (va->values + %d),' % (getter, i)) + + self.b(' invocation);') + + if in_args: + self.b(' g_value_unset (&args_val);') + self.b(' }') self.b(' else') self.b(' {') if self.not_implemented_func: - self.b(' %s (context);' % self.not_implemented_func) + self.b(' %s (invocation);' % self.not_implemented_func) else: - self.b(' GError e = { DBUS_GERROR, ') - self.b(' DBUS_GERROR_UNKNOWN_METHOD,') - self.b(' "Method not implemented" };') - self.b('') - self.b(' dbus_g_method_return_error (context, &e);') + self.b(' g_dbus_method_invocation_return_error (invocation,') + self.b(' G_DBUS_ERROR,') + self.b(' G_DBUS_ERROR_UNKNOWN_METHOD,') + self.b(' "Method not implemented");') self.b(' }') self.b('}') self.b('') @@ -581,44 +566,59 @@ class Generator(object): self.b('}') self.b('') - # Return convenience function (static inline, in header) + # Return convenience function self.d('/**') self.d(' * %s:' % ret_name) - self.d(' * @context: The D-Bus method invocation context') - for (ctype, name) in out_args: + self.d(' * @invocation: The D-Bus method invocation context') + for (gtype, ctype, name) in out_args: self.d(' * @%s: %s (FIXME, generate documentation)' % (name, ctype)) self.d(' *') - self.d(' * Return successfully by calling dbus_g_method_return().') - self.d(' * This inline function exists only to provide type-safety.') + self.d(' * Return successfully by calling g_dbus_method_invocation_return_value().') self.d(' */') self.d('') - tmp = (['DBusGMethodInvocation *context'] + - [ctype + name for (ctype, name) in out_args]) - self.h('static inline') - self.h('/* this comment is to stop gtkdoc realising this is static */') + tmp = (['GDBusMethodInvocation *invocation'] + + [ctype + name for (gtype, ctype, name) in out_args]) self.h(('void %s (' % ret_name) + (',\n '.join(tmp)) + ');') - self.h('static inline void') - self.h(('%s (' % ret_name) + (',\n '.join(tmp)) + ')') - self.h('{') - tmp = ['context'] + [name for (ctype, name) in out_args] - self.h(' dbus_g_method_return (' + ',\n '.join(tmp) + ');') - self.h('}') - self.h('') - return in_class + self.b('void') + self.b(('%s (' % ret_name) + (',\n '.join(tmp)) + ')') + self.b('{') + self.b(' GValueArray *tmp = tp_value_array_build (%d,' % len(out_args)) + + for (gtype, ctype, name) in out_args: + self.b(' %s, %s,' % (gtype, name)) + + self.b(' G_TYPE_INVALID);') + self.b(' GValue args_val = G_VALUE_INIT;') + self.b('') + + self.b(' g_value_init (&args_val, ' + 'dbus_g_type_get_struct ("GValueArray",') + + for (gtype, ctype, name) in out_args: + self.b(' %s,' % gtype) + + self.b(' G_TYPE_INVALID));') + + self.b(' g_value_take_boxed (&args_val, tmp);') + + self.b(' g_dbus_method_invocation_return_value (invocation,') + self.b(' /* consume floating ref */') + self.b(' dbus_g_value_build_g_variant (&args_val));') + self.b(' g_value_unset (&args_val);') + self.b('}') + self.b('') def get_signal_const_entry(self, signal): assert self.node_name_uc is not None return ('SIGNAL_%s_%s' % (self.node_name_uc, signal.getAttribute('name'))) - def do_signal(self, signal): + def do_signal(self, signal, in_base_init, in_signal_table): assert self.node_name_mixed is not None - in_base_init = [] - # for signal: Thing::StuffHappened (s, u) # we want to emit: # void tp_svc_thing_emit_stuff_happened (gpointer instance, @@ -716,7 +716,7 @@ class Generator(object): in_base_init.append(' %s);' % ',\n '.join(tmp)) in_base_init.append('') - return in_base_init + in_signal_table.append(' "%s",' % signal_name) def have_properties(self, nodes): for node in nodes: @@ -730,12 +730,9 @@ class Generator(object): nodes.sort(key=key_by_name) self.h('#include <glib-object.h>') + self.h('#include <gio/gio.h>') self.h('#include <dbus/dbus-glib.h>') - for header in self.headers: - self.h('#include %s' % header) - self.h('') - self.h('') self.h('G_BEGIN_DECLS') self.h('') @@ -743,6 +740,19 @@ class Generator(object): self.b('#include "%s.h"' % self.basename) self.b('') + if self.allow_single_include: + self.b('#include <telepathy-glib/core-svc-interface.h>') + self.b('#include <telepathy-glib/dbus.h>') + self.b('#include <telepathy-glib/dbus-properties-mixin.h>') + self.b('#include <telepathy-glib/util.h>') + else: + self.b('#include <telepathy-glib/telepathy-glib.h>') + self.b('') + + for header in self.headers: + self.b('#include %s' % header) + self.b('') + for node in nodes: self.do_node(node) @@ -777,9 +787,9 @@ options: --not-implemented-func='symbol' Set action when methods not implemented in the interface vtable are called. symbol must have signature - void symbol (DBusGMethodInvocation *context) + void symbol (GDBusMethodInvocation *invocation) and return some sort of "not implemented" error via - dbus_g_method_return_error (context, ...) + e.g. g_dbus_method_invocation_return_error """) sys.exit(1) @@ -791,7 +801,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] @@ -804,6 +815,7 @@ if __name__ == '__main__': end_headers = [] not_implemented_func = '' allow_havoc = False + allow_single_include = False for option, value in options: if option == '--filename': @@ -822,6 +834,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]) @@ -829,4 +843,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/libglibcodegen.py b/tools/libglibcodegen.py index 0b703a5a8..5cd005853 100644 --- a/tools/libglibcodegen.py +++ b/tools/libglibcodegen.py @@ -47,59 +47,6 @@ def dbus_gutils_wincaps_to_uscore(s): ret += c return ret - -def signal_to_marshal_type(signal): - """ - return a list of strings indicating the marshalling type for this signal. - """ - - mtype=[] - for i in signal.getElementsByTagName("arg"): - name =i.getAttribute("name") - type = i.getAttribute("type") - mtype.append(type_to_gtype(type)[2]) - - return mtype - - -_glib_marshallers = ['VOID', 'BOOLEAN', 'CHAR', 'UCHAR', 'INT', - 'STRING', 'UINT', 'LONG', 'ULONG', 'ENUM', 'FLAGS', 'FLOAT', - 'DOUBLE', 'STRING', 'PARAM', 'BOXED', 'POINTER', 'OBJECT', - 'UINT_POINTER'] - - -def signal_to_marshal_name(signal, prefix): - - mtype = signal_to_marshal_type(signal) - if len(mtype): - name = '_'.join(mtype) - else: - name = 'VOID' - - if name in _glib_marshallers: - return 'g_cclosure_marshal_VOID__' + name - else: - return prefix + '_marshal_VOID__' + name - - -def method_to_glue_marshal_name(method, prefix): - - mtype = [] - for i in method.getElementsByTagName("arg"): - if i.getAttribute("direction") != "out": - type = i.getAttribute("type") - mtype.append(type_to_gtype(type)[2]) - - mtype.append('POINTER') - - name = '_'.join(mtype) - - if name in _glib_marshallers: - return 'g_cclosure_marshal_VOID__' + name - else: - return prefix + '_marshal_VOID__' + name - - def type_to_gtype(s): if s == 'y': #byte return ("guchar ", "G_TYPE_UCHAR","UCHAR", False) @@ -171,25 +118,227 @@ def type_to_gtype(s): # we just don't know .. 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) +def value_getter(gtype, marshaller): + if marshaller == 'BOXED': + return 'g_value_get_boxed' + elif gtype == 'G_TYPE_STRING': + return 'g_value_get_string' elif gtype == 'G_TYPE_UCHAR': - return 'g_value_set_uchar (%s, %s);' % (gvaluep, name) + return 'g_value_get_uchar' 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) + return 'g_value_get_boolean' 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) + return 'g_value_get_uint' + elif gtype == 'G_TYPE_INT': + return 'g_value_get_int' elif gtype == 'G_TYPE_UINT64': - return 'g_value_set_uint64 (%s, %s);' % (gvaluep, name) + return 'g_value_get_uint64' + elif gtype == 'G_TYPE_INT64': + return 'g_value_get_int64' elif gtype == 'G_TYPE_DOUBLE': - return 'g_value_set_double (%s, %s);' % (gvaluep, name) + return 'g_value_get_double' else: - raise AssertionError("Don't know how to put %s in a GValue" % gtype) + raise AssertionError("Don't know how to get %s from a GValue" % marshaller) + +class GDBusInterfaceInfo(object): + def __init__(self, ugly_name, iface_element, c_name): + self.ugly_name = ugly_name + self.mixed_name = ugly_name.replace('_', '') + self.lc_name = ugly_name.lower() + self.uc_name = ugly_name.upper() + self.c_name = c_name + self.iface_element = iface_element + + self.method_elements = iface_element.getElementsByTagName('method') + self.signal_elements = iface_element.getElementsByTagName('signal') + self.property_elements = iface_element.getElementsByTagName('property') + + def do_methods(self): + method_args = [ + ] + method_in_arg_pointers = [ + ] + method_out_arg_pointers = [ + ] + methods = [ + ] + method_pointers = [ + 'static const GDBusMethodInfo *const method_pointers_%s[] = {' + % self.c_name, + ] + + for meth in self.method_elements: + lc_name = meth.getAttribute('tp:name-for-bindings') + if meth.getAttribute('name') != lc_name.replace('_', ''): + raise AssertionError('Method %s tp:name-for-bindings (%s) ' + 'does not match' % + (meth.getAttribute('name'), lc_name)) + lc_name = lc_name.lower() + + c_name = 'method_%s_%s' % (self.c_name, lc_name) + + method_in_arg_pointers.append('static const GDBusArgInfo *const ' + 'method_in_arg_pointers_%s_%s[] = {' % + (self.c_name, lc_name)) + method_out_arg_pointers.append('static const GDBusArgInfo *const ' + 'method_out_arg_pointers_%s_%s[] = {' + % (self.c_name, lc_name)) + + for i, arg in enumerate(meth.getElementsByTagName('arg')): + name = arg.getAttribute('name') + if not name: + name = 'arg%d' % i + + method_args.append('static const GDBusArgInfo ' + 'method_arg_%s_%s_%d = {' % (self.c_name, lc_name, i)) + method_args.append(' -1, /* refcount */') + method_args.append(' "%s",' % name) + method_args.append(' "%s",' % arg.getAttribute('type')) + method_args.append(' NULL /* annotations */') + method_args.append('};') + + if arg.getAttribute('direction') == 'out': + method_out_arg_pointers.append(' &method_arg_%s_%s_%d,' % + (self.c_name, lc_name, i)) + else: + method_in_arg_pointers.append(' &method_arg_%s_%s_%d,' % + (self.c_name, lc_name, i)) + + method_in_arg_pointers.append(' NULL') + method_in_arg_pointers.append('};') + method_out_arg_pointers.append(' NULL') + method_out_arg_pointers.append('};') + + methods.append('static const GDBusMethodInfo %s = {' % c_name) + methods.append(' -1, /* refcount */') + methods.append(' "%s",' % meth.getAttribute("name")) + methods.append(' (GDBusArgInfo **) method_in_arg_pointers_%s_%s,' + % (self.c_name, lc_name)) + methods.append(' (GDBusArgInfo **) method_out_arg_pointers_%s_%s,' + % (self.c_name, lc_name)) + methods.append(' NULL /* annotations */') + methods.append('};') + + method_pointers.append(' &%s,' % c_name) + + method_pointers.append(' NULL') + method_pointers.append('};') + + return (method_args + method_in_arg_pointers + + method_out_arg_pointers + methods + method_pointers) + + def do_signals(self): + signal_args = [ + ] + signal_arg_pointers = [ + ] + signals = [ + ] + signal_pointers = [ + 'static const GDBusSignalInfo *const signal_pointers_%s[] = {' + % self.c_name, + ] + + for sig in self.signal_elements: + lc_name = sig.getAttribute('tp:name-for-bindings') + if sig.getAttribute('name') != lc_name.replace('_', ''): + raise AssertionError('Signal %s tp:name-for-bindings (%s) ' + 'does not match' % + (sig.getAttribute('name'), lc_name)) + lc_name = lc_name.lower() + + c_name = 'signal_%s_%s' % (self.c_name, lc_name) + + signal_arg_pointers.append('static const GDBusArgInfo *const ' + 'signal_arg_pointers_%s_%s[] = {' % (self.c_name, lc_name)) + + for i, arg in enumerate(sig.getElementsByTagName('arg')): + name = arg.getAttribute('name') + if not name: + name = 'arg%d' % i + + signal_args.append('static const GDBusArgInfo ' + 'signal_arg_%s_%s_%d = {' % (self.c_name, lc_name, i)) + signal_args.append(' -1, /* refcount */') + signal_args.append(' "%s",' % name) + signal_args.append(' "%s",' % arg.getAttribute('type')) + signal_args.append(' NULL /* annotations */') + signal_args.append('};') + + signal_arg_pointers.append(' &signal_arg_%s_%s_%d,' % + (self.c_name, lc_name, i)) + + signal_arg_pointers.append(' NULL') + signal_arg_pointers.append('};') + + signals.append('static const GDBusSignalInfo %s = {' % c_name) + signals.append(' -1, /* refcount */') + signals.append(' "%s",' % sig.getAttribute("name")) + signals.append(' (GDBusArgInfo **) signal_arg_pointers_%s_%s,' + % (self.c_name, lc_name)) + signals.append(' NULL /* annotations */') + signals.append('};') + + signal_pointers.append(' &%s,' % c_name) + + signal_pointers.append(' NULL') + signal_pointers.append('};') + + return signal_args + signal_arg_pointers + signals + signal_pointers + + def do_properties(self): + properties = [ + ] + property_pointers = [ + 'static const GDBusPropertyInfo *const property_pointers_%s[] = {' + % self.c_name, + ] + + for prop in self.property_elements: + access = prop.getAttribute('access') + flags = { + 'read': 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE', + 'write': 'G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE', + 'readwrite': + 'G_DBUS_PROPERTY_INFO_FLAGS_READABLE | ' + 'G_DBUS_PROPERTY_INFO_FLAGS_WRITABLE', + }[access] + + lc_name = prop.getAttribute('tp:name-for-bindings') + if prop.getAttribute('name') != lc_name.replace('_', ''): + raise AssertionError('Property %s tp:name-for-bindings (%s) ' + 'does not match' % + (prop.getAttribute('name'), lc_name)) + lc_name = lc_name.lower() + + c_name = 'property_%s_%s' % (self.c_name, lc_name) + + properties.append('static const GDBusPropertyInfo %s = {' % c_name) + properties.append(' -1, /* refcount */') + properties.append(' "%s",' % prop.getAttribute("name")) + properties.append(' "%s",' % prop.getAttribute("type")) + properties.append(' %s,' % flags) + # FIXME: add annotations? + properties.append(' NULL /* annotations */') + properties.append('};') + + property_pointers.append(' &%s,' % c_name) + + property_pointers.append(' NULL') + property_pointers.append('};') + + return properties + property_pointers + + def to_lines(self, linkage='static'): + return (self.do_methods() + + self.do_signals() + + self.do_properties() + [ + '%s const GDBusInterfaceInfo %s = {' % (linkage, self.c_name), + ' -1, /* refcount */', + ' "%s",' % self.iface_element.getAttribute('name'), + ' (GDBusMethodInfo **) method_pointers_%s,' % self.c_name, + ' (GDBusSignalInfo **) signal_pointers_%s,' % self.c_name, + ' (GDBusPropertyInfo **) property_pointers_%s,' % self.c_name, + ' NULL /* annotations */', + '};' + ]) diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py index 99de66340..021a82be4 100644 --- a/tools/libtpcodegen.py +++ b/tools/libtpcodegen.py @@ -245,3 +245,13 @@ class Signature(str): def xml_escape(s): s = s.replace('&', '&').replace("'", ''').replace('"', '"') return s.replace('<', '<').replace('>', '>') + +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 |