aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/Makefile.am12
-rw-r--r--tools/Makefile.am14
-rw-r--r--tools/c-constants-gen.py84
-rw-r--r--tools/check-coding-style.mk4
-rw-r--r--tools/git-which-branch.sh25
-rw-r--r--tools/glib-client-gen.py283
-rw-r--r--tools/glib-errors-check-gen.py58
-rw-r--r--tools/glib-errors-enum-body-gen.py62
-rw-r--r--tools/glib-errors-enum-header-gen.py75
-rw-r--r--tools/glib-errors-str-gen.py82
-rw-r--r--tools/glib-ginterface-gen.py293
-rw-r--r--tools/glib-gtypes-generator.py214
-rw-r--r--tools/glib-interfaces-gen.py138
-rw-r--r--tools/gobject-foo.py23
-rw-r--r--tools/identity.xsl7
-rw-r--r--tools/libglibcodegen.py5
-rw-r--r--tools/libtpcodegen.py36
-rw-r--r--tools/make-release-mail.py76
-rw-r--r--tools/manager-file.py175
-rw-r--r--tools/shave.mk1
-rw-r--r--tools/telepathy-glib.supp390
-rwxr-xr-xtools/test-wrapper.sh30
-rw-r--r--tools/valgrind.mk13
-rw-r--r--tools/with-session-bus.sh10
-rw-r--r--tools/xincludator.py39
25 files changed, 1623 insertions, 526 deletions
diff --git a/extensions/Makefile.am b/extensions/Makefile.am
index ef8b751fb..0d540f5fa 100644
--- a/extensions/Makefile.am
+++ b/extensions/Makefile.am
@@ -59,10 +59,9 @@ XSLTPROCFLAGS = --nonet --novalid
# Generated files which can be generated for all categories simultaneously
-_gen/all.xml: all.xml $(wildcard *.xml)
+_gen/all.xml: all.xml $(wildcard *.xml) $(tools_dir)/xincludator.py
@$(mkdir_p) _gen
- $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) --xinclude $(tools_dir)/identity.xsl \
- $< > $@
+ $(AM_V_GEN)$(PYTHON) $(tools_dir)/xincludator.py $< > $@
extensions.html: _gen/all.xml $(tools_dir)/doc-generator.xsl
$(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) \
@@ -95,7 +94,7 @@ _gen/enums.h: _gen/all.xml \
$(tools_dir)/c-constants-gen.py
$(AM_V_GEN)$(PYTHON) $(tools_dir)/c-constants-gen.py \
Emp \
- $< > $@
+ $< _gen/enums
_gen/interfaces-body.h _gen/interfaces.h: _gen/all.xml \
$(tools_dir)/glib-interfaces-gen.py
@@ -106,10 +105,9 @@ _gen/interfaces-body.h _gen/interfaces.h: _gen/all.xml \
# subclass you want to use with --subclass will need to have its own category,
# although you can subdivide further if you want.
-_gen/misc.xml: misc.xml $(wildcard *.xml)
+_gen/misc.xml: misc.xml $(wildcard *.xml) $(tools_dir)/xincludator.py
@$(mkdir_p) _gen
- $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) --xinclude $(tools_dir)/identity.xsl \
- $< > $@
+ $(AM_V_GEN)$(PYTHON) $(tools_dir)/xincludator.py $< > $@
_gen/cli-misc-body.h _gen/cli-misc.h: _gen/misc.xml \
$(tools_dir)/glib-client-gen.py
diff --git a/tools/Makefile.am b/tools/Makefile.am
index c9ac350ee..96cc60f58 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -14,23 +14,29 @@ EXTRA_DIST = \
check-whitespace.sh \
doc-generator.xsl \
flymake.mk \
+ git-which-branch.sh \
glib-client-gen.py \
glib-client-marshaller-gen.py \
- glib-errors-enum-body-gen.py \
- glib-errors-enum-header-gen.py \
+ glib-errors-check-gen.py \
+ glib-errors-str-gen.py \
glib-ginterface-gen.py \
glib-gtypes-generator.py \
glib-interfaces-gen.py \
glib-signals-marshal-gen.py \
gobject-foo.py \
- identity.xsl \
lcov.am \
libtpcodegen.py \
libglibcodegen.py \
+ make-release-mail.py \
make-version-script.py \
+ manager-file.py \
+ shave.mk \
telepathy.am \
+ telepathy-glib.supp \
telepathy-glib-env.in \
- with-session-bus.sh
+ test-wrapper.sh \
+ with-session-bus.sh \
+ xincludator.py
CLEANFILES = libtpcodegen.pyc libtpcodegen.pyo libglibcodegen.pyc libglibcodegen.pyo $(noinst_SCRIPTS)
diff --git a/tools/c-constants-gen.py b/tools/c-constants-gen.py
index f338257aa..188ab82ac 100644
--- a/tools/c-constants-gen.py
+++ b/tools/c-constants-gen.py
@@ -3,34 +3,43 @@
from sys import argv, stdout, stderr
import xml.dom.minidom
-from libglibcodegen import NS_TP, camelcase_to_upper, get_docstring, \
+from libglibcodegen import NS_TP, get_docstring, \
get_descendant_text, get_by_path
class Generator(object):
- def __init__(self, prefix, dom):
+ def __init__(self, prefix, dom, output_base):
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')
+
def __call__(self):
self.do_header()
self.do_body()
self.do_footer()
+ def write(self, code):
+ self.__header.write(code.encode('utf-8'))
+
+ def d(self, code):
+ self.__docs.write(code.encode('utf-8'))
+
# Header
def do_header(self):
- stdout.write('/* Generated from ')
- stdout.write(get_descendant_text(get_by_path(self.spec, 'title')))
+ self.write('/* Generated from ')
+ self.write(get_descendant_text(get_by_path(self.spec, 'title')))
version = get_by_path(self.spec, "version")
if version:
- stdout.write(', version ' + get_descendant_text(version))
- stdout.write('\n\n')
+ self.write(', version ' + get_descendant_text(version))
+ self.write('\n\n')
for copyright in get_by_path(self.spec, 'copyright'):
- stdout.write(get_descendant_text(copyright))
- stdout.write('\n')
- stdout.write(get_descendant_text(get_by_path(self.spec, 'license')))
- stdout.write('\n')
- stdout.write(get_descendant_text(get_by_path(self.spec, 'docstring')))
- stdout.write("""
+ self.write(get_descendant_text(copyright))
+ self.write('\n')
+ self.write(get_descendant_text(get_by_path(self.spec, 'license')))
+ self.write('\n')
+ self.write(get_descendant_text(get_by_path(self.spec, 'docstring')))
+ self.write("""
*/
#ifdef __cplusplus
@@ -51,28 +60,30 @@ extern "C" {
value_prefix = flags.getAttribute('singular') or \
flags.getAttribute('value-prefix') or \
flags.getAttribute('name')
- stdout.write("""\
+ self.d("""\
/**
*
%s:
""" % (self.prefix + name).replace('_', ''))
for flag in get_by_path(flags, 'flag'):
self.do_gtkdoc(flag, value_prefix)
- stdout.write(' *\n')
+ self.d(' *\n')
docstrings = get_by_path(flags, 'docstring')
if docstrings:
- stdout.write("""\
+ self.d("""\
* <![CDATA[%s]]>
*
""" % get_descendant_text(docstrings).replace('\n', ' '))
- stdout.write("""\
+ self.d("""\
* Bitfield/set of flags generated from the Telepathy specification.
*/
-typedef enum {
""")
+
+ self.write("typedef enum /*< flags >*/ {\n")
+
for flag in get_by_path(flags, 'flag'):
self.do_val(flag, value_prefix)
- stdout.write("""\
+ self.write("""\
} %s;
""" % (self.prefix + name).replace('_', ''))
@@ -84,7 +95,7 @@ typedef enum {
enum.getAttribute('name')
name_plural = enum.getAttribute('plural') or \
enum.getAttribute('name') + 's'
- stdout.write("""\
+ self.d("""\
/**
*
%s:
@@ -92,28 +103,35 @@ typedef enum {
vals = get_by_path(enum, 'enumvalue')
for val in vals:
self.do_gtkdoc(val, value_prefix)
- stdout.write(' *\n')
+ self.d(' *\n')
docstrings = get_by_path(enum, 'docstring')
if docstrings:
- stdout.write("""\
+ self.d("""\
* <![CDATA[%s]]>
*
""" % get_descendant_text(docstrings).replace('\n', ' '))
- stdout.write("""\
+ self.d("""\
* Bitfield/set of flags generated from the Telepathy specification.
*/
-typedef enum {
""")
+
+ self.write("typedef enum {\n")
+
for val in vals:
self.do_val(val, value_prefix)
- stdout.write("""\
-} %(mixed-name)s;
+ self.write("} %s;\n" % (self.prefix + name).replace('_', ''))
+ self.d("""\
/**
* NUM_%(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(),
+ 'last-val' : vals[-1].getAttribute('value')})
+
+ self.write("""\
#define NUM_%(upper-plural)s (%(last-val)s+1)
""" % {'mixed-name' : (self.prefix + name).replace('_', ''),
@@ -127,20 +145,20 @@ typedef enum {
(suffix or name)).upper()
assert not (name and suffix) or name == suffix, \
'Flag/enumvalue name %s != suffix %s' % (name, suffix)
- stdout.write(' %s = %s,\n' % (use_name, val.getAttribute('value')))
+ self.write(' %s = %s,\n' % (use_name, val.getAttribute('value')))
def do_gtkdoc(self, node, value_prefix):
- stdout.write(' * @')
- stdout.write((self.prefix + value_prefix + '_' +
+ self.d(' * @')
+ self.d((self.prefix + value_prefix + '_' +
node.getAttribute('suffix')).upper())
- stdout.write(': <![CDATA[')
+ self.d(': <![CDATA[')
docstring = get_by_path(node, 'docstring')
- stdout.write(get_descendant_text(docstring).replace('\n', ' '))
- stdout.write(']]>\n')
+ self.d(get_descendant_text(docstring).replace('\n', ' '))
+ self.d(']]>\n')
# Footer
def do_footer(self):
- stdout.write("""
+ self.write("""
#ifdef __cplusplus
}
#endif
@@ -148,4 +166,4 @@ typedef enum {
if __name__ == '__main__':
argv = argv[1:]
- Generator(argv[0], xml.dom.minidom.parse(argv[1]))()
+ Generator(argv[0], xml.dom.minidom.parse(argv[1]), argv[2])()
diff --git a/tools/check-coding-style.mk b/tools/check-coding-style.mk
index 3fc92fc8d..1c0a60f66 100644
--- a/tools/check-coding-style.mk
+++ b/tools/check-coding-style.mk
@@ -3,12 +3,12 @@ check-coding-style:
if test -n "$(check_misc_sources)"; then \
tools_dir=$(top_srcdir)/tools \
sh $(top_srcdir)/tools/check-misc.sh \
- $(check_misc_sources) || fail=1; \
+ $(addprefix $(srcdir)/,$(check_misc_sources)) || fail=1; \
fi; \
if test -n "$(check_c_sources)"; then \
tools_dir=$(top_srcdir)/tools \
sh $(top_srcdir)/tools/check-c-style.sh \
- $(check_c_sources) || fail=1; \
+ $(addprefix $(srcdir)/,$(check_c_sources)) || fail=1; \
fi;\
if test yes = "$(ENABLE_CODING_STYLE_CHECKS)"; then \
exit "$$fail";\
diff --git a/tools/git-which-branch.sh b/tools/git-which-branch.sh
new file mode 100644
index 000000000..b96b5d5e2
--- /dev/null
+++ b/tools/git-which-branch.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+# git-which-branch.sh - output the name of the current git branch
+#
+# The canonical location of this program is the telepathy-spec tools/
+# directory, please synchronize any changes with that copy.
+#
+# Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+
+default="$1"
+if { ref="`git symbolic-ref HEAD 2>/dev/null`"; }; then
+ echo ${ref#refs/heads/}
+ exit 0
+fi
+
+if test -n "$default"; then
+ echo "$default" >/dev/null
+ exit 0
+fi
+
+echo "no git branch found" >&2
+exit 1
diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py
index 701fcafeb..6b0bdeba1 100644
--- a/tools/glib-client-gen.py
+++ b/tools/glib-client-gen.py
@@ -28,7 +28,7 @@ import xml.dom.minidom
from getopt import gnu_getopt
from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \
- camelcase_to_lower, get_docstring, xml_escape
+ get_docstring, xml_escape, get_deprecated
NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
@@ -39,6 +39,7 @@ class Generator(object):
self.dom = dom
self.__header = []
self.__body = []
+ self.__docs = []
self.prefix_lc = prefix.lower()
self.prefix_uc = prefix.upper()
@@ -55,6 +56,11 @@ 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.deprecate_reentrant = opts.get('--deprecate-reentrant', None)
+ self.deprecation_attribute = opts.get('--deprecation-attribute',
+ 'G_GNUC_DEPRECATED')
def h(self, s):
if isinstance(s, unicode):
@@ -66,6 +72,11 @@ class Generator(object):
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 get_iface_quark(self):
assert self.iface_dbus is not None
assert self.iface_uc is not None
@@ -78,7 +89,11 @@ class Generator(object):
iface_lc = iface.lower()
member = signal.getAttribute('name')
- member_lc = camelcase_to_lower(member)
+ member_lc = signal.getAttribute('tp:name-for-bindings')
+ if member != member_lc.replace('_', ''):
+ raise AssertionError('Signal %s tp:name-for-bindings (%s) does '
+ 'not match' % (member, member_lc))
+ member_lc = member_lc.lower()
member_uc = member_lc.upper()
arg_count = 0
@@ -114,25 +129,27 @@ class Generator(object):
# guint arg_handle, gboolean arg_suppress_handler,
# gpointer user_data, GObject *weak_object);
- self.b('/**')
- self.b(' * %s:' % callback_name)
- self.b(' * @proxy: The proxy on which %s_%s_connect_to_%s ()'
+ self.d('/**')
+ self.d(' * %s:' % callback_name)
+ self.d(' * @proxy: The proxy on which %s_%s_connect_to_%s ()'
% (self.prefix_lc, iface_lc, member_lc))
- self.b(' * was called')
+ self.d(' * was called')
for arg in args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- self.b(' * @%s: %s' % (name,
+ self.d(' * @%s: %s' % (name,
xml_escape(get_docstring(elt) or '(Undocumented)')))
- self.b(' * @user_data: User-supplied data')
- self.b(' * @weak_object: User-supplied weakly referenced object')
- self.b(' *')
- self.b(' * Represents the signature of a callback for the signal %s.'
+ self.d(' * @user_data: User-supplied data')
+ self.d(' * @weak_object: User-supplied weakly referenced object')
+ self.d(' *')
+ self.d(' * Represents the signature of a callback for the signal %s.'
% member)
- self.b(' */')
+ self.d(' */')
+ self.d('')
+
self.h('typedef void (*%s) (%sproxy,'
% (callback_name, self.proxy_cls))
@@ -281,31 +298,33 @@ class Generator(object):
# emitted the 'invalidated' signal, or because the weakly referenced
# object has gone away.
- self.b('/**')
- self.b(' * %s_%s_connect_to_%s:'
+ self.d('/**')
+ self.d(' * %s_%s_connect_to_%s:'
% (self.prefix_lc, iface_lc, member_lc))
- self.b(' * @proxy: %s' % self.proxy_doc)
- self.b(' * @callback: Callback to be called when the signal is')
- self.b(' * received')
- self.b(' * @user_data: User-supplied data for the callback')
- self.b(' * @destroy: Destructor for the user-supplied data, which')
- self.b(' * will be called when this signal is disconnected, or')
- self.b(' * before this function returns %NULL')
- self.b(' * @weak_object: A #GObject which will be weakly referenced; ')
- self.b(' * if it is destroyed, this callback will automatically be')
- self.b(' * disconnected')
- self.b(' * @error: If not %NULL, used to raise an error if %NULL is')
- self.b(' * returned')
- self.b(' *')
- self.b(' * Connect a handler to the signal %s.' % member)
- self.b(' *')
- self.b(' * %s' % xml_escape(get_docstring(signal) or '(Undocumented)'))
- self.b(' *')
- self.b(' * Returns: a #TpProxySignalConnection containing all of the')
- self.b(' * above, which can be used to disconnect the signal; or')
- self.b(' * %NULL if the proxy does not have the desired interface')
- self.b(' * or has become invalid.')
- self.b(' */')
+ self.d(' * @proxy: %s' % self.proxy_doc)
+ self.d(' * @callback: Callback to be called when the signal is')
+ self.d(' * received')
+ self.d(' * @user_data: User-supplied data for the callback')
+ self.d(' * @destroy: Destructor for the user-supplied data, which')
+ self.d(' * will be called when this signal is disconnected, or')
+ self.d(' * before this function returns %NULL')
+ self.d(' * @weak_object: A #GObject which will be weakly referenced; ')
+ self.d(' * if it is destroyed, this callback will automatically be')
+ self.d(' * disconnected')
+ self.d(' * @error: If not %NULL, used to raise an error if %NULL is')
+ self.d(' * returned')
+ self.d(' *')
+ self.d(' * Connect a handler to the signal %s.' % member)
+ self.d(' *')
+ self.d(' * %s' % xml_escape(get_docstring(signal) or '(Undocumented)'))
+ self.d(' *')
+ self.d(' * Returns: a #TpProxySignalConnection containing all of the')
+ self.d(' * above, which can be used to disconnect the signal; or')
+ self.d(' * %NULL if the proxy does not have the desired interface')
+ self.d(' * or has become invalid.')
+ 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(' %s callback,' % callback_name)
@@ -313,6 +332,7 @@ class Generator(object):
self.h(' GDestroyNotify destroy,')
self.h(' GObject *weak_object,')
self.h(' GError **error);')
+ self.h('')
self.b('TpProxySignalConnection *')
self.b('%s_%s_connect_to_%s (%sproxy,'
@@ -352,13 +372,15 @@ class Generator(object):
self.b('}')
self.b('')
- self.h('')
-
def do_method(self, iface, method):
iface_lc = iface.lower()
member = method.getAttribute('name')
- member_lc = camelcase_to_lower(member)
+ member_lc = method.getAttribute('tp:name-for-bindings')
+ if member != member_lc.replace('_', ''):
+ raise AssertionError('Method %s tp:name-for-bindings (%s) does '
+ 'not match' % (member, member_lc))
+ member_lc = member_lc.lower()
member_uc = member_lc.upper()
in_count = 0
@@ -401,27 +423,35 @@ class Generator(object):
# gpointer user_data,
# GObject *weak_object);
- self.b('/**')
- self.b(' * %s_%s_callback_for_%s:'
+ self.d('/**')
+ self.d(' * %s_%s_callback_for_%s:'
% (self.prefix_lc, iface_lc, member_lc))
- self.b(' * @proxy: the proxy on which the call was made')
+ self.d(' * @proxy: the proxy on which the call was made')
for arg in out_args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- self.b(' * @%s: Used to return an \'out\' argument if @error is '
+ self.d(' * @%s: Used to return an \'out\' argument if @error is '
'%%NULL: %s'
% (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
- self.b(' * @error: %NULL on success, or an error on failure')
- self.b(' * @user_data: user-supplied data')
- self.b(' * @weak_object: user-supplied object')
- self.b(' *')
- self.b(' * Signature of the callback called when a %s method call'
+ self.d(' * @error: %NULL on success, or an error on failure')
+ self.d(' * @user_data: user-supplied data')
+ self.d(' * @weak_object: user-supplied object')
+ self.d(' *')
+ self.d(' * Signature of the callback called when a %s method call'
% member)
- self.b(' * succeeds or fails.')
- self.b(' */')
+ self.d(' * succeeds or fails.')
+
+ deprecated = method.getElementsByTagName('tp:deprecated')
+ if deprecated:
+ d = deprecated[0]
+ self.d(' *')
+ self.d(' * Deprecated: %s' % xml_escape(get_deprecated(d)))
+
+ self.d(' */')
+ self.d('')
callback_name = '%s_%s_callback_for_%s' % (self.prefix_lc, iface_lc,
member_lc)
@@ -646,42 +676,51 @@ class Generator(object):
% (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
self.h(' gint timeout_ms,')
- self.b('/**')
- self.b(' * %s_%s_call_%s:'
+ self.d('/**')
+ self.d(' * %s_%s_call_%s:'
% (self.prefix_lc, iface_lc, member_lc))
- self.b(' * @proxy: the #TpProxy')
- self.b(' * @timeout_ms: the timeout in milliseconds, or -1 to use the')
- self.b(' * default')
+ self.d(' * @proxy: the #TpProxy')
+ self.d(' * @timeout_ms: the timeout in milliseconds, or -1 to use the')
+ self.d(' * default')
for arg in in_args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- self.b(' * @%s: Used to pass an \'in\' argument: %s'
+ self.d(' * @%s: Used to pass an \'in\' argument: %s'
% (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
- self.b(' * @callback: called when the method call succeeds or fails;')
- self.b(' * may be %NULL to make a "fire and forget" call with no ')
- self.b(' * reply tracking')
- self.b(' * @user_data: user-supplied data passed to the callback;')
- self.b(' * must be %NULL if @callback is %NULL')
- self.b(' * @destroy: called with the user_data as argument, after the')
- self.b(' * call has succeeded, failed or been cancelled;')
- self.b(' * must be %NULL if @callback is %NULL')
- self.b(' * @weak_object: If not %NULL, a #GObject which will be ')
- self.b(' * weakly referenced; if it is destroyed, this call ')
- self.b(' * will automatically be cancelled. Must be %NULL if ')
- self.b(' * @callback is %NULL')
- self.b(' *')
- self.b(' * Start a %s method call.' % member)
- self.b(' *')
- self.b(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)'))
- self.b(' *')
- self.b(' * Returns: a #TpProxyPendingCall representing the call in')
- self.b(' * progress. It is borrowed from the object, and will become')
- self.b(' * invalid when the callback is called, the call is')
- self.b(' * cancelled or the #TpProxy becomes invalid.')
- self.b(' */')
+ 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 ')
+ self.d(' * reply tracking')
+ self.d(' * @user_data: user-supplied data passed to the callback;')
+ self.d(' * must be %NULL if @callback is %NULL')
+ self.d(' * @destroy: called with the user_data as argument, after the')
+ self.d(' * call has succeeded, failed or been cancelled;')
+ self.d(' * must be %NULL if @callback is %NULL')
+ self.d(' * @weak_object: If not %NULL, a #GObject which will be ')
+ self.d(' * weakly referenced; if it is destroyed, this call ')
+ self.d(' * will automatically be cancelled. Must be %NULL if ')
+ self.d(' * @callback is %NULL')
+ self.d(' *')
+ self.d(' * Start a %s method call.' % member)
+ self.d(' *')
+ self.d(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)'))
+ self.d(' *')
+ self.d(' * Returns: a #TpProxyPendingCall representing the call in')
+ self.d(' * progress. It is borrowed from the object, and will become')
+ self.d(' * invalid when the callback is called, the call is')
+ self.d(' * cancelled or the #TpProxy becomes invalid.')
+
+ deprecated = method.getElementsByTagName('tp:deprecated')
+ if deprecated:
+ d = deprecated[0]
+ self.d(' *')
+ self.d(' * Deprecated: %s' % xml_escape(get_deprecated(d)))
+
+ 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(' gint timeout_ms,')
@@ -793,6 +832,17 @@ 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)
+
+ # leave a gap for the end of the method
+ self.d('')
+ self.b('')
+ self.h('')
+
+ def do_method_reentrant(self, method, iface_lc, member, member_lc, in_args,
+ out_args, collect_callback):
# Reentrant blocking calls
# Example:
# gboolean tp_cli_properties_interface_run_get_properties
@@ -877,48 +927,60 @@ class Generator(object):
self.b('}')
self.b('')
+ if self.deprecate_reentrant:
+ self.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,')
- self.b('/**')
- self.b(' * %s_%s_run_%s:' % (self.prefix_lc, iface_lc, member_lc))
- self.b(' * @proxy: %s' % self.proxy_doc)
- self.b(' * @timeout_ms: Timeout in milliseconds, or -1 for default')
+ 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')
for arg in in_args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- self.b(' * @%s: Used to pass an \'in\' argument: %s'
+ self.d(' * @%s: Used to pass an \'in\' argument: %s'
% (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
for arg in out_args:
name, info, tp_type, elt = arg
ctype, gtype, marshaller, pointer = info
- self.b(' * @%s: Used to return an \'out\' argument if %%TRUE is '
+ self.d(' * @%s: Used to return an \'out\' argument if %%TRUE is '
'returned: %s'
% (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
- self.b(' * @error: If not %NULL, used to return errors if %FALSE ')
- self.b(' * is returned')
- self.b(' * @loop: If not %NULL, set before re-entering ')
- self.b(' * the main loop, to point to a #GMainLoop ')
- self.b(' * which can be used to cancel this call with ')
- self.b(' * g_main_loop_quit(), causing a return of ')
- self.b(' * %FALSE with @error set to %TP_DBUS_ERROR_CANCELLED')
- self.b(' *')
- self.b(' * Call the method %s and run the main loop' % member)
- self.b(' * until it returns. Before calling this method, you must')
- self.b(' * add a reference to any borrowed objects you need to keep,')
- self.b(' * and generally ensure that everything is in a consistent')
- self.b(' * state.')
- self.b(' *')
- self.b(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)'))
- self.b(' *')
- self.b(' * Returns: TRUE on success, FALSE and sets @error on error')
- self.b(' */')
+ self.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')
+
+ deprecated = method.getElementsByTagName('tp:deprecated')
+ if deprecated:
+ d = deprecated[0]
+ self.d(' *')
+ self.d(' * Deprecated: %s' % xml_escape(get_deprecated(d)))
+
+ self.d(' */')
+ self.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,')
@@ -940,7 +1002,13 @@ class Generator(object):
self.b(' %s*%s,' % (ctype, name))
self.h(' GError **error,')
- self.h(' GMainLoop **loop);')
+
+ if self.deprecate_reentrant:
+ self.h(' GMainLoop **loop) %s;' % self.deprecation_attribute)
+ self.h('#endif /* not %s */' % self.deprecate_reentrant)
+ else:
+ self.h(' GMainLoop **loop);')
+
self.h('')
self.b(' GError **error,')
@@ -1012,10 +1080,6 @@ class Generator(object):
self.b('}')
self.b('')
- # leave a gap for the end of the method
- self.b('')
- self.h('')
-
def do_signal_add(self, signal):
marshaller_items = []
gtypes = []
@@ -1136,6 +1200,7 @@ class Generator(object):
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))
def types_to_gtypes(types):
@@ -1145,7 +1210,9 @@ def types_to_gtypes(types):
if __name__ == '__main__':
options, argv = gnu_getopt(sys.argv[1:], '',
['group=', 'subclass=', 'subclass-assert=',
- 'iface-quark-prefix=', 'tp-proxy-api='])
+ 'iface-quark-prefix=', 'tp-proxy-api=',
+ 'generate-reentrant', 'deprecate-reentrant=',
+ 'deprecation-attribute='])
opts = {}
diff --git a/tools/glib-errors-check-gen.py b/tools/glib-errors-check-gen.py
new file mode 100644
index 000000000..553fc9caf
--- /dev/null
+++ b/tools/glib-errors-check-gen.py
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+
+import sys
+import xml.dom.minidom
+
+from libglibcodegen import NS_TP, get_docstring, get_descendant_text
+
+class Generator(object):
+ def __init__(self, dom):
+ self.dom = dom
+ self.errors = self.dom.getElementsByTagNameNS(NS_TP, 'errors')[0]
+
+ def __call__(self):
+
+ print '{'
+ print ' GEnumClass *klass;'
+ 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'):
+ ns = error.parentNode.getAttribute('namespace')
+ nick = error.getAttribute('name').replace(' ', '')
+ enum = ('TP_ERROR_' +
+ error.getAttribute('name').replace(' ', '_').replace('.', '_').upper())
+ s = ('TP_ERROR_STR_' +
+ error.getAttribute('name').replace(' ', '_').replace('.', '_').upper())
+
+ print ''
+ print ' /* %s.%s */' % (ns, nick)
+ print (' value_by_name = g_enum_get_value_by_name (klass, "%s");'
+ % enum)
+ print (' value_by_nick = g_enum_get_value_by_nick (klass, "%s");'
+ % nick)
+ print (' g_assert (value_by_name != NULL);')
+ print (' g_assert (value_by_nick != NULL);')
+ print (' g_assert_cmpint (value_by_name->value, ==, %s);'
+ % enum)
+ print (' g_assert_cmpint (value_by_nick->value, ==, %s);'
+ % enum)
+ print (' g_assert_cmpstr (value_by_name->value_name, ==, "%s");'
+ % enum)
+ print (' g_assert_cmpstr (value_by_nick->value_name, ==, "%s");'
+ % enum)
+ print (' g_assert_cmpstr (value_by_name->value_nick, ==, "%s");'
+ % nick)
+ print (' g_assert_cmpstr (value_by_nick->value_nick, ==, "%s");'
+ % nick)
+ print (' g_assert_cmpstr (%s, ==, TP_ERROR_PREFIX ".%s");'
+ % (s, nick))
+
+ print '}'
+
+if __name__ == '__main__':
+ argv = sys.argv[1:]
+ Generator(xml.dom.minidom.parse(argv[0]))()
diff --git a/tools/glib-errors-enum-body-gen.py b/tools/glib-errors-enum-body-gen.py
deleted file mode 100644
index 44863ee4c..000000000
--- a/tools/glib-errors-enum-body-gen.py
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import xml.dom.minidom
-
-from libglibcodegen import NS_TP, camelcase_to_upper, get_docstring, \
- get_descendant_text
-
-class Generator(object):
- def __init__(self, dom):
- self.dom = dom
- self.errors = self.dom.getElementsByTagNameNS(NS_TP, 'errors')[0]
-
- def do_header(self):
- print '/* Generated from the Telepathy spec\n'
- copyrights = self.errors.getElementsByTagNameNS(NS_TP, 'copyright')
- for copyright in copyrights:
- print get_descendant_text(copyright)
- license = self.errors.getElementsByTagNameNS(NS_TP, 'license')[0]
- print '\n' + get_descendant_text(license) + '\n*/'
-
- def do_enum_values(self):
- for error in self.errors.getElementsByTagNameNS(NS_TP, 'error'):
- print ''
- nick = error.getAttribute('name').replace(' ', '')
- name = camelcase_to_upper(nick.replace('.', ''))
- ns = error.parentNode.getAttribute('namespace')
- enum = 'TP_ERROR_' + name
- print ' /* ' + ns + '.' + name
- print ' ' + get_docstring(error)
- print ' */'
- print ' { %s, "%s", "%s" },' % (enum, enum, nick)
-
-
- def do_get_type(self):
- print """
-#include <_gen/telepathy-errors.h>
-
-GType
-tp_error_get_type (void)
-{
- static GType etype = 0;
- if (G_UNLIKELY (etype == 0))
- {
- static const GEnumValue values[] = {"""
- self.do_enum_values()
- print """\
- };
-
- etype = g_enum_register_static ("TpError", values);
- }
- return etype;
-}
-"""
-
- def __call__(self):
- self.do_header()
- self.do_get_type()
-
-if __name__ == '__main__':
- argv = sys.argv[1:]
- Generator(xml.dom.minidom.parse(argv[0]))()
diff --git a/tools/glib-errors-enum-header-gen.py b/tools/glib-errors-enum-header-gen.py
deleted file mode 100644
index 64939b414..000000000
--- a/tools/glib-errors-enum-header-gen.py
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import xml.dom.minidom
-
-from libglibcodegen import NS_TP, camelcase_to_upper, get_docstring, \
- get_descendant_text
-
-class Generator(object):
- def __init__(self, dom):
- self.dom = dom
- self.errors = self.dom.getElementsByTagNameNS(NS_TP, 'errors')[0]
-
- def do_header(self):
- print '/* Generated from the Telepathy spec\n'
- copyrights = self.errors.getElementsByTagNameNS(NS_TP, 'copyright')
- for copyright in copyrights:
- print get_descendant_text(copyright)
- license = self.errors.getElementsByTagNameNS(NS_TP, 'license')[0]
- print '\n' + get_descendant_text(license) + '\n*/'
-
- def do_gtkdoc(self):
- for error in self.errors.getElementsByTagNameNS(NS_TP, 'error'):
- ns = error.parentNode.getAttribute('namespace')
- nick = error.getAttribute('name').replace(' ', '')
- enum = 'TP_ERROR_' + camelcase_to_upper(nick.replace('.', ''))
- print ' * @' + enum + ': ' + ns + '.' + nick + ':'
- print ' * ' + get_docstring(error) + ' '
-
- def do_enumnames(self):
- for error in self.errors.getElementsByTagNameNS(NS_TP, 'error'):
- nick = error.getAttribute('name').replace(' ', '')
- enum = 'TP_ERROR_' + camelcase_to_upper(nick.replace('.', ''))
- print ' ' + enum + ','
-
- def do_get_type(self):
- print """
-#include <glib-object.h>
-
-G_BEGIN_DECLS
-
-GType tp_error_get_type (void);
-
-/**
- * TP_TYPE_ERROR:
- *
- * The GType of the Telepathy error enumeration.
- */
-#define TP_TYPE_ERROR (tp_error_get_type())
-"""
-
- def do_enum(self):
- print """\
-/**
- * TpError:"""
- self.do_gtkdoc()
- print """\
- *
- * Enumerated type representing the Telepathy D-Bus errors.
- */
-typedef enum {"""
- self.do_enumnames()
- print """\
-} TpError;
-
-G_END_DECLS"""
-
- def __call__(self):
- self.do_header()
- self.do_get_type()
- self.do_enum()
-
-if __name__ == '__main__':
- argv = sys.argv[1:]
- Generator(xml.dom.minidom.parse(argv[0]))()
diff --git a/tools/glib-errors-str-gen.py b/tools/glib-errors-str-gen.py
new file mode 100644
index 000000000..a948a7ca8
--- /dev/null
+++ b/tools/glib-errors-str-gen.py
@@ -0,0 +1,82 @@
+#!/usr/bin/python
+
+import sys
+import xml.dom.minidom
+
+from libglibcodegen import NS_TP, get_docstring, xml_escape
+
+class Generator(object):
+ def __init__(self, dom, basename):
+ self.dom = dom
+ self.errors = self.dom.getElementsByTagNameNS(NS_TP, 'errors')[0]
+ self.basename = basename
+
+ self.__header = []
+ self.__body = []
+ self.__docs = []
+
+ 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 __call__(self):
+ errors = self.errors.getElementsByTagNameNS(NS_TP, 'error')
+
+ self.b('#include <telepathy-glib/errors.h>')
+ self.b('')
+ self.b('const gchar *')
+ self.b('tp_error_get_dbus_name (TpError error)')
+ self.b('{')
+ self.b(' switch (error)')
+ self.b(' {')
+
+ for error in errors:
+ ns = error.parentNode.getAttribute('namespace')
+ nick = error.getAttribute('name').replace(' ', '')
+ uc_nick = error.getAttribute('name').replace(' ', '_').replace('.', '_').upper()
+ name = 'TP_ERROR_STR_' + uc_nick
+ error_name = '%s.%s' % (ns, nick)
+
+ self.d('/**')
+ self.d(' * %s:' % name)
+ self.d(' *')
+ self.d(' * The D-Bus error name %s' % error_name)
+ self.d(' *')
+ self.d(' * %s' % xml_escape(get_docstring(error)))
+ self.d(' */')
+ self.d('')
+
+ self.h('#define %s "%s"' % (name, error_name))
+
+ self.b(' case TP_ERROR_%s:' % uc_nick)
+ self.b(' return %s;' % name)
+
+ self.b(' default:')
+ self.b(' g_return_val_if_reached (NULL);')
+ self.b(' }')
+ self.b('}')
+
+ # make both files end with a newline
+ 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))
+
+if __name__ == '__main__':
+ argv = sys.argv[1:]
+ basename = argv[0]
+
+ Generator(xml.dom.minidom.parse(argv[1]), basename)()
diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py
index 9eb7af5ce..9dfdcc75d 100644
--- a/tools/glib-ginterface-gen.py
+++ b/tools/glib-ginterface-gen.py
@@ -27,7 +27,7 @@ import os.path
import xml.dom.minidom
from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \
- camelcase_to_lower, NS_TP, dbus_gutils_wincaps_to_uscore, \
+ NS_TP, dbus_gutils_wincaps_to_uscore, \
signal_to_marshal_name, method_to_glue_marshal_name
@@ -41,6 +41,7 @@ class Generator(object):
self.dom = dom
self.__header = []
self.__body = []
+ self.__docs = []
assert prefix.endswith('_')
assert not signal_marshal_prefix.endswith('_')
@@ -66,6 +67,7 @@ class Generator(object):
self.prefix_ = prefix.lower()
self.PREFIX_ = prefix.upper()
+ self.basename = basename
self.signal_marshal_prefix = signal_marshal_prefix
self.headers = headers
self.end_headers = end_headers
@@ -73,11 +75,20 @@ class Generator(object):
self.allow_havoc = allow_havoc
def h(self, s):
+ if isinstance(s, unicode):
+ s = s.encode('utf-8')
self.__header.append(s)
def b(self, s):
+ if isinstance(s, unicode):
+ s = s.encode('utf-8')
self.__body.append(s)
+ def d(self, s):
+ if isinstance(s, unicode):
+ s = s.encode('utf-8')
+ self.__docs.append(s)
+
def do_node(self, node):
node_name = node.getAttribute('name').replace('/', '')
node_name_mixed = self.node_name_mixed = node_name.replace('_', '')
@@ -157,20 +168,55 @@ class Generator(object):
self.b('}')
self.b('')
- self.h('/**')
- self.h(' * %s%s:' % (self.Prefix, node_name_mixed))
- self.h(' *')
- self.h(' * Dummy typedef representing any implementation of this '
+ self.d('/**')
+ self.d(' * %s%s:' % (self.Prefix, node_name_mixed))
+ self.d(' *')
+ self.d(' * Dummy typedef representing any implementation of this '
'interface.')
- self.h(' */')
+ self.d(' */')
+
self.h('typedef struct _%s%s %s%s;'
% (self.Prefix, node_name_mixed, self.Prefix, node_name_mixed))
self.h('')
- self.h('/**')
- self.h(' * %s%sClass:' % (self.Prefix, node_name_mixed))
- self.h(' *')
- self.h(' * The class of %s%s.' % (self.Prefix, node_name_mixed))
- self.h(' */')
+
+ self.d('/**')
+ self.d(' * %s%sClass:' % (self.Prefix, node_name_mixed))
+ self.d(' *')
+ self.d(' * The class of %s%s.' % (self.Prefix, node_name_mixed))
+
+ if methods:
+ self.d(' *')
+ self.d(' * In a full implementation of this interface (i.e. all')
+ self.d(' * methods implemented), the interface initialization')
+ self.d(' * function used in G_IMPLEMENT_INTERFACE() would')
+ self.d(' * typically look like this:')
+ self.d(' *')
+ self.d(' * <programlisting>')
+ self.d(' * static void')
+ self.d(' * implement_%s (gpointer klass,' % self.node_name_lc)
+ self.d(' * gpointer unused G_GNUC_UNUSED)')
+ self.d(' * {')
+ self.d(' * #define IMPLEMENT(x) %s%s_implement_&num;&num;x (\\'
+ % (self.prefix_, self.node_name_lc))
+ self.d(' * klass, my_object_&num;&num;x)')
+
+ for method in methods:
+ class_member_name = method.getAttribute('tp:name-for-bindings')
+ class_member_name = class_member_name.lower()
+ self.d(' * IMPLEMENT (%s);' % class_member_name)
+
+ self.d(' * #undef IMPLEMENT')
+ self.d(' * }')
+ self.d(' * </programlisting>')
+ else:
+ self.d(' * This interface has no D-Bus methods, so an')
+ self.d(' * implementation can typically pass %NULL to')
+ self.d(' * G_IMPLEMENT_INTERFACE() as the interface')
+ self.d(' * initialization function.')
+
+ self.d(' */')
+ self.d('')
+
self.h('typedef struct _%s%sClass %s%sClass;'
% (self.Prefix, node_name_mixed, self.Prefix, node_name_mixed))
self.h('')
@@ -207,48 +253,56 @@ class Generator(object):
self.b('%s%s_base_init_once (gpointer klass G_GNUC_UNUSED)'
% (self.prefix_, node_name_lc))
self.b('{')
- self.b(' static TpDBusPropertiesMixinPropInfo properties[%d] = {'
- % (len(properties) + 1))
- for m in properties:
- access = m.getAttribute('access')
- assert access in ('read', 'write', 'readwrite')
+ if properties:
+ self.b(' static TpDBusPropertiesMixinPropInfo properties[%d] = {'
+ % (len(properties) + 1))
- if access == 'read':
- flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_READ'
- elif access == 'write':
- flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE'
- else:
- flags = ('TP_DBUS_PROPERTIES_MIXIN_FLAG_READ | '
- 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE')
+ for m in properties:
+ access = m.getAttribute('access')
+ assert access in ('read', 'write', 'readwrite')
- self.b(' { 0, %s, "%s", 0, NULL, NULL }, /* %s */'
- % (flags, m.getAttribute('type'), m.getAttribute('name')))
+ if access == 'read':
+ flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_READ'
+ elif access == 'write':
+ flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE'
+ else:
+ flags = ('TP_DBUS_PROPERTIES_MIXIN_FLAG_READ | '
+ 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE')
- self.b(' { 0, 0, NULL, 0, NULL, NULL }')
- self.b(' };')
- self.b(' static TpDBusPropertiesMixinIfaceInfo interface =')
- self.b(' { 0, properties, NULL, NULL };')
- self.b('')
- self.b(' interface.dbus_interface = g_quark_from_static_string '
- '("%s");' % self.iface_name)
+ self.b(' { 0, %s, "%s", 0, NULL, NULL }, /* %s */'
+ % (flags, m.getAttribute('type'), m.getAttribute('name')))
- for i, m in enumerate(properties):
- self.b(' properties[%d].name = g_quark_from_static_string ("%s");'
- % (i, m.getAttribute('name')))
- self.b(' properties[%d].type = %s;'
- % (i, type_to_gtype(m.getAttribute('type'))[1]))
+ self.b(' { 0, 0, NULL, 0, NULL, NULL }')
+ self.b(' };')
+ self.b(' static TpDBusPropertiesMixinIfaceInfo interface =')
+ self.b(' { 0, properties, NULL, NULL };')
+ self.b('')
- self.b(' tp_svc_interface_set_dbus_properties_info (%s, &interface);'
- % self.current_gtype)
- self.b('')
- for s in base_init_code:
- self.b(s)
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)
+
+ for i, m in enumerate(properties):
+ self.b(' properties[%d].name = g_quark_from_static_string ("%s");'
+ % (i, m.getAttribute('name')))
+ self.b(' properties[%d].type = %s;'
+ % (i, type_to_gtype(m.getAttribute('type'))[1]))
+
+ self.b(' tp_svc_interface_set_dbus_properties_info (%s, &interface);'
+ % self.current_gtype)
+
+ self.b('')
+
+ for s in base_init_code:
+ self.b(s)
self.b('}')
self.b('static void')
@@ -276,6 +330,10 @@ class Generator(object):
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('')
@@ -335,7 +393,11 @@ class Generator(object):
return ''.join(info) + '\0', offsets
def do_method_glue(self, method, offset):
- lc_name = camelcase_to_lower(method.getAttribute('name'))
+ 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 = method_to_glue_marshal_name(method,
self.signal_marshal_prefix)
@@ -357,10 +419,16 @@ class Generator(object):
def get_method_impl_names(self, method):
dbus_method_name = method.getAttribute('name')
- class_member_name = camelcase_to_lower(dbus_method_name)
+
+ class_member_name = method.getAttribute('tp:name-for-bindings')
+ if dbus_method_name != class_member_name.replace('_', ''):
+ raise AssertionError('Method %s tp:name-for-bindings (%s) does '
+ 'not match' % (dbus_method_name, class_member_name))
+ class_member_name = class_member_name.lower()
+
stub_name = (self.prefix_ + self.node_name_lc + '_' +
class_member_name)
- return (stub_name + '_impl', class_member_name)
+ return (stub_name + '_impl', class_member_name + '_cb')
def do_method(self, method):
assert self.node_name_mixed is not None
@@ -372,7 +440,12 @@ class Generator(object):
# DoStuff
dbus_method_name = method.getAttribute('name')
# do_stuff
- class_member_name = camelcase_to_lower(dbus_method_name)
+ class_member_name = method.getAttribute('tp:name-for-bindings')
+ if dbus_method_name != class_member_name.replace('_', ''):
+ raise AssertionError('Method %s tp:name-for-bindings (%s) does '
+ '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 *);
stub_name = (self.prefix_ + self.node_name_lc + '_' +
@@ -414,18 +487,19 @@ class Generator(object):
else:
out_args.append(struct)
- # Implementation type declaration (in header, docs in body)
- self.b('/**')
- self.b(' * %s:' % impl_name)
- self.b(' * @self: The object implementing this interface')
+ # Implementation type declaration (in header, docs separated)
+ self.d('/**')
+ self.d(' * %s:' % impl_name)
+ self.d(' * @self: The object implementing this interface')
for (ctype, name) in in_args:
- self.b(' * @%s: %s (FIXME, generate documentation)'
+ self.d(' * @%s: %s (FIXME, generate documentation)'
% (name, ctype))
- self.b(' * @context: Used to return values or throw an error')
- self.b(' *')
- self.b(' * The signature of an implementation of the D-Bus method')
- self.b(' * %s on interface %s.' % (dbus_method_name, self.iface_name))
- self.b(' */')
+ self.d(' * @context: 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))
+ self.d(' */')
+
self.h('typedef void (*%s) (%s%s *self,'
% (impl_name, self.Prefix, self.node_name_mixed))
for (ctype, name) in in_args:
@@ -443,7 +517,7 @@ class Generator(object):
self.b(' %s%s,' % (ctype, name))
self.b(' DBusGMethodInvocation *context)')
self.b('{')
- self.b(' %s impl = (%s%s_GET_CLASS (self)->%s);'
+ self.b(' %s impl = (%s%s_GET_CLASS (self)->%s_cb);'
% (impl_name, self.PREFIX_, self.node_name_uc, class_member_name))
self.b('')
self.b(' if (impl != NULL)')
@@ -470,38 +544,41 @@ class Generator(object):
% (self.prefix_, self.node_name_lc, class_member_name,
self.Prefix, self.node_name_mixed, impl_name))
- self.b('/**')
- self.b(' * %s%s_implement_%s:'
+ self.d('/**')
+ self.d(' * %s%s_implement_%s:'
% (self.prefix_, self.node_name_lc, class_member_name))
- self.b(' * @klass: A class whose instances implement this interface')
- self.b(' * @impl: A callback used to implement the %s D-Bus method'
+ self.d(' * @klass: A class whose instances implement this interface')
+ self.d(' * @impl: A callback used to implement the %s D-Bus method'
% dbus_method_name)
- self.b(' *')
- self.b(' * Register an implementation for the %s method in the vtable'
+ self.d(' *')
+ self.d(' * Register an implementation for the %s method in the vtable'
% dbus_method_name)
- self.b(' * of an implementation of this interface. To be called from')
- self.b(' * the interface init function.')
- self.b(' */')
+ self.d(' * of an implementation of this interface. To be called from')
+ self.d(' * the interface init function.')
+ self.d(' */')
+
self.b('void')
self.b('%s%s_implement_%s (%s%sClass *klass, %s impl)'
% (self.prefix_, self.node_name_lc, class_member_name,
self.Prefix, self.node_name_mixed, impl_name))
self.b('{')
- self.b(' klass->%s = impl;' % class_member_name)
+ self.b(' klass->%s_cb = impl;' % class_member_name)
self.b('}')
self.b('')
# Return convenience function (static inline, in header)
- self.h('/**')
- self.h(' * %s:' % ret_name)
- self.h(' * @context: The D-Bus method invocation context')
+ self.d('/**')
+ self.d(' * %s:' % ret_name)
+ self.d(' * @context: The D-Bus method invocation context')
for (ctype, name) in out_args:
- self.h(' * @%s: %s (FIXME, generate documentation)'
+ self.d(' * @%s: %s (FIXME, generate documentation)'
% (name, ctype))
- self.h(' *')
- self.h(' * Return successfully by calling dbus_g_method_return().')
- self.h(' * This inline function exists only to provide type-safety.')
- self.h(' */')
+ 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(' */')
+ self.d('')
+
tmp = (['DBusGMethodInvocation *context'] +
[ctype + name for (ctype, name) in out_args])
self.h('static inline')
@@ -533,8 +610,15 @@ class Generator(object):
# const char *arg0, guint arg1);
dbus_name = signal.getAttribute('name')
+
+ ugly_name = signal.getAttribute('tp:name-for-bindings')
+ if dbus_name != ugly_name.replace('_', ''):
+ raise AssertionError('Signal %s tp:name-for-bindings (%s) does '
+ 'not match' % (dbus_name, ugly_name))
+
stub_name = (self.prefix_ + self.node_name_lc + '_emit_' +
- camelcase_to_lower(dbus_name))
+ ugly_name.lower())
+
const_name = self.get_signal_const_entry(signal)
# Gather arguments
@@ -564,17 +648,17 @@ class Generator(object):
# FIXME: emit docs
- self.b('/**')
- self.b(' * %s:' % stub_name)
- self.b(' * @instance: The object implementing this interface')
+ self.d('/**')
+ self.d(' * %s:' % stub_name)
+ self.d(' * @instance: The object implementing this interface')
for (ctype, name, gtype) in args:
- self.b(' * @%s: %s (FIXME, generate documentation)'
+ self.d(' * @%s: %s (FIXME, generate documentation)'
% (name, ctype))
- self.b(' *')
- self.b(' * Type-safe wrapper around g_signal_emit to emit the')
- self.b(' * %s signal on interface %s.'
+ self.d(' *')
+ self.d(' * Type-safe wrapper around g_signal_emit to emit the')
+ self.d(' * %s signal on interface %s.'
% (dbus_name, self.iface_name))
- self.b(' */')
+ self.d(' */')
self.b('void')
self.b(('%s (' % stub_name) + (',\n '.join(tmp)) + ')')
@@ -590,16 +674,20 @@ class Generator(object):
signal_name = dbus_gutils_wincaps_to_uscore(dbus_name).replace('_',
'-')
- in_base_init.append(' /**')
- in_base_init.append(' * %s%s::%s:'
+
+ 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:
- in_base_init.append(' * @%s: %s (FIXME, generate documentation)'
+ self.d(' * @%s: %s (FIXME, generate documentation)'
% (name, ctype))
- in_base_init.append(' *')
- in_base_init.append(' * The %s D-Bus signal is emitted whenever '
+ self.d(' *')
+ self.d(' * The %s D-Bus signal is emitted whenever '
'this GObject signal is.' % dbus_name)
- in_base_init.append(' */')
+ self.d(' */')
+ self.d('')
+
in_base_init.append(' %s_signals[%s] ='
% (self.node_name_lc, const_name))
in_base_init.append(' g_signal_new ("%s",' % signal_name)
@@ -616,23 +704,33 @@ class Generator(object):
return in_base_init
+ def have_properties(self, nodes):
+ for node in nodes:
+ interface = node.getElementsByTagName('interface')[0]
+ if interface.getElementsByTagName('property'):
+ return True
+ return False
+
def __call__(self):
+ nodes = self.dom.getElementsByTagName('node')
+ nodes.sort(cmp_by_name)
+
self.h('#include <glib-object.h>')
self.h('#include <dbus/dbus-glib.h>')
- self.h('#include <telepathy-glib/dbus-properties-mixin.h>')
+
+ if self.have_properties(nodes):
+ self.h('#include <telepathy-glib/dbus-properties-mixin.h>')
+
self.h('')
self.h('G_BEGIN_DECLS')
self.h('')
- self.b('#include "%s.h"' % basename)
+ self.b('#include "%s.h"' % self.basename)
self.b('')
for header in self.headers:
self.b('#include %s' % header)
self.b('')
- nodes = self.dom.getElementsByTagName('node')
- nodes.sort(cmp_by_name)
-
for node in nodes:
self.do_node(node)
@@ -645,8 +743,9 @@ class Generator(object):
self.h('')
self.b('')
- open(basename + '.h', 'w').write('\n'.join(self.__header))
- open(basename + '.c', 'w').write('\n'.join(self.__body))
+ 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))
def cmdline_error():
diff --git a/tools/glib-gtypes-generator.py b/tools/glib-gtypes-generator.py
index fcb46e841..a49c36e7f 100644
--- a/tools/glib-gtypes-generator.py
+++ b/tools/glib-gtypes-generator.py
@@ -44,16 +44,35 @@ class GTypesGenerator(object):
self.header = open(output + '.h', 'w')
self.body = open(output + '-body.h', 'w')
+ self.docs = open(output + '-gtk-doc.h', 'w')
- for f in (self.header, self.body):
+ 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')
+ # keys are e.g. 'sv', values are the key escaped
self.need_mappings = {}
+ # keys are the contents of the struct (e.g. 'sssu'), values are the
+ # key escaped
self.need_structs = {}
- self.need_arrays = {}
+ # keys are the contents of the struct (e.g. 'sssu'), values are the
+ # key escaped
+ self.need_struct_arrays = {}
+
+ # keys are the contents of the array (unlike need_struct_arrays!),
+ # values are the key escaped
+ self.need_other_arrays = {}
+
+ def h(self, code):
+ self.header.write(code.encode("utf-8"))
+
+ def c(self, code):
+ self.body.write(code.encode("utf-8"))
+
+ def d(self, code):
+ self.docs.write(code.encode('utf-8'))
def do_mapping_header(self, mapping):
members = mapping.getElementsByTagNameNS(NS_TP, 'member')
@@ -70,45 +89,60 @@ class GTypesGenerator(object):
docstring = get_docstring(mapping) or '(Undocumented)'
- self.header.write('/**\n * %s:\n *\n' % name)
- self.header.write(' * %s\n' % xml_escape(docstring))
- self.header.write(' *\n')
- self.header.write(' * This macro expands to a call to a function\n')
- self.header.write(' * that returns the #GType of a #GHashTable\n')
- self.header.write(' * appropriate for representing a D-Bus\n')
- self.header.write(' * dictionary of signature\n')
- self.header.write(' * <literal>a{%s}</literal>.\n' % impl_sig)
- self.header.write(' *\n')
+ self.d('/**\n * %s:\n *\n' % name)
+ self.d(' * %s\n' % xml_escape(docstring))
+ self.d(' *\n')
+ self.d(' * This macro expands to a call to a function\n')
+ self.d(' * that returns the #GType of a #GHashTable\n')
+ self.d(' * appropriate for representing a D-Bus\n')
+ self.d(' * dictionary of signature\n')
+ self.d(' * <literal>a{%s}</literal>.\n' % impl_sig)
+ self.d(' *\n')
key, value = members
- self.header.write(' * Keys (D-Bus type <literal>%s</literal>,\n'
+ self.d(' * Keys (D-Bus type <literal>%s</literal>,\n'
% key.getAttribute('type'))
tp_type = key.getAttributeNS(NS_TP, 'type')
if tp_type:
- self.header.write(' * type <literal>%s</literal>,\n' % tp_type)
- self.header.write(' * named <literal>%s</literal>):\n'
+ self.d(' * type <literal>%s</literal>,\n' % tp_type)
+ self.d(' * named <literal>%s</literal>):\n'
% key.getAttribute('name'))
docstring = get_docstring(key) or '(Undocumented)'
- self.header.write(' * %s\n' % xml_escape(docstring))
- self.header.write(' *\n')
+ self.d(' * %s\n' % xml_escape(docstring))
+ self.d(' *\n')
- self.header.write(' * Values (D-Bus type <literal>%s</literal>,\n'
+ self.d(' * Values (D-Bus type <literal>%s</literal>,\n'
% value.getAttribute('type'))
tp_type = value.getAttributeNS(NS_TP, 'type')
if tp_type:
- self.header.write(' * type <literal>%s</literal>,\n' % tp_type)
- self.header.write(' * named <literal>%s</literal>):\n'
+ self.d(' * type <literal>%s</literal>,\n' % tp_type)
+ self.d(' * named <literal>%s</literal>):\n'
% value.getAttribute('name'))
docstring = get_docstring(value) or '(Undocumented)'
- self.header.write(' * %s\n' % xml_escape(docstring))
- self.header.write(' *\n')
+ self.d(' * %s\n' % xml_escape(docstring))
+ self.d(' *\n')
- self.header.write(' */\n')
+ self.d(' */\n')
- self.header.write('#define %s (%s ())\n\n' % (name, impl))
+ self.h('#define %s (%s ())\n\n' % (name, impl))
self.need_mappings[impl_sig] = esc_impl_sig
+ array_name = mapping.getAttribute('array-name')
+ if array_name:
+ gtype_name = self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper()
+ contents_sig = 'a{' + impl_sig + '}'
+ esc_contents_sig = escape_as_identifier(contents_sig)
+ impl = self.prefix_ + 'type_dbus_array_of_' + esc_contents_sig
+ self.d('/**\n * %s:\n\n' % gtype_name)
+ self.d(' * Expands to a call to a function\n')
+ self.d(' * that returns the #GType of a #GPtrArray\n')
+ self.d(' * of #%s.\n' % name)
+ self.d(' */\n\n')
+
+ self.h('#define %s (%s ())\n\n' % (gtype_name, impl))
+ self.need_other_arrays[contents_sig] = esc_contents_sig
+
def do_struct_header(self, struct):
members = struct.getElementsByTagNameNS(NS_TP, 'member')
impl_sig = ''.join([elt.getAttribute('type') for elt in members])
@@ -128,43 +162,45 @@ class GTypesGenerator(object):
docstring = '(Undocumented)'
else:
docstring = '(Undocumented)'
- self.header.write('/**\n * %s:\n\n' % name)
- self.header.write(' * %s\n' % xml_escape(docstring))
- self.header.write(' *\n')
- self.header.write(' * This macro expands to a call to a function\n')
- self.header.write(' * that returns the #GType of a #GValueArray\n')
- self.header.write(' * appropriate for representing a D-Bus struct\n')
- self.header.write(' * with signature <literal>(%s)</literal>.\n'
+ self.d('/**\n * %s:\n\n' % name)
+ self.d(' * %s\n' % xml_escape(docstring))
+ self.d(' *\n')
+ self.d(' * This macro expands to a call to a function\n')
+ self.d(' * that returns the #GType of a #GValueArray\n')
+ self.d(' * appropriate for representing a D-Bus struct\n')
+ self.d(' * with signature <literal>(%s)</literal>.\n'
% impl_sig)
- self.header.write(' *\n')
+ self.d(' *\n')
for i, member in enumerate(members):
- self.header.write(' * Member %d (D-Bus type '
+ self.d(' * Member %d (D-Bus type '
'<literal>%s</literal>,\n'
% (i, member.getAttribute('type')))
tp_type = member.getAttributeNS(NS_TP, 'type')
if tp_type:
- self.header.write(' * type <literal>%s</literal>,\n' % tp_type)
- self.header.write(' * named <literal>%s</literal>):\n'
+ self.d(' * type <literal>%s</literal>,\n' % tp_type)
+ self.d(' * named <literal>%s</literal>):\n'
% member.getAttribute('name'))
docstring = get_docstring(member) or '(Undocumented)'
- self.header.write(' * %s\n' % xml_escape(docstring))
- self.header.write(' *\n')
+ self.d(' * %s\n' % xml_escape(docstring))
+ self.d(' *\n')
- self.header.write(' */\n')
- self.header.write('#define %s (%s ())\n\n' % (name, impl))
+ self.d(' */\n\n')
+
+ self.h('#define %s (%s ())\n\n' % (name, impl))
array_name = struct.getAttribute('array-name')
if array_name != '':
array_name = (self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper())
impl = self.prefix_ + 'type_dbus_array_' + esc_impl_sig
- self.header.write('/**\n * %s:\n\n' % array_name)
- self.header.write(' * Expands to a call to a function\n')
- self.header.write(' * that returns the #GType of a #GPtrArray\n')
- self.header.write(' * of #%s.\n' % name)
- self.header.write(' */\n')
- self.header.write('#define %s (%s ())\n\n' % (array_name, impl))
- self.need_arrays[impl_sig] = esc_impl_sig
+ self.d('/**\n * %s:\n\n' % array_name)
+ self.d(' * Expands to a call to a function\n')
+ self.d(' * that returns the #GType of a #GPtrArray\n')
+ self.d(' * of #%s.\n' % name)
+ self.d(' */\n\n')
+
+ self.h('#define %s (%s ())\n\n' % (array_name, impl))
+ self.need_struct_arrays[impl_sig] = esc_impl_sig
self.need_structs[impl_sig] = esc_impl_sig
@@ -176,51 +212,83 @@ class GTypesGenerator(object):
self.do_mapping_header(mapping)
for sig in self.need_mappings:
- self.header.write('GType %stype_dbus_hash_%s (void);\n\n' %
+ self.h('GType %stype_dbus_hash_%s (void);\n\n' %
(self.prefix_, self.need_mappings[sig]))
- self.body.write('GType\n%stype_dbus_hash_%s (void)\n{\n' %
+ self.c('GType\n%stype_dbus_hash_%s (void)\n{\n' %
(self.prefix_, self.need_mappings[sig]))
- self.body.write(' static GType t = 0;\n\n')
- self.body.write(' if (G_UNLIKELY (t == 0))\n')
+ self.c(' static GType t = 0;\n\n')
+ self.c(' if (G_UNLIKELY (t == 0))\n')
# FIXME: translate sig into two GTypes
items = tuple(Signature(sig))
gtypes = types_to_gtypes(items)
- self.body.write(' t = dbus_g_type_get_map ("GHashTable", '
+ self.c(' t = dbus_g_type_get_map ("GHashTable", '
'%s, %s);\n' % (gtypes[0], gtypes[1]))
- self.body.write(' return t;\n')
- self.body.write('}\n\n')
+ self.c(' return t;\n')
+ self.c('}\n\n')
for struct in structs:
self.do_struct_header(struct)
for sig in self.need_structs:
- self.header.write('GType %stype_dbus_struct_%s (void);\n\n' %
+ self.h('GType %stype_dbus_struct_%s (void);\n\n' %
(self.prefix_, self.need_structs[sig]))
- self.body.write('GType\n%stype_dbus_struct_%s (void)\n{\n' %
+ self.c('GType\n%stype_dbus_struct_%s (void)\n{\n' %
(self.prefix_, self.need_structs[sig]))
- self.body.write(' static GType t = 0;\n\n')
- self.body.write(' if (G_UNLIKELY (t == 0))\n')
- self.body.write(' t = dbus_g_type_get_struct ("GValueArray",\n')
+ self.c(' static GType t = 0;\n\n')
+ self.c(' if (G_UNLIKELY (t == 0))\n')
+ self.c(' t = dbus_g_type_get_struct ("GValueArray",\n')
items = tuple(Signature(sig))
gtypes = types_to_gtypes(items)
for gtype in gtypes:
- self.body.write(' %s,\n' % gtype)
- self.body.write(' G_TYPE_INVALID);\n')
- self.body.write(' return t;\n')
- self.body.write('}\n\n')
-
- for sig in self.need_arrays:
- self.header.write('GType %stype_dbus_array_%s (void);\n\n' %
- (self.prefix_, self.need_structs[sig]))
- self.body.write('GType\n%stype_dbus_array_%s (void)\n{\n' %
- (self.prefix_, self.need_structs[sig]))
- self.body.write(' static GType t = 0;\n\n')
- self.body.write(' if (G_UNLIKELY (t == 0))\n')
- self.body.write(' t = dbus_g_type_get_collection ("GPtrArray", '
+ self.c(' %s,\n' % gtype)
+ self.c(' G_TYPE_INVALID);\n')
+ self.c(' return t;\n')
+ self.c('}\n\n')
+
+ for sig in self.need_struct_arrays:
+ self.h('GType %stype_dbus_array_%s (void);\n\n' %
+ (self.prefix_, self.need_struct_arrays[sig]))
+ self.c('GType\n%stype_dbus_array_%s (void)\n{\n' %
+ (self.prefix_, self.need_struct_arrays[sig]))
+ self.c(' static GType t = 0;\n\n')
+ self.c(' if (G_UNLIKELY (t == 0))\n')
+ self.c(' t = dbus_g_type_get_collection ("GPtrArray", '
'%stype_dbus_struct_%s ());\n' %
- (self.prefix_, self.need_structs[sig]))
- self.body.write(' return t;\n')
- self.body.write('}\n\n')
+ (self.prefix_, self.need_struct_arrays[sig]))
+ self.c(' return t;\n')
+ self.c('}\n\n')
+
+ for sig in self.need_other_arrays:
+ self.h('GType %stype_dbus_array_of_%s (void);\n\n' %
+ (self.prefix_, self.need_other_arrays[sig]))
+ self.c('GType\n%stype_dbus_array_of_%s (void)\n{\n' %
+ (self.prefix_, self.need_other_arrays[sig]))
+ self.c(' static GType t = 0;\n\n')
+ self.c(' if (G_UNLIKELY (t == 0))\n')
+
+ if sig[:2] == 'a{' and sig[-1:] == '}':
+ # array of mappings
+ self.c(' t = dbus_g_type_get_collection ('
+ '"GPtrArray", '
+ '%stype_dbus_hash_%s ());\n' %
+ (self.prefix_, escape_as_identifier(sig[2:-1])))
+ elif sig[:2] == 'a(' and sig[-1:] == ')':
+ # array of arrays of struct
+ self.c(' t = dbus_g_type_get_collection ('
+ '"GPtrArray", '
+ '%stype_dbus_array_%s ());\n' %
+ (self.prefix_, escape_as_identifier(sig[2:-1])))
+ elif sig[:1] == 'a':
+ # array of arrays of non-struct
+ self.c(' t = dbus_g_type_get_collection ('
+ '"GPtrArray", '
+ '%stype_dbus_array_of_%s ());\n' %
+ (self.prefix_, escape_as_identifier(sig[1:])))
+ else:
+ raise AssertionError("array of '%s' not supported" % sig)
+
+ self.c(' return t;\n')
+ self.c('}\n\n')
if __name__ == '__main__':
argv = sys.argv[1:]
diff --git a/tools/glib-interfaces-gen.py b/tools/glib-interfaces-gen.py
index 741626ceb..69c721be3 100644
--- a/tools/glib-interfaces-gen.py
+++ b/tools/glib-interfaces-gen.py
@@ -3,36 +3,50 @@
from sys import argv, stdout, stderr
import xml.dom.minidom
-from libglibcodegen import NS_TP, camelcase_to_upper, get_docstring, \
+from libglibcodegen import NS_TP, get_docstring, \
get_descendant_text, get_by_path
class Generator(object):
def __init__(self, prefix, implfile, declfile, dom):
self.prefix = prefix + '_'
+
+ 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.spec = get_by_path(dom, "spec")[0]
+ def h(self, code):
+ self.decls.write(code.encode('utf-8'))
+
+ def c(self, code):
+ self.impls.write(code.encode('utf-8'))
+
+ def d(self, code):
+ self.docs.write(code.encode('utf-8'))
+
def __call__(self):
- for file in self.decls, self.impls:
- self.do_header(file)
+ for f in self.h, self.c:
+ self.do_header(f)
self.do_body()
# Header
- def do_header(self, file):
- file.write('/* Generated from: ')
- file.write(get_descendant_text(get_by_path(self.spec, 'title')))
+ def do_header(self, f):
+ f('/* Generated from: ')
+ f(get_descendant_text(get_by_path(self.spec, 'title')))
version = get_by_path(self.spec, "version")
if version:
- file.write(' version ' + get_descendant_text(version))
- file.write('\n\n')
+ f(' version ' + get_descendant_text(version))
+ f('\n\n')
for copyright in get_by_path(self.spec, 'copyright'):
- stdout.write(get_descendant_text(copyright))
- stdout.write('\n')
- file.write('\n')
- file.write(get_descendant_text(get_by_path(self.spec, 'license')))
- file.write(get_descendant_text(get_by_path(self.spec, 'docstring')))
- file.write("""
+ f(get_descendant_text(copyright))
+ f('\n')
+ f('\n')
+ f(get_descendant_text(get_by_path(self.spec, 'license')))
+ f(get_descendant_text(get_by_path(self.spec, 'docstring')))
+ f("""
*/
""")
@@ -44,25 +58,37 @@ class Generator(object):
def do_iface(self, iface):
parent_name = get_by_path(iface, '../@name')
- self.decls.write("""\
+ self.d("""\
/**
* %(IFACE_DEFINE)s:
- *
+ *
* The interface name "%(name)s"
*/
+""" % {'IFACE_DEFINE' : (self.prefix + 'IFACE_' + \
+ parent_name).upper().replace('/', ''),
+ 'name' : iface.getAttribute('name')})
+
+ self.h("""
#define %(IFACE_DEFINE)s \\
"%(name)s"
""" % {'IFACE_DEFINE' : (self.prefix + 'IFACE_' + \
parent_name).upper().replace('/', ''),
'name' : iface.getAttribute('name')})
- self.decls.write("""
+ self.d("""
/**
* %(IFACE_QUARK_DEFINE)s:
- *
+ *
* Expands to a call to a function that returns a quark for the interface \
name "%(name)s"
*/
+""" % {'IFACE_QUARK_DEFINE' : (self.prefix + 'IFACE_QUARK_' + \
+ parent_name).upper().replace('/', ''),
+ 'iface_quark_func' : (self.prefix + 'iface_quark_' + \
+ parent_name).lower().replace('/', ''),
+ 'name' : iface.getAttribute('name')})
+
+ self.h("""
#define %(IFACE_QUARK_DEFINE)s \\
(%(iface_quark_func)s ())
@@ -74,7 +100,7 @@ GQuark %(iface_quark_func)s (void);
parent_name).lower().replace('/', ''),
'name' : iface.getAttribute('name')})
- self.impls.write("""\
+ self.c("""\
GQuark
%(iface_quark_func)s (void)
{
@@ -92,6 +118,80 @@ GQuark
parent_name).lower().replace('/', ''),
'name' : iface.getAttribute('name')})
+ for prop in iface.getElementsByTagNameNS(None, 'property'):
+ self.d("""
+/**
+ * %(IFACE_PREFIX)s_%(PROP_UC)s:
+ *
+ * The fully-qualified property name "%(name)s.%(prop)s"
+ */
+""" % {'IFACE_PREFIX' : (self.prefix + 'PROP_' + \
+ parent_name).upper().replace('/', ''),
+ 'PROP_UC': prop.getAttributeNS(NS_TP, "name-for-bindings").upper(),
+ 'name' : iface.getAttribute('name'),
+ 'prop' : prop.getAttribute('name'),
+ })
+
+ self.h("""
+#define %(IFACE_PREFIX)s_%(PROP_UC)s \\
+"%(name)s.%(prop)s"
+""" % {'IFACE_PREFIX' : (self.prefix + 'PROP_' + \
+ parent_name).upper().replace('/', ''),
+ 'PROP_UC': prop.getAttributeNS(NS_TP, "name-for-bindings").upper(),
+ 'name' : iface.getAttribute('name'),
+ 'prop' : prop.getAttribute('name'),
+ })
+
+
+ for prop in iface.getElementsByTagNameNS(NS_TP, 'contact-attribute'):
+ self.d("""
+/**
+ * %(TOKEN_PREFIX)s_%(TOKEN_UC)s:
+ *
+ * The fully-qualified contact attribute token name "%(name)s/%(prop)s"
+ */
+""" % {'TOKEN_PREFIX' : (self.prefix + 'TOKEN_' + \
+ parent_name).upper().replace('/', ''),
+ 'TOKEN_UC': prop.getAttributeNS(None, "name").upper().replace("-", "_").replace(".", "_"),
+ 'name' : iface.getAttribute('name'),
+ 'prop' : prop.getAttribute('name'),
+ })
+
+ self.h("""
+#define %(TOKEN_PREFIX)s_%(TOKEN_UC)s \\
+"%(name)s/%(prop)s"
+""" % {'TOKEN_PREFIX' : (self.prefix + 'TOKEN_' + \
+ parent_name).upper().replace('/', ''),
+ 'TOKEN_UC': prop.getAttributeNS(None, "name").upper().replace("-", "_").replace(".", "_"),
+ 'name' : iface.getAttribute('name'),
+ 'prop' : prop.getAttribute('name'),
+ })
+
+ for prop in iface.getElementsByTagNameNS(NS_TP, 'hct'):
+ if (prop.getAttribute('is-family') != "yes"):
+ self.d("""
+/**
+ * %(TOKEN_PREFIX)s_%(TOKEN_UC)s:
+ *
+ * The fully-qualified capability token name "%(name)s/%(prop)s"
+ */
+""" % {'TOKEN_PREFIX' : (self.prefix + 'TOKEN_' + \
+ parent_name).upper().replace('/', ''),
+ 'TOKEN_UC': prop.getAttributeNS(None, "name").upper().replace("-", "_").replace(".", "_"),
+ 'name' : iface.getAttribute('name'),
+ 'prop' : prop.getAttribute('name'),
+ })
+
+ self.h("""
+#define %(TOKEN_PREFIX)s_%(TOKEN_UC)s \\
+"%(name)s/%(prop)s"
+""" % {'TOKEN_PREFIX' : (self.prefix + 'TOKEN_' + \
+ parent_name).upper().replace('/', ''),
+ 'TOKEN_UC': prop.getAttributeNS(None, "name").upper().replace("-", "_").replace(".", "_"),
+ 'name' : iface.getAttribute('name'),
+ 'prop' : prop.getAttribute('name'),
+ })
+
if __name__ == '__main__':
argv = argv[1:]
Generator(argv[0], argv[1], argv[2], xml.dom.minidom.parse(argv[3]))()
diff --git a/tools/gobject-foo.py b/tools/gobject-foo.py
index 5921cab8a..002a290ba 100644
--- a/tools/gobject-foo.py
+++ b/tools/gobject-foo.py
@@ -5,7 +5,7 @@
# The master copy of this program is in the telepathy-glib repository -
# please make any changes there.
#
-# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
+# Copyright (C) 2007-2010 Collabora Ltd. <http://www.collabora.co.uk/>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -33,8 +33,13 @@ def gobject_header(head, tail, as_interface=False):
gtype = head.upper() + '_TYPE_' + tail.upper()
o("typedef struct _%s %s;" % (MixedCase, MixedCase))
- o("typedef struct _%sClass %sClass;" % (MixedCase, MixedCase))
- o("typedef struct _%sPrivate %sPrivate;" % (MixedCase, MixedCase))
+
+ if as_interface:
+ o("typedef struct _%sInterface %sInterface;" % (MixedCase, MixedCase))
+ else:
+ o("typedef struct _%sClass %sClass;" % (MixedCase, MixedCase))
+ o("typedef struct _%sPrivate %sPrivate;" % (MixedCase, MixedCase))
+
o("")
o("GType %s_get_type (void);" % lower_case)
o("")
@@ -54,13 +59,17 @@ def gobject_header(head, tail, as_interface=False):
o("#define %s_IS_%s(obj) \\" % (head.upper(), tail.upper()))
o(" (G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))" % gtype)
- if not as_interface:
+ if as_interface:
+ o("#define %s_GET_IFACE(obj) \\" % UPPER_CASE)
+ o(" (G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, \\" % gtype)
+ o(" %sInterface))" % MixedCase)
+ else:
o("#define %s_IS_%s_CLASS(klass) \\" % (head.upper(), tail.upper()))
o(" (G_TYPE_CHECK_CLASS_TYPE ((klass), %s))" % gtype)
- o("#define %s_GET_CLASS(obj) \\" % UPPER_CASE)
- o(" (G_TYPE_INSTANCE_GET_CLASS ((obj), %s, \\" % gtype)
- o(" %sClass))" % MixedCase)
+ o("#define %s_GET_CLASS(obj) \\" % UPPER_CASE)
+ o(" (G_TYPE_INSTANCE_GET_CLASS ((obj), %s, \\" % gtype)
+ o(" %sClass))" % MixedCase)
return out
diff --git a/tools/identity.xsl b/tools/identity.xsl
deleted file mode 100644
index 6630f84de..000000000
--- a/tools/identity.xsl
+++ /dev/null
@@ -1,7 +0,0 @@
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:template match="@*|node()">
- <xsl:copy>
- <xsl:apply-templates select="@*|node()"/>
- </xsl:copy>
- </xsl:template>
-</xsl:stylesheet>
diff --git a/tools/libglibcodegen.py b/tools/libglibcodegen.py
index 129c179e7..6a9d21485 100644
--- a/tools/libglibcodegen.py
+++ b/tools/libglibcodegen.py
@@ -23,14 +23,13 @@ please make any changes there.
from libtpcodegen import NS_TP, \
Signature, \
- camelcase_to_lower, \
- camelcase_to_upper, \
cmp_by_name, \
escape_as_identifier, \
get_by_path, \
get_descendant_text, \
get_docstring, \
- xml_escape
+ xml_escape, \
+ get_deprecated
def dbus_gutils_wincaps_to_uscore(s):
"""Bug-for-bug compatible Python port of _dbus_gutils_wincaps_to_uscore
diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py
index 6391f1a48..837ff2f74 100644
--- a/tools/libtpcodegen.py
+++ b/tools/libtpcodegen.py
@@ -29,32 +29,6 @@ NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
_ASCII_ALNUM = ascii_letters + digits
-def camelcase_to_lower(s):
- out ="";
- out += s[0].lower()
- last_upper=False
- if s[0].isupper():
- last_upper=True
- for i in range(1,len(s)):
- if s[i].isupper():
- if last_upper:
- if (i+1) < len(s) and s[i+1].islower():
- out += "_" + s[i].lower()
- else:
- out += s[i].lower()
- else:
- out += "_" + s[i].lower()
- last_upper=True
- else:
- out += s[i]
- last_upper=False
- return out
-
-
-def camelcase_to_upper(s):
- return camelcase_to_lower(s).upper()
-
-
def cmp_by_name(node1, node2):
return cmp(node1.getAttributeNode("name").nodeValue,
node2.getAttributeNode("name").nodeValue)
@@ -146,6 +120,16 @@ def get_docstring(element):
docstring = ''
return docstring
+def get_deprecated(element):
+ text = []
+ for x in element.childNodes:
+ if hasattr(x, 'data'):
+ text.append(x.data.replace('\n', ' ').strip())
+ else:
+ # This caters for tp:dbus-ref elements, but little else.
+ if x.childNodes and hasattr(x.childNodes[0], 'data'):
+ text.append(x.childNodes[0].data.replace('\n', ' ').strip())
+ return ' '.join(text)
def get_descendant_text(element_or_elements):
if not element_or_elements:
diff --git a/tools/make-release-mail.py b/tools/make-release-mail.py
new file mode 100644
index 000000000..2bd7c2bcc
--- /dev/null
+++ b/tools/make-release-mail.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# vim: set fileencoding=utf-8 :
+#
+# Hello. This is make-release-mail.py from the Telepathy project. It's
+# designed to turn an item from a NEWS file into a mail suitable for sending
+# to <telepathy@lists.freedesktop.org>. I hope that you enjoy your stay.
+
+import sys
+
+def extract_description(package, version, news_path):
+ release_name = []
+ details = []
+
+ with open(news_path) as f:
+ lines = (line for line in f.readlines())
+ for line in lines:
+ # Find the 'telepathy-foo 0.1.2' header
+ if line.startswith("%s %s" % (package, version)):
+ break
+
+ # Skip the ====== line, and the first blank line
+ lines.next()
+ lines.next()
+
+ got_release_name = False
+
+ for line in lines:
+ line = line.rstrip()
+ # If we hit the next version header, we're done
+ if line.startswith(package):
+ break
+ # Else, if we hit a blank line and we're still reading the release
+ # name, we're done with the release name.
+ elif not got_release_name and line == '':
+ got_release_name = True
+ # Otherwise, append this to the relevant list
+ elif not got_release_name:
+ release_name.append(line)
+ else:
+ details.append(line)
+
+ assert got_release_name, (release_name, details)
+
+ # We rstrip details because it picks up a trailing blank line
+ return ('\n'.join(release_name), '\n'.join(details).rstrip())
+
+BASE_URL = 'http://telepathy.freedesktop.org/releases'
+
+def main(package, version, news_path):
+ release_name, details = extract_description(package, version, news_path)
+
+ print """
+%(release_name)s
+
+tarball: %(base_url)s/%(package)s/%(package)s-%(version)s.tar.gz
+signature: %(base_url)s/%(package)s/%(package)s-%(version)s.tar.gz.asc
+
+%(details)s""".strip().rstrip() % {
+ 'base_url': BASE_URL,
+ 'package': package,
+ 'version': version,
+ 'release_name': release_name,
+ 'details': details,
+ }
+
+if __name__ == '__main__':
+ try:
+ package, version, news_path = sys.argv[1:]
+
+ main(package, version, news_path)
+ except ValueError, e:
+ sys.stderr.write(
+ 'Usage: %s package-name package.version.number path/to/NEWS\n' %
+ sys.argv[0])
+ sys.stderr.flush()
+ sys.exit(1)
diff --git a/tools/manager-file.py b/tools/manager-file.py
new file mode 100644
index 000000000..45f640403
--- /dev/null
+++ b/tools/manager-file.py
@@ -0,0 +1,175 @@
+#!/usr/bin/python
+
+# manager-file.py: generate .manager files and TpCMParamSpec arrays from the
+# same data (should be suitable for all connection managers that don't have
+# plugins)
+#
+# The master copy of this program is in the telepathy-glib repository -
+# please make any changes there.
+#
+# Copyright (c) Collabora Ltd. <http://www.collabora.co.uk/>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# 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 re
+import sys
+
+_NOT_C_STR = re.compile(r'[^A-Za-z0-9_-]')
+
+def c_string(x):
+ # whitelist-based brute force and ignorance - escape nearly all punctuation
+ return '"' + _NOT_C_STR.sub(lambda c: r'\x%02x' % ord(c), x) + '"'
+
+def desktop_string(x):
+ return x.replace(' ', r'\s').replace('\n', r'\n').replace('\r', r'\r').replace('\t', r'\t')
+
+supported = list('sbuiqn')
+
+fdefaultencoders = {
+ 's': desktop_string,
+ 'b': (lambda b: b and '1' or '0'),
+ 'u': (lambda n: '%u' % n),
+ 'i': (lambda n: '%d' % n),
+ 'q': (lambda n: '%u' % n),
+ 'n': (lambda n: '%d' % n),
+ }
+for x in supported: assert x in fdefaultencoders
+
+gtypes = {
+ 's': 'G_TYPE_STRING',
+ 'b': 'G_TYPE_BOOLEAN',
+ 'u': 'G_TYPE_UINT',
+ 'i': 'G_TYPE_INT',
+ 'q': 'G_TYPE_UINT',
+ 'n': 'G_TYPE_INT',
+}
+for x in supported: assert x in gtypes
+
+gdefaultencoders = {
+ 's': c_string,
+ 'b': (lambda b: b and 'GINT_TO_POINTER (TRUE)' or 'GINT_TO_POINTER (FALSE)'),
+ 'u': (lambda n: 'GUINT_TO_POINTER (%u)' % n),
+ 'i': (lambda n: 'GINT_TO_POINTER (%d)' % n),
+ 'q': (lambda n: 'GUINT_TO_POINTER (%u)' % n),
+ 'n': (lambda n: 'GINT_TO_POINTER (%d)' % n),
+ }
+for x in supported: assert x in gdefaultencoders
+
+gdefaultdefaults = {
+ 's': 'NULL',
+ 'b': 'GINT_TO_POINTER (FALSE)',
+ 'u': 'GUINT_TO_POINTER (0)',
+ 'i': 'GINT_TO_POINTER (0)',
+ 'q': 'GUINT_TO_POINTER (0)',
+ 'n': 'GINT_TO_POINTER (0)',
+ }
+for x in supported: assert x in gdefaultdefaults
+
+gflags = {
+ 'has-default': 'TP_CONN_MGR_PARAM_FLAG_HAS_DEFAULT',
+ 'register': 'TP_CONN_MGR_PARAM_FLAG_REGISTER',
+ 'required': 'TP_CONN_MGR_PARAM_FLAG_REQUIRED',
+ 'secret': 'TP_CONN_MGR_PARAM_FLAG_SECRET',
+ 'dbus-property': 'TP_CONN_MGR_PARAM_FLAG_DBUS_PROPERTY',
+}
+
+def write_manager(f, manager, protos):
+ # pointless backwards compat section
+ print >> f, '[ConnectionManager]'
+ print >> f, 'BusName=org.freedesktop.Telepathy.ConnectionManager.' + manager
+ print >> f, 'ObjectPath=/org/freedesktop/Telepathy/ConnectionManager/' + manager
+
+ # protocols
+ for proto, params in protos.iteritems():
+ print >> f
+ print >> f, '[Protocol %s]' % proto
+
+ defaults = {}
+
+ for param, info in params.iteritems():
+ dtype = info['dtype']
+ flags = info.get('flags', '').split()
+ struct_field = info.get('struct_field', param.replace('-', '_'))
+ filter = info.get('filter', 'NULL')
+ filter_data = info.get('filter_data', 'NULL')
+ setter_data = 'NULL'
+
+ if 'default' in info:
+ default = fdefaultencoders[dtype](info['default'])
+ defaults[param] = default
+
+ if flags:
+ flags = ' ' + ' '.join(flags)
+ else:
+ flags = ''
+
+ print >> f, 'param-%s=%s%s' % (param, desktop_string(dtype), flags)
+
+ for param, default in defaults.iteritems():
+ print >> f, 'default-%s=%s' % (param, default)
+
+def write_c_params(f, manager, proto, struct, params):
+ print >> f, "static const TpCMParamSpec %s_%s_params[] = {" % (manager, proto)
+
+ for param, info in params.iteritems():
+ dtype = info['dtype']
+ flags = info.get('flags', '').split()
+ struct_field = info.get('struct_field', param.replace('-', '_'))
+ filter = info.get('filter', 'NULL')
+ filter_data = info.get('filter_data', 'NULL')
+ setter_data = 'NULL'
+
+ if 'default' in info:
+ default = gdefaultencoders[dtype](info['default'])
+ else:
+ default = gdefaultdefaults[dtype]
+
+ if flags:
+ flags = ' | '.join([gflags[flag] for flag in flags])
+ else:
+ flags = '0'
+
+ if struct is None or struct_field is None:
+ struct_offset = '0'
+ else:
+ struct_offset = 'G_STRUCT_OFFSET (%s, %s)' % (struct, struct_field)
+
+ print >> f, (''' { %s, %s, %s,
+ %s,
+ %s, /* default */
+ %s, /* struct offset */
+ %s, /* filter */
+ %s, /* filter data */
+ %s /* setter data */ },''' %
+ (c_string(param), c_string(dtype), gtypes[dtype], flags,
+ default, struct_offset, filter, filter_data, setter_data))
+
+ print >> f, " { NULL }"
+ print >> f, "};"
+
+if __name__ == '__main__':
+ environment = {}
+ execfile(sys.argv[1], environment)
+
+ f = open('%s/%s.manager' % (sys.argv[2], environment['MANAGER']), 'w')
+ write_manager(f, environment['MANAGER'], environment['PARAMS'])
+ f.close()
+
+ f = open('%s/param-spec-struct.h' % sys.argv[2], 'w')
+ for protocol in environment['PARAMS']:
+ write_c_params(f, environment['MANAGER'], protocol,
+ environment['STRUCTS'][protocol],
+ environment['PARAMS'][protocol])
+ f.close()
diff --git a/tools/shave.mk b/tools/shave.mk
new file mode 100644
index 000000000..53cb3bf5e
--- /dev/null
+++ b/tools/shave.mk
@@ -0,0 +1 @@
+QUIET_GEN = $(Q:@=@echo ' GEN '$@;)
diff --git a/tools/telepathy-glib.supp b/tools/telepathy-glib.supp
new file mode 100644
index 000000000..28bd5a06a
--- /dev/null
+++ b/tools/telepathy-glib.supp
@@ -0,0 +1,390 @@
+# Valgrind error suppression file
+
+# ============================= libc ==================================
+
+{
+ ld.so initialization + selinux
+ Memcheck:Leak
+ ...
+ fun:_dl_init
+ obj:/lib/ld-*.so
+}
+
+{
+ dlopen initialization, triggered by handle-leak-debug code
+ Memcheck:Leak
+ ...
+ fun:__libc_dlopen_mode
+ fun:init
+ fun:backtrace
+ fun:handle_leak_debug_bt
+ fun:dynamic_ensure_handle
+ fun:tp_handle_ensure
+}
+
+# default.supp has these for 2.10, but they're too specific
+{
+ Debian libc6 (2.10.x, 2.11.x) stripped dynamic linker
+ Memcheck:Cond
+ fun:index
+ fun:expand_dynamic_string_token
+ fun:_dl_map_object
+ fun:map_doit
+ fun:_dl_catch_error
+ fun:do_preload
+ fun:dl_main
+ fun:_dl_sysdep_start
+ fun:_dl_start
+ obj:/lib/ld-*.so
+}
+{
+ Debian libc6 (2.9.x - 2.11.x) stripped dynamic linker
+ Memcheck:Cond
+ fun:_dl_relocate_object
+ fun:dl_main
+ fun:_dl_sysdep_start
+ fun:_dl_start
+ obj:/lib/ld-*.so
+}
+
+{
+ ld.so initialization on glibc 2.9
+ Memcheck:Cond
+ fun:strlen
+ fun:_dl_init_paths
+ fun:dl_main
+ fun:_dl_sysdep_start
+ fun:_dl_start
+ obj:/lib/ld-2.9.so
+}
+
+# ======================= libselinux on Debian amd64 =====================
+
+{
+ I have no idea what SELinux is doing but it's not my problem
+ Memcheck:Cond
+ ...
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+}
+
+{
+ I have no idea what SELinux is doing but it's not my problem
+ Memcheck:Value8
+ ...
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+}
+
+{
+ I have no idea what SELinux is doing but it's not my problem
+ Memcheck:Leak
+ ...
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+ obj:/lib/libselinux.so.1
+}
+
+# ============================= GLib ==================================
+
+{
+ g_set_prgname copies its argument
+ Memcheck:Leak
+ ...
+ fun:g_set_prgname
+}
+
+{
+ one g_get_charset per child^Wprocess
+ Memcheck:Leak
+ ...
+ fun:g_get_charset
+}
+
+{
+ one g_get_home_dir per process
+ Memcheck:Leak
+ ...
+ fun:g_get_home_dir
+}
+
+{
+ GQuarks can't be freed
+ Memcheck:Leak
+ ...
+ fun:g_quark_from_static_string
+}
+
+{
+ GQuarks can't be freed
+ Memcheck:Leak
+ ...
+ fun:g_quark_from_string
+}
+
+{
+ interned strings can't be freed
+ Memcheck:Leak
+ ...
+ fun:g_intern_string
+}
+
+{
+ interned strings can't be freed
+ Memcheck:Leak
+ ...
+ fun:g_intern_static_string
+}
+
+{
+ shared global default g_main_context
+ Memcheck:Leak
+ ...
+ fun:g_main_context_new
+ fun:g_main_context_default
+}
+
+{
+ GTest initialization
+ Memcheck:Leak
+ ...
+ fun:g_test_init
+ fun:main
+}
+
+{
+ GTest admin
+ Memcheck:Leak
+ ...
+ fun:g_test_add_vtable
+}
+
+{
+ GTest pseudorandomness
+ Memcheck:Leak
+ ...
+ fun:g_rand_new_with_seed_array
+ fun:test_run_seed
+ ...
+ fun:g_test_run
+}
+
+{
+ GSLice initialization
+ Memcheck:Leak
+ ...
+ fun:g_malloc0
+ fun:g_slice_init_nomessage
+ fun:g_slice_alloc
+}
+
+# ============================= GObject ===============================
+
+{
+ g_type_init
+ Memcheck:Leak
+ ...
+ fun:g_type_init
+}
+
+{
+ g_type_init_with_debug_flags
+ Memcheck:Leak
+ ...
+ fun:g_type_init_with_debug_flags
+}
+
+{
+ g_type_register_static
+ Memcheck:Leak
+ ...
+ fun:g_type_register_static
+}
+
+{
+ g_type_add_interface_static
+ Memcheck:Leak
+ ...
+ fun:g_type_add_interface_static
+}
+
+{
+ initialization of interfaces
+ Memcheck:Leak
+ ...
+ fun:type_iface_vtable_base_init_Wm
+ fun:g_type_class_ref
+}
+
+# ============================= GIO ===================================
+
+{
+ GIO init
+ Memcheck:Leak
+ ...
+ fun:g_inet_address_class_intern_init
+}
+
+{
+ g_simple_async_result class
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_simple_async_result_new
+}
+
+# ============================= dbus-glib =============================
+
+{
+ registering marshallers is permanent
+ Memcheck:Leak
+ ...
+ fun:dbus_g_object_register_marshaller_array
+ fun:dbus_g_object_register_marshaller
+}
+
+{
+ dbus-glib specialized GTypes are permanent
+ Memcheck:Leak
+ ...
+ fun:dbus_g_type_specialized_init
+}
+
+{
+ libdbus shared connection
+ Memcheck:Leak
+ ...
+ fun:dbus_g_bus_get
+}
+
+{
+ dbus-gobject registrations aren't freed unless we fall off the bus
+ Memcheck:Leak
+ ...
+ fun:g_slist_append
+ fun:dbus_g_connection_register_g_object
+}
+
+{
+ DBusGProxy slots aren't freed unless we fall off the bus
+ Memcheck:Leak
+ ...
+ fun:dbus_connection_allocate_data_slot
+ ...
+ fun:dbus_g_proxy_constructor
+}
+
+{
+ error registrations are for life, not just for Christmas
+ Memcheck:Leak
+ ...
+ fun:dbus_g_error_domain_register
+}
+
+{
+ DBusGProxy class init
+ Memcheck:Leak
+ ...
+ fun:dbus_g_proxy_class_init
+}
+
+# ============================= telepathy-glib ========================
+
+{
+ tp_dbus_daemon_constructor @daemons once per DBusConnection
+ Memcheck:Leak
+ ...
+ fun:g_slice_alloc
+ fun:tp_dbus_daemon_constructor
+}
+
+{
+ tp_proxy_subclass_add_error_mapping refs the enum
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ fun:tp_proxy_subclass_add_error_mapping
+}
+
+{
+ tp_proxy_or_subclass_hook_on_interface_add never frees its list
+ Memcheck:Leak
+ ...
+ fun:tp_proxy_or_subclass_hook_on_interface_add
+}
+
+{
+ tp_dbus_daemon_constructor filter not freed til we fall off the bus
+ Memcheck:Leak
+ ...
+ fun:dbus_connection_add_filter
+ fun:tp_dbus_daemon_constructor
+}
+
+{
+ tp_g_socket_address_from_variant reffing GNIO types
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:tp_g_socket_address_from_variant
+}
+
+{
+ creating classes for DBusGProxy
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_object_new
+ ...
+ fun:tp_proxy_borrow_interface_by_id
+}
+
+{
+ creating classes for tp_dbus_daemon_new
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_object_new
+ ...
+ fun:tp_dbus_daemon_new
+}
+
+{
+ creating classes for TpCHannel
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_object_new
+ ...
+ fun:tp_channel_new
+}
+
+{
+ creating a boxed type to use in TpCapabilities
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_param_spec_boxed
+ fun:tp_capabilities_class_intern_init
+}
+
+# ============================= questionable ==========================
+
+{
+ creating classes for instances (this is a pretty big hammer)
+ Memcheck:Leak
+ ...
+ fun:g_type_class_ref
+ ...
+ fun:g_type_create_instance
+ ...
+ fun:g_param_spec_string
+}
diff --git a/tools/test-wrapper.sh b/tools/test-wrapper.sh
new file mode 100755
index 000000000..94900674a
--- /dev/null
+++ b/tools/test-wrapper.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+# Make tests shut up. On success, if stdout is a tty, we only output messages
+# about skipped tests; on failure, or if stdout is a file or pipe, we output
+# the lot.
+#
+# Usage: test-wrapper.sh PROGRAM [ARGS...]
+
+set -e
+
+if test -t 1 && test "z$CHECK_VERBOSE" = z; then
+ : # continue with the output-suppressed code path, below
+else
+ "$@" || e=$?
+ exit $e
+fi
+
+e=0
+"$@" > capture-$$.log 2>&1 || e=$?
+if test z$e = z0; then
+ grep -i skipped capture-$$.log || true
+ rm -f capture-$$.log
+else
+ cat capture-$$.log
+ exit $e
+fi
+
+# Copyright © 2010 Collabora Ltd. <http://www.collabora.co.uk/>
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved. There is no warranty.
diff --git a/tools/valgrind.mk b/tools/valgrind.mk
new file mode 100644
index 000000000..25a3488cd
--- /dev/null
+++ b/tools/valgrind.mk
@@ -0,0 +1,13 @@
+VALGRIND = valgrind --tool=memcheck \
+ --verbose \
+ --leak-check=full \
+ --leak-resolution=high \
+ --suppressions=$(top_srcdir)/tools/telepathy-glib.supp \
+ --child-silent-after-fork=yes \
+ --num-callers=20 \
+ --gen-suppressions=all
+
+# other potentially interesting options:
+# --show-reachable=yes reachable objects (many!)
+# --read-var-info=yes better diagnostics from DWARF3 info
+# --track-origins=yes better diagnostics for uninit values (slow)
diff --git a/tools/with-session-bus.sh b/tools/with-session-bus.sh
index 063bd7e17..cfedb5b9d 100644
--- a/tools/with-session-bus.sh
+++ b/tools/with-session-bus.sh
@@ -59,7 +59,9 @@ cleanup ()
{
pid=`head -n1 $me-$$.pid`
if test -n "$pid" ; then
- echo "Killing temporary bus daemon: $pid" >&2
+ if [ -n "$VERBOSE_TESTS" ]; then
+ echo "Killing temporary bus daemon: $pid" >&2
+ fi
kill -INT "$pid"
fi
rm -f $me-$$.address
@@ -69,8 +71,10 @@ cleanup ()
trap cleanup INT HUP TERM
dbus-daemon $dbus_daemon_args
-{ echo -n "Temporary bus daemon is "; cat $me-$$.address; } >&2
-{ echo -n "Temporary bus daemon PID is "; head -n1 $me-$$.pid; } >&2
+if [ -n "$VERBOSE_TESTS" ]; then
+ { echo -n "Temporary bus daemon is "; cat $me-$$.address; } >&2
+ { echo -n "Temporary bus daemon PID is "; head -n1 $me-$$.pid; } >&2
+fi
e=0
DBUS_SESSION_BUS_ADDRESS="`cat $me-$$.address`"
diff --git a/tools/xincludator.py b/tools/xincludator.py
new file mode 100644
index 000000000..63e106ace
--- /dev/null
+++ b/tools/xincludator.py
@@ -0,0 +1,39 @@
+#!/usr/bin/python
+
+from sys import argv, stdout, stderr
+import codecs, locale
+import os
+import xml.dom.minidom
+
+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):
+ attr = dom.documentElement.attributes.item(i)
+ if attr.prefix == 'xmlns':
+ if attr.localName in dropns:
+ remove_attrs.append(attr)
+ else:
+ dropns.append(attr.localName)
+ for attr in remove_attrs:
+ dom.documentElement.removeAttributeNode(attr)
+ for include in dom.getElementsByTagNameNS(NS_XI, 'include'):
+ href = include.getAttribute('href')
+ # FIXME: assumes Unixy paths
+ filename = os.path.join(os.path.dirname(base), href)
+ subdom = xml.dom.minidom.parse(filename)
+ xincludate(subdom, filename, dropns)
+ if './' in href:
+ subdom.documentElement.setAttribute('xml:base', href)
+ include.parentNode.replaceChild(subdom.documentElement, include)
+
+if __name__ == '__main__':
+ argv = argv[1:]
+ dom = xml.dom.minidom.parse(argv[0])
+ xincludate(dom, argv[0])
+ xml = dom.toxml()
+ stdout.write(xml)
+ stdout.write('\n')