summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2007-11-23 14:01:39 +0000
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2007-11-23 14:01:39 +0000
commit031607bd26b6cd7b042ff26eaa0b97d3cf387164 (patch)
treee3ad9651a748df059719e38f810169ffc7b18d94 /tools
parentc81f69f6db3db739f2c17ad9c0075e19de3c6f62 (diff)
Move tools directory to top level. Stop using spec-gen.am
Diffstat (limited to 'tools')
-rw-r--r--tools/.git-darcs-dir0
-rw-r--r--tools/Makefile.am9
-rw-r--r--tools/c-constants-generator.xsl255
-rw-r--r--tools/c-interfaces-generator.xsl82
-rw-r--r--tools/doc-generator.xsl427
-rw-r--r--tools/genginterface.py709
-rw-r--r--tools/ls-interfaces.xsl33
-rw-r--r--tools/make-all-async.xsl22
-rw-r--r--tools/spec-to-introspect.xsl26
-rw-r--r--tools/update-spec-gen-am.sh75
10 files changed, 1638 insertions, 0 deletions
diff --git a/tools/.git-darcs-dir b/tools/.git-darcs-dir
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/.git-darcs-dir
diff --git a/tools/Makefile.am b/tools/Makefile.am
new file mode 100644
index 0000000..c27fe04
--- /dev/null
+++ b/tools/Makefile.am
@@ -0,0 +1,9 @@
+EXTRA_DIST = \
+ c-constants-generator.xsl \
+ c-interfaces-generator.xsl \
+ doc-generator.xsl \
+ genginterface.py \
+ ls-interfaces.xsl \
+ make-all-async.xsl \
+ spec-to-introspect.xsl \
+ update-spec-gen-am.sh
diff --git a/tools/c-constants-generator.xsl b/tools/c-constants-generator.xsl
new file mode 100644
index 0000000..c249240
--- /dev/null
+++ b/tools/c-constants-generator.xsl
@@ -0,0 +1,255 @@
+<!-- Stylesheet to extract C enumerations from the Telepathy spec.
+
+Copyright (C) 2006, 2007 Collabora Limited
+
+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
+Library 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
+ exclude-result-prefixes="tp">
+
+ <xsl:output method="text" indent="no" encoding="ascii"/>
+
+ <xsl:param name="mixed-case-prefix" select="''"/>
+
+ <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
+ <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
+
+ <xsl:variable name="upper-case-prefix" select="concat(translate($mixed-case-prefix, $lower, $upper), '_')"/>
+ <xsl:variable name="lower-case-prefix" select="concat(translate($mixed-case-prefix, $upper, $lower), '_')"/>
+
+
+ <xsl:template match="tp:flags">
+ <xsl:variable name="name">
+ <xsl:choose>
+ <xsl:when test="@plural">
+ <xsl:value-of select="@plural"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="value-prefix">
+ <xsl:choose>
+ <xsl:when test="@singular">
+ <xsl:value-of select="@singular"/>
+ </xsl:when>
+ <xsl:when test="@value-prefix">
+ <xsl:value-of select="@value-prefix"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+/**
+ * <xsl:value-of select="translate(concat($mixed-case-prefix, $name), '_', '')"/>:
+<xsl:apply-templates mode="flag-or-enumvalue-gtkdoc">
+ <xsl:with-param name="value-prefix" select="$value-prefix"/>
+</xsl:apply-templates> *
+<xsl:if test="tp:docstring">
+ * &lt;![CDATA[<xsl:value-of select="translate(string (tp:docstring), '&#13;&#10;', ' ')"/>]]&gt;
+ *
+</xsl:if> * Bitfield/set of flags generated from the Telepathy specification.
+ */
+typedef enum {
+<xsl:apply-templates>
+ <xsl:with-param name="value-prefix" select="$value-prefix"/>
+</xsl:apply-templates>} <xsl:value-of select="translate(concat($mixed-case-prefix, $name), '_', '')"/>;
+
+</xsl:template>
+
+ <xsl:template match="text()" mode="flag-or-enumvalue-gtkdoc"/>
+
+ <xsl:template match="tp:enumvalue" mode="flag-or-enumvalue-gtkdoc">
+ <xsl:param name="value-prefix"/>
+ <xsl:text> * @</xsl:text>
+ <xsl:value-of select="translate(concat($upper-case-prefix, $value-prefix, '_', @suffix), $lower, $upper)"/>
+ <xsl:text>: &lt;![CDATA[</xsl:text>
+ <xsl:value-of select="translate(string(tp:docstring), '&#13;&#10;', ' ')"/>
+ <xsl:text>]]&gt;&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="tp:flag" mode="flag-or-enumvalue-gtkdoc">
+ <xsl:param name="value-prefix"/>
+ <xsl:text> * @</xsl:text>
+ <xsl:value-of select="translate(concat($upper-case-prefix, $value-prefix, '_', @suffix), $lower, $upper)"/>
+ <xsl:text>: &lt;![CDATA[</xsl:text>
+ <xsl:value-of select="translate(string(tp:docstring), '&#13;&#10;', ' ')"/>
+ <xsl:text>]]&gt;&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="tp:enum">
+ <xsl:variable name="name">
+ <xsl:choose>
+ <xsl:when test="@singular">
+ <xsl:value-of select="@singular"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="value-prefix">
+ <xsl:choose>
+ <xsl:when test="@singular">
+ <xsl:value-of select="@singular"/>
+ </xsl:when>
+ <xsl:when test="@value-prefix">
+ <xsl:value-of select="@value-prefix"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="name-plural">
+ <xsl:choose>
+ <xsl:when test="@plural">
+ <xsl:value-of select="@plural"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/><xsl:text>s</xsl:text>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+/**
+ * <xsl:value-of select="translate(concat($mixed-case-prefix, $name), '_', '')"/>:
+<xsl:apply-templates mode="flag-or-enumvalue-gtkdoc">
+ <xsl:with-param name="value-prefix" select="$value-prefix"/>
+</xsl:apply-templates> *
+<xsl:if test="tp:docstring">
+ * &lt;![CDATA[[<xsl:value-of select="translate(string (tp:docstring), '&#13;&#10;', ' ')"/>]]&gt;
+ *
+</xsl:if> * Enumeration generated from the Telepathy specification.
+ */
+typedef enum {
+<xsl:apply-templates>
+ <xsl:with-param name="value-prefix" select="$value-prefix"/>
+</xsl:apply-templates>} <xsl:value-of select="translate(concat($mixed-case-prefix, $name), '_', '')"/>;
+
+/**
+ * NUM_<xsl:value-of select="translate(concat($upper-case-prefix, $name-plural), $lower, $upper)"/>:
+ *
+ * 1 higher than the highest valid value of #<xsl:value-of select="translate(concat($mixed-case-prefix, $name), '_', '')"/>.
+ */
+#define NUM_<xsl:value-of select="translate(concat($upper-case-prefix, $name-plural), $lower, $upper)"/> (<xsl:value-of select="tp:enumvalue[position() = last()]/@value"/>+1)
+
+</xsl:template>
+
+ <xsl:template match="tp:flags/tp:flag">
+ <xsl:param name="value-prefix"/>
+ <xsl:variable name="suffix">
+ <xsl:choose>
+ <xsl:when test="@suffix">
+ <xsl:value-of select="@suffix"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="name" select="translate(concat($upper-case-prefix, $value-prefix, '_', $suffix), $lower, $upper)"/>
+
+ <xsl:if test="@name and @suffix and @name != @suffix">
+ <xsl:message terminate="yes">Flag name <xsl:value-of select="@name"/> != suffix <xsl:value-of select="@suffix"/>
+</xsl:message>
+ </xsl:if>
+ <xsl:text> </xsl:text><xsl:value-of select="$name"/> = <xsl:value-of select="@value"/>,
+</xsl:template>
+
+ <xsl:template match="tp:enum/tp:enumvalue">
+ <xsl:param name="value-prefix"/>
+ <xsl:variable name="suffix">
+ <xsl:choose>
+ <xsl:when test="@suffix">
+ <xsl:value-of select="@suffix"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:variable name="name" select="translate(concat($upper-case-prefix, $value-prefix, '_', $suffix), $lower, $upper)"/>
+
+ <xsl:if test="@name and @suffix and @name != @suffix">
+ <xsl:message terminate="yes">Flag name <xsl:value-of select="@name"/> != suffix <xsl:value-of select="@suffix"/>
+</xsl:message>
+ </xsl:if>
+
+ <xsl:if test="preceding-sibling::tp:enumvalue and number(preceding-sibling::tp:enumvalue[1]/@value) > number(@value)">
+ <xsl:message terminate="yes">Enum values must be in ascending numeric order,
+but <xsl:value-of select="$name"/> is less than the previous value
+</xsl:message>
+ </xsl:if>
+
+ <xsl:text> </xsl:text><xsl:value-of select="$name"/> = <xsl:value-of select="@value"/>,
+</xsl:template>
+
+ <xsl:template match="tp:flag">
+ <xsl:message terminate="yes">tp:flag found outside tp:flags
+</xsl:message>
+ </xsl:template>
+
+ <xsl:template match="tp:enumvalue">
+ <xsl:message terminate="yes">tp:enumvalue found outside tp:enum
+</xsl:message>
+ </xsl:template>
+
+ <xsl:template match="text()"/>
+
+ <xsl:template match="/tp:spec">
+ <xsl:if test="$mixed-case-prefix = ''">
+ <xsl:message terminate="yes">
+ <xsl:text>mixed-case-prefix param must be set&#10;</xsl:text>
+ </xsl:message>
+ </xsl:if>
+
+ <xsl:text>/* Generated from </xsl:text>
+ <xsl:value-of select="tp:title"/>
+ <xsl:if test="tp:version">
+ <xsl:text>, version </xsl:text>
+ <xsl:value-of select="tp:version"/>
+ </xsl:if>
+ <xsl:text>&#10;&#10;</xsl:text>
+ <xsl:for-each select="tp:copyright">
+ <xsl:value-of select="."/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:for-each>
+ <xsl:value-of select="tp:license"/>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:value-of select="tp:docstring"/>
+ <xsl:text>&#10; */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+</xsl:text>
+ <xsl:apply-templates select="node"/>
+ <xsl:text>
+
+#ifdef __cplusplus
+}
+#endif
+
+</xsl:text>
+ </xsl:template>
+
+</xsl:stylesheet>
+
+<!-- vim:set sw=2 sts=2 et noai noci: -->
diff --git a/tools/c-interfaces-generator.xsl b/tools/c-interfaces-generator.xsl
new file mode 100644
index 0000000..8cd2a59
--- /dev/null
+++ b/tools/c-interfaces-generator.xsl
@@ -0,0 +1,82 @@
+<!-- Stylesheet to extract C enumerations from the Telepathy spec.
+
+Copyright (C) 2006, 2007 Collabora Limited
+
+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
+Library 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
+ exclude-result-prefixes="tp">
+
+ <xsl:param name="mixed-case-prefix" select="''"/>
+
+ <xsl:variable name="PREFIX"
+ select="translate($mixed-case-prefix, $lower, $upper)"/>
+ <xsl:variable name="Prefix" select="$mixed-case-prefix"/>
+ <xsl:variable name="prefix"
+ select="translate($mixed-case-prefix, $upper, $lower)"/>
+
+ <xsl:output method="text" indent="no" encoding="ascii"/>
+
+ <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
+ <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
+
+ <xsl:template match="interface">
+ <xsl:text>/**&#10; * </xsl:text>
+ <xsl:value-of select="$PREFIX"/>
+ <xsl:text>_IFACE_</xsl:text>
+ <xsl:value-of select="translate(../@name, concat($lower, '/'), $upper)"/>
+ <xsl:text>:&#10; * &#10; * The interface name "</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>"&#10; */&#10;#define </xsl:text>
+ <xsl:value-of select="$PREFIX"/>
+ <xsl:text>_IFACE_</xsl:text>
+ <xsl:value-of select="translate(../@name, concat($lower, '/'), $upper)"/>
+ <xsl:text> \&#10;"</xsl:text>
+ <xsl:value-of select="@name"/>
+ <xsl:text>"&#10;&#10;</xsl:text>
+ </xsl:template>
+
+ <xsl:template match="text()"/>
+
+ <xsl:template match="/tp:spec">
+ <xsl:if test="$mixed-case-prefix = ''">
+ <xsl:message terminate="yes">
+ <xsl:text>mixed-case-prefix param must be set&#10;</xsl:text>
+ </xsl:message>
+ </xsl:if>
+
+ <xsl:text>/* Generated from: </xsl:text>
+ <xsl:value-of select="tp:title"/>
+ <xsl:if test="tp:version">
+ <xsl:text> version </xsl:text>
+ <xsl:value-of select="tp:version"/>
+ </xsl:if>
+ <xsl:text>&#10;&#10;</xsl:text>
+ <xsl:for-each select="tp:copyright">
+ <xsl:value-of select="."/>
+ <xsl:text>&#10;</xsl:text>
+ </xsl:for-each>
+ <xsl:text>&#10;</xsl:text>
+ <xsl:value-of select="tp:license"/>
+ <xsl:value-of select="tp:docstring"/>
+ <xsl:text>&#10; */&#10;&#10;</xsl:text>
+ <xsl:apply-templates select="node"/>
+ </xsl:template>
+
+</xsl:stylesheet>
+
+<!-- vim:set sw=2 sts=2 et noai noci: -->
diff --git a/tools/doc-generator.xsl b/tools/doc-generator.xsl
new file mode 100644
index 0000000..3b76d13
--- /dev/null
+++ b/tools/doc-generator.xsl
@@ -0,0 +1,427 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
+ exclude-result-prefixes="tp">
+ <!--Don't move the declaration of the HTML namespace up here - XMLNSs
+ don't work ideally in the presence of two things that want to use the
+ absence of a prefix, sadly. -->
+
+ <xsl:template match="*" mode="identity">
+ <xsl:copy>
+ <xsl:apply-templates mode="identity"/>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="tp:docstring">
+ <xsl:apply-templates select="node()" mode="identity"/>
+ </xsl:template>
+
+ <xsl:template match="tp:errors">
+ <h1 xmlns="http://www.w3.org/1999/xhtml">Errors</h1>
+ <xsl:apply-templates/>
+ </xsl:template>
+
+ <xsl:template match="tp:error">
+ <h2 xmlns="http://www.w3.org/1999/xhtml"><a name="{concat(../@namespace, '.', translate(@name, ' ', ''))}"></a><xsl:value-of select="concat(../@namespace, '.', translate(@name, ' ', ''))"/></h2>
+ <xsl:apply-templates select="tp:docstring"/>
+ </xsl:template>
+
+ <xsl:template match="/tp:spec/tp:copyright">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:apply-templates/>
+ </div>
+ </xsl:template>
+ <xsl:template match="/tp:spec/tp:license">
+ <div xmlns="http://www.w3.org/1999/xhtml" class="license">
+ <xsl:apply-templates mode="identity"/>
+ </div>
+ </xsl:template>
+
+ <xsl:template match="tp:copyright"/>
+ <xsl:template match="tp:license"/>
+
+ <xsl:template match="interface">
+ <h1 xmlns="http://www.w3.org/1999/xhtml"><a name="{@name}"></a><xsl:value-of select="@name"/></h1>
+
+ <xsl:if test="tp:requires">
+ <p>Implementations of this interface must also implement:</p>
+ <ul xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:for-each select="tp:requires">
+ <li><code><a href="#{@interface}"><xsl:value-of select="@interface"/></a></code></li>
+ </xsl:for-each>
+ </ul>
+ </xsl:if>
+
+ <xsl:apply-templates select="tp:docstring" />
+
+ <xsl:choose>
+ <xsl:when test="method">
+ <h2 xmlns="http://www.w3.org/1999/xhtml">Methods:</h2>
+ <xsl:apply-templates select="method"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <p xmlns="http://www.w3.org/1999/xhtml">Interface has no methods.</p>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:choose>
+ <xsl:when test="signal">
+ <h2 xmlns="http://www.w3.org/1999/xhtml">Signals:</h2>
+ <xsl:apply-templates select="signal"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <p xmlns="http://www.w3.org/1999/xhtml">Interface has no signals.</p>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:choose>
+ <xsl:when test="tp:property">
+ <h2 xmlns="http://www.w3.org/1999/xhtml">Properties:</h2>
+ <dl xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:apply-templates select="tp:property"/>
+ </dl>
+ </xsl:when>
+ <xsl:otherwise>
+ <p xmlns="http://www.w3.org/1999/xhtml">Interface has no properties.</p>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <xsl:if test="tp:enum">
+ <h2 xmlns="http://www.w3.org/1999/xhtml">Enumerated types:</h2>
+ <xsl:apply-templates select="tp:enum"/>
+ </xsl:if>
+
+ <xsl:if test="tp:flags">
+ <h2 xmlns="http://www.w3.org/1999/xhtml">Sets of flags:</h2>
+ <xsl:apply-templates select="tp:flags"/>
+ </xsl:if>
+
+ </xsl:template>
+
+ <xsl:template match="tp:flags">
+ <h3 xmlns="http://www.w3.org/1999/xhtml"><xsl:value-of select="@name"/></h3>
+ <xsl:apply-templates select="tp:docstring" />
+ <dl xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:variable name="value-prefix">
+ <xsl:choose>
+ <xsl:when test="@value-prefix">
+ <xsl:value-of select="@value-prefix"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:for-each select="tp:flag">
+ <dt xmlns="http://www.w3.org/1999/xhtml"><code><xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/></code></dt>
+ <xsl:choose>
+ <xsl:when test="tp:docstring">
+ <dd xmlns="http://www.w3.org/1999/xhtml"><xsl:apply-templates select="tp:docstring" /></dd>
+ </xsl:when>
+ <xsl:otherwise>
+ <dd xmlns="http://www.w3.org/1999/xhtml">(Undocumented)</dd>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </dl>
+ </xsl:template>
+
+ <xsl:template match="tp:enum">
+ <h3 xmlns="http://www.w3.org/1999/xhtml"><xsl:value-of select="@name"/></h3>
+ <xsl:apply-templates select="tp:docstring" />
+ <dl xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:variable name="value-prefix">
+ <xsl:choose>
+ <xsl:when test="@value-prefix">
+ <xsl:value-of select="@value-prefix"/>
+ </xsl:when>
+ <xsl:otherwise>
+ <xsl:value-of select="@name"/>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:variable>
+ <xsl:for-each select="tp:enumvalue">
+ <dt xmlns="http://www.w3.org/1999/xhtml"><code><xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/></code></dt>
+ <xsl:choose>
+ <xsl:when test="tp:docstring">
+ <dd xmlns="http://www.w3.org/1999/xhtml"><xsl:apply-templates select="tp:docstring" /></dd>
+ </xsl:when>
+ <xsl:otherwise>
+ <dd xmlns="http://www.w3.org/1999/xhtml">(Undocumented)</dd>
+ </xsl:otherwise>
+ </xsl:choose>
+ </xsl:for-each>
+ </dl>
+ </xsl:template>
+
+ <xsl:template match="tp:property">
+ <dt xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:if test="@name">
+ <code><xsl:value-of select="@name"/></code> -
+ </xsl:if>
+ <code><xsl:value-of select="@type"/></code>
+ </dt>
+ <dd xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:apply-templates select="tp:docstring"/>
+ </dd>
+ </xsl:template>
+
+ <xsl:template match="method">
+ <div xmlns="http://www.w3.org/1999/xhtml" class="method">
+ <h3 xmlns="http://www.w3.org/1999/xhtml"><xsl:value-of select="@name"/> (
+ <xsl:for-each xmlns="" select="arg[@direction='in']">
+ <xsl:value-of select="@type"/>: <xsl:value-of select="@name"/>
+ <xsl:if test="position() != last()">, </xsl:if>
+ </xsl:for-each>
+ ) &#x2192;
+ <xsl:choose>
+ <xsl:when test="arg[@direction='out']">
+ <xsl:for-each xmlns="" select="arg[@direction='out']">
+ <xsl:value-of select="@type"/>
+ <xsl:if test="position() != last()">, </xsl:if>
+ </xsl:for-each>
+ </xsl:when>
+ <xsl:otherwise>nothing</xsl:otherwise>
+ </xsl:choose>
+ </h3>
+ <div xmlns="http://www.w3.org/1999/xhtml" class="docstring">
+ <xsl:apply-templates select="tp:docstring" />
+ </div>
+
+ <xsl:if test="arg[@direction='in']">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <h4>Parameters</h4>
+ <dl xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:apply-templates select="arg[@direction='in']"
+ mode="parameters-in-docstring"/>
+ </dl>
+ </div>
+ </xsl:if>
+
+ <xsl:if test="arg[@direction='out']">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <h4>Returns</h4>
+ <dl xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:apply-templates select="arg[@direction='out']"
+ mode="returns-in-docstring"/>
+ </dl>
+ </div>
+ </xsl:if>
+
+ <xsl:if test="tp:possible-errors">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <h4>Possible errors</h4>
+ <dl xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:apply-templates select="tp:possible-errors/tp:error"/>
+ </dl>
+ </div>
+ </xsl:if>
+
+ </div>
+ </xsl:template>
+
+ <xsl:template match="arg" mode="parameters-in-docstring">
+ <dt xmlns="http://www.w3.org/1999/xhtml">
+ <code><xsl:value-of select="@name"/></code> -
+ <code><xsl:value-of select="@type"/></code>
+ </dt>
+ <dd xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:apply-templates select="tp:docstring" />
+ </dd>
+ </xsl:template>
+
+ <xsl:template match="arg" mode="returns-in-docstring">
+ <dt xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:if test="@name">
+ <code><xsl:value-of select="@name"/></code> -
+ </xsl:if>
+ <code><xsl:value-of select="@type"/></code>
+ </dt>
+ <dd xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:apply-templates select="tp:docstring"/>
+ </dd>
+ </xsl:template>
+
+ <xsl:template match="tp:possible-errors/tp:error">
+ <dt xmlns="http://www.w3.org/1999/xhtml">
+ <code><xsl:value-of select="@name"/></code>
+ </dt>
+ <dd xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:variable name="name" select="@name"/>
+ <xsl:choose>
+ <xsl:when test="tp:docstring">
+ <xsl:apply-templates select="tp:docstring"/>
+ </xsl:when>
+ <xsl:when test="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring">
+ <xsl:apply-templates select="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring"/> <em xmlns="http://www.w3.org/1999/xhtml">(generic description)</em>
+ </xsl:when>
+ <xsl:otherwise>
+ (Undocumented.)
+ </xsl:otherwise>
+ </xsl:choose>
+ </dd>
+ </xsl:template>
+
+ <xsl:template match="signal">
+ <div xmlns="http://www.w3.org/1999/xhtml" class="signal">
+ <h3 xmlns="http://www.w3.org/1999/xhtml"><xsl:value-of select="@name"/> (
+ <xsl:for-each xmlns="" select="arg">
+ <xsl:value-of select="@type"/>: <xsl:value-of select="@name"/>
+ <xsl:if test="position() != last()">, </xsl:if>
+ </xsl:for-each>
+ )</h3>
+ <div xmlns="http://www.w3.org/1999/xhtml" class="docstring">
+ <xsl:apply-templates select="tp:docstring"/>
+ </div>
+
+ <xsl:if test="arg">
+ <div xmlns="http://www.w3.org/1999/xhtml">
+ <h4>Parameters</h4>
+ <dl xmlns="http://www.w3.org/1999/xhtml">
+ <xsl:apply-templates select="arg" mode="parameters-in-docstring"/>
+ </dl>
+ </div>
+ </xsl:if>
+ </div>
+ </xsl:template>
+
+ <xsl:output method="xml" indent="no" encoding="ascii"
+ omit-xml-declaration="yes"
+ doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" />
+
+ <xsl:template match="/tp:spec">
+ <html xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>
+ <xsl:value-of select="tp:title"/>
+ <xsl:if test="tp:version">
+ <xsl:text> version </xsl:text>
+ <xsl:value-of select="tp:version"/>
+ </xsl:if>
+ </title>
+ <style type="text/css">
+
+ body {
+ font-family: sans-serif;
+ margin: 2em;
+ height: 100%;
+ font-size: 1.2em;
+ }
+ h1 {
+ padding-top: 5px;
+ padding-bottom: 5px;
+ font-size: 1.6em;
+ background: #dadae2;
+ }
+ h2 {
+ font-size: 1.3em;
+ }
+ h3 {
+ font-size: 1.2em;
+ }
+ a:link, a:visited, a:link:hover, a:visited:hover {
+ font-weight: bold;
+ }
+ .topbox {
+ padding-top: 10px;
+ padding-left: 10px;
+ border-bottom: black solid 1px;
+ padding-bottom: 10px;
+ background: #dadae2;
+ font-size: 2em;
+ font-weight: bold;
+ color: #5c5c5c;
+ }
+ .topnavbox {
+ padding-left: 10px;
+ padding-top: 5px;
+ padding-bottom: 5px;
+ background: #abacba;
+ border-bottom: black solid 1px;
+ font-size: 1.2em;
+ }
+ .topnavbox a{
+ color: black;
+ font-weight: normal;
+ }
+ .sidebar {
+ float: left;
+ /* width:9em;
+ border-right:#abacba solid 1px;
+ border-left: #abacba solid 1px;
+ height:100%; */
+ border: #abacba solid 1px;
+ padding-left: 10px;
+ margin-left: 10px;
+ padding-right: 10px;
+ margin-right: 10px;
+ color: #5d5d5d;
+ background: #dadae2;
+ }
+ .sidebar a {
+ text-decoration: none;
+ border-bottom: #e29625 dotted 1px;
+ color: #e29625;
+ font-weight: normal;
+ }
+ .sidebar h1 {
+ font-size: 1.2em;
+ color: black;
+ }
+ .sidebar ul {
+ padding-left: 25px;
+ padding-bottom: 10px;
+ border-bottom: #abacba solid 1px;
+ }
+ .sidebar li {
+ padding-top: 2px;
+ padding-bottom: 2px;
+ }
+ .sidebar h2 {
+ font-style:italic;
+ font-size: 0.81em;
+ padding-left: 5px;
+ padding-right: 5px;
+ font-weight: normal;
+ }
+ .date {
+ font-size: 0.6em;
+ float: right;
+ font-style: italic;
+ }
+ .method {
+ margin-left: 1em;
+ margin-right: 4em;
+ }
+ .signal {
+ margin-left: 1em;
+ margin-right: 4em;
+ }
+
+ </style>
+ </head>
+ <body>
+ <h1 class="topbox">
+ <xsl:value-of select="tp:title" />
+ </h1>
+ <xsl:if test="tp:version">
+ <h2>Version <xsl:apply-templates select="tp:version"/></h2>
+ </xsl:if>
+ <xsl:apply-templates select="tp:copyright"/>
+ <xsl:apply-templates select="tp:license"/>
+ <xsl:apply-templates select="tp:docstring"/>
+ <h2>Interfaces</h2>
+ <ul>
+ <xsl:for-each select="node/interface">
+ <li><code><a href="#{@name}"><xsl:value-of select="@name"/></a></code></li>
+ </xsl:for-each>
+ </ul>
+ <xsl:apply-templates select="node"/>
+ <xsl:apply-templates select="tp:errors"/>
+ </body>
+ </html>
+ </xsl:template>
+
+</xsl:stylesheet>
+
+<!-- vim:set sw=2 sts=2 et: -->
diff --git a/tools/genginterface.py b/tools/genginterface.py
new file mode 100644
index 0000000..9fbbb04
--- /dev/null
+++ b/tools/genginterface.py
@@ -0,0 +1,709 @@
+#!/usr/bin/python
+
+import sys
+import os.path
+import xml.dom.minidom
+
+def cmdline_error():
+ print """\
+usage:
+ gen-ginterface [OPTIONS] xmlfile classname
+options:
+ --include='<header.h>' (may be repeated)
+ --include='"header.h"' (ditto)
+ Include extra headers in the generated .c file
+ --signal-marshal-prefix='prefix'
+ Use the given prefix on generated signal marshallers (default is
+ derived from class name). If this is given, classname-signals-marshal.h
+ is not automatically included.
+ --filename='BASENAME'
+ Set the basename for the output files (default is derived from class
+ name)
+ --not-implemented-func='symbol'
+ Set action when methods not implemented in the interface vtable are
+ called. symbol must have signature
+ void symbol (DBusGMethodInvocation *context)
+ and return some sort of "not implemented" error via
+ dbus_g_method_return_error (context, ...)
+"""
+ sys.exit(1)
+
+def dbus_gutils_wincaps_to_uscore(s):
+ """Bug-for-bug compatible Python port of _dbus_gutils_wincaps_to_uscore
+ which gets sequences of capital letters wrong in the same way.
+ (e.g. in Telepathy, SendDTMF -> send_dt_mf)
+ """
+ ret = ''
+ for c in s:
+ if c >= 'A' and c <= 'Z':
+ length = len(ret)
+ if length > 0 and (length < 2 or ret[length-2] != '_'):
+ ret += '_'
+ ret += c.lower()
+ else:
+ ret += c
+ return ret
+
+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()
+
+class SignatureIter:
+ """Iterator over a D-Bus signature. Copied from dbus-python 0.71 so we
+ can run genginterface in a limited environment with only Python
+ (like Scratchbox).
+ """
+ def __init__(self, string):
+ self.remaining = string
+
+ def next(self):
+ if self.remaining == '':
+ raise StopIteration
+
+ signature = self.remaining
+ block_depth = 0
+ block_type = None
+ end = len(signature)
+
+ for marker in range(0, end):
+ cur_sig = signature[marker]
+
+ if cur_sig == 'a':
+ pass
+ elif cur_sig == '{' or cur_sig == '(':
+ if block_type == None:
+ block_type = cur_sig
+
+ if block_type == cur_sig:
+ block_depth = block_depth + 1
+
+ elif cur_sig == '}':
+ if block_type == '{':
+ block_depth = block_depth - 1
+
+ if block_depth == 0:
+ end = marker
+ break
+
+ elif cur_sig == ')':
+ if block_type == '(':
+ block_depth = block_depth - 1
+
+ if block_depth == 0:
+ end = marker
+ break
+
+ else:
+ if block_depth == 0:
+ end = marker
+ break
+
+ end = end + 1
+ self.remaining = signature[end:]
+ return Signature(signature[0:end])
+
+
+class Signature(str):
+ def __iter__(self):
+ return SignatureIter(self)
+
+
+def type_to_gtype(s):
+ if s == 'y': #byte
+ return ("guchar ", "G_TYPE_UCHAR","UCHAR", False)
+ elif s == 'b': #boolean
+ return ("gboolean ", "G_TYPE_BOOLEAN","BOOLEAN", False)
+ elif s == 'n': #int16
+ return ("gint ", "G_TYPE_INT","INT", False)
+ elif s == 'q': #uint16
+ return ("guint ", "G_TYPE_UINT","UINT", False)
+ elif s == 'i': #int32
+ return ("gint ", "G_TYPE_INT","INT", False)
+ elif s == 'u': #uint32
+ return ("guint ", "G_TYPE_UINT","UINT", False)
+ elif s == 'x': #int64
+ return ("gint ", "G_TYPE_INT64","INT64", False)
+ elif s == 't': #uint32
+ return ("guint ", "G_TYPE_UINT64","UINT64", False)
+ elif s == 'd': #double
+ return ("gdouble ", "G_TYPE_DOUBLE","DOUBLE", False)
+ elif s == 's': #string
+ return ("gchar *", "G_TYPE_STRING", "STRING", True)
+ elif s == 'g': #signature - FIXME
+ return ("gchar *", "DBUS_TYPE_G_SIGNATURE", "STRING", True)
+ elif s == 'o': #object path
+ return ("gchar *", "DBUS_TYPE_G_OBJECT_PATH", "STRING", True)
+ elif s == 'v': #variant
+ return ("GValue *", "G_TYPE_VALUE", "BOXED", True)
+ elif s == 'as': #array of strings
+ return ("gchar **", "G_TYPE_STRV", "BOXED", True)
+ elif s == 'ay': #byte array
+ return ("GArray *",
+ "dbus_g_type_get_collection (\"GArray\", G_TYPE_UCHAR)", "BOXED",
+ True)
+ elif s == 'au': #uint array
+ return ("GArray *", "DBUS_TYPE_G_UINT_ARRAY", "BOXED", True)
+ elif s == 'ai': #int array
+ return ("GArray *", "DBUS_TYPE_G_INT_ARRAY", "BOXED", True)
+ elif s == 'ax': #int64 array
+ return ("GArray *", "DBUS_TYPE_G_INT64_ARRAY", "BOXED", True)
+ elif s == 'at': #uint64 array
+ return ("GArray *", "DBUS_TYPE_G_UINT64_ARRAY", "BOXED", True)
+ elif s == 'ad': #double array
+ return ("GArray *", "DBUS_TYPE_G_DOUBLE_ARRAY", "BOXED", True)
+ elif s == 'ab': #boolean array
+ return ("GArray *", "DBUS_TYPE_G_BOOLEAN_ARRAY", "BOXED", True)
+ elif s[:2] == 'a(': #array of structs, recurse
+ gtype = type_to_gtype(s[1:])[1]
+ return ("GPtrArray *", "(dbus_g_type_get_collection (\"GPtrArray\", "+gtype+"))", "BOXED", True)
+ elif s == 'a{ss}': #hash table of string to string
+ return ("GHashTable *", "DBUS_TYPE_G_STRING_STRING_HASHTABLE", "BOXED", False)
+ elif s[:2] == 'a{': #some arbitrary hash tables
+ if s[2] not in ('y', 'b', 'n', 'q', 'i', 'u', 's', 'o', 'g'):
+ raise Exception, "can't index a hashtable off non-basic type " + s
+ first = type_to_gtype(s[2])
+ second = type_to_gtype(s[3:-1])
+ return ("GHashTable *", "(dbus_g_type_get_map (\"GHashTable\", " + first[1] + ", " + second[1] + "))", "BOXED", False)
+ elif s[:1] == '(': #struct
+ gtype = "(dbus_g_type_get_struct (\"GValueArray\", "
+ for subsig in Signature(s[1:-1]):
+ gtype = gtype + type_to_gtype(subsig)[1] + ", "
+ gtype = gtype + "G_TYPE_INVALID))"
+ return ("GValueArray *", gtype, "BOXED", True)
+
+ # we just don't know ..
+ raise Exception, "don't know the GType for " + s
+
+
+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
+
+def signal_to_marshal_name(signal, prefix):
+ glib_marshallers = ['VOID', 'BOOLEAN', 'CHAR', 'UCHAR', 'INT',
+ 'STRING', 'UINT', 'LONG', 'ULONG', 'ENUM', 'FLAGS', 'FLOAT',
+ 'DOUBLE', 'STRING', 'PARAM', 'BOXED', 'POINTER', 'OBJECT',
+ 'UINT_POINTER']
+
+ 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 signal_to_gtype_list(signal):
+ gtype=[]
+ for i in signal.getElementsByTagName("arg"):
+ name =i.getAttribute("name")
+ type = i.getAttribute("type")
+ gtype.append(type_to_gtype(type)[1])
+
+ return gtype
+
+
+def print_license(stream, filename, description, dom):
+ stream.write(
+"""/*
+ * %s - %s
+ *
+""" % (filename, description))
+
+ for c in dom.getElementsByTagName('tp:copyright'):
+ # assume all child nodes are text
+ stream.write(' * %s\n' % ''.join([n.data for n in c.childNodes
+ if n.nodeType in (n.TEXT_NODE,
+ n.CDATA_SECTION_NODE)]))
+
+ stream.write("""\
+ *
+ * This file may be distributed under the same terms as the specification
+ * from which it is generated.
+ */
+
+""")
+
+def print_header_begin(stream, prefix):
+ guardname = '__'+prefix.upper()+'_H__'
+ stream.write ("#ifndef "+guardname+"\n")
+ stream.write ("#define "+guardname+"\n\n")
+
+ stream.write ("#include <glib-object.h>\n#include <dbus/dbus-glib.h>\n\n")
+ stream.write ("G_BEGIN_DECLS\n\n")
+
+def print_header_end(stream, prefix):
+ guardname = '__'+prefix.upper()+'_H__'
+ stream.write ("\nG_END_DECLS\n\n")
+ stream.write ("#endif /* #ifndef "+guardname+"*/\n")
+
+def print_class_declaration(stream, prefix, classname, methods):
+ stream.write ("""\
+/**
+ * %(classname)s:
+ *
+ * Dummy typedef representing any implementation of this interface.
+ */
+typedef struct _%(classname)s %(classname)s;
+
+/**
+ * %(classname)sClass:
+ *
+ * The class of %(classname)s.
+ */
+typedef struct _%(classname)sClass %(classname)sClass;
+
+""" % locals())
+
+ stream.write(
+"""
+GType %(prefix)s_get_type (void);
+
+""" % {'prefix':prefix,'uprefix':prefix.upper()})
+
+ macro_prefix = prefix.upper().split('_',1)
+ gtype = '_TYPE_'.join(macro_prefix)
+
+ stream.write(
+"""/* TYPE MACROS */
+#define %(type)s \\
+ (%(prefix)s_get_type ())
+#define %(main)s_%(sub)s(obj) \\
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), %(type)s, %(name)s))
+#define %(main)s_IS_%(sub)s(obj) \\
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), %(type)s))
+#define %(main)s_%(sub)s_GET_CLASS(obj) \\
+ (G_TYPE_INSTANCE_GET_INTERFACE ((obj), %(type)s, %(name)sClass))
+
+""" % {"main":macro_prefix[0], "sub":macro_prefix[1], "type":gtype, "name":classname, "prefix":prefix})
+
+
+def signal_emit_stub(signal):
+ # for signal: org.freedesktop.Telepathy.Thing::StuffHappened (s, u)
+ # emit: void tp_svc_thing_emit_stuff_happened (gpointer instance,
+ # const char *arg, guint arg2)
+ dbus_name = signal.getAttributeNode("name").nodeValue
+ c_emitter_name = prefix + '_emit_' + camelcase_to_lower(dbus_name)
+ c_signal_const_name = 'SIGNAL_' + dbus_name
+
+ macro_prefix = prefix.upper().split('_',1)
+
+ decl = 'void ' + c_emitter_name + ' (gpointer instance'
+ args = ''
+ argdoc = ''
+
+ for i in signal.getElementsByTagName("arg"):
+ name = i.getAttribute("name")
+ type = i.getAttribute("type")
+ info = type_to_gtype(type)
+ gtype = info[0]
+ if gtype[3]:
+ gtype = 'const ' + gtype
+ decl += ',\n ' + gtype + ' ' + name
+ args += ', ' + name
+ argdoc += ' * @' + name + ': FIXME: document args in genginterface\n'
+ decl += ')'
+
+ doc = ("""\
+/**
+ * %s:
+ * @instance: An object implementing this interface
+%s *
+ * Emit the %s D-Bus signal from @instance with the given arguments.
+ */
+""" % (c_emitter_name, argdoc, dbus_name))
+
+ header = decl + ';\n\n'
+ body = doc + decl + ('\n{\n'
+ ' g_assert (%s_IS_%s (instance));\n'
+ ' g_signal_emit (instance, signals[%s], 0%s);\n'
+ '}\n\n'
+ % (macro_prefix[0], macro_prefix[1], c_signal_const_name,
+ args))
+
+ return header, body
+
+
+def print_class_definition(stream, prefix, classname, methods):
+ stream.write ("struct _%sClass {\n" % classname)
+ stream.write (" GTypeInterface parent_class;\n")
+
+ for method in methods:
+ dbus_method_name = method.getAttributeNode("name").nodeValue
+ lc_method_name = camelcase_to_lower(dbus_method_name)
+ c_impl_name = prefix + '_' + lc_method_name + '_impl'
+ stream.write(' %s %s;\n' % (c_impl_name, lc_method_name))
+
+ stream.write ("};\n\n")
+
+
+def cmp_by_name(node1, node2):
+ return cmp(node1.getAttributeNode("name").nodeValue,
+ node2.getAttributeNode("name").nodeValue)
+
+
+def do_method(method):
+ # DoStuff (s -> u)
+ dbus_method_name = method.getAttributeNode("name").nodeValue
+ lc_method_name = camelcase_to_lower(dbus_method_name)
+ # void tp_svc_thing_do_stuff (TpSvcThing *, const char *,
+ # DBusGMethodInvocation *);
+ c_method_name = prefix + '_' + lc_method_name
+ # typedef void (*tp_svc_thing_do_stuff_impl) (TpSvcThing *, const char *,
+ # DBusGMethodInvocation *);
+ c_impl_name = prefix + '_' + lc_method_name + '_impl'
+ # void tp_svc_thing_return_from_do_stuff (DBusGMethodInvocation *, guint);
+ ret_method_name = prefix + '_return_from_' + lc_method_name
+
+ ret_count=0
+
+ header = ''
+ body = ''
+
+ c_decl = "static void\n"
+ method_decl = "typedef void (*" + c_impl_name + ') ('
+ ret_decl = 'void\n'
+ ret_body = '{\n dbus_g_method_return (dbus_context'
+ arg_doc = ''
+ ret_arg_doc = ''
+
+ tmp = c_method_name+' ('
+ pad = ' ' * len(tmp)
+ c_decl += tmp+classname+' *self'
+
+ method_pad = ' ' * len(method_decl)
+ method_decl += classname + ' *self'
+ args = 'self'
+
+ tmp = ret_method_name+' ('
+ ret_pad = ' ' * len(tmp)
+ ret_decl += tmp+'DBusGMethodInvocation *dbus_context'
+
+ for i in method.getElementsByTagName("arg"):
+ name =i.getAttribute("name")
+ direction = i.getAttribute("direction")
+ type = i.getAttribute("type")
+
+ if not name and direction == "out":
+ if ret_count==0:
+ name = "ret"
+ else:
+ name = "ret"+str(ret_count)
+ ret_count += 1
+
+ gtype = type_to_gtype(type)[0]
+ if type_to_gtype(type)[3]:
+ gtype="const "+gtype
+ if direction != "out":
+ c_decl +=",\n"+pad+gtype+name
+ method_decl +=",\n"+method_pad+gtype+name
+ args += ', '+name
+ arg_doc += (' * @' + name
+ + ': FIXME: document args in genginterface\n')
+ else:
+ ret_decl += ",\n"+ret_pad+gtype+name
+ ret_body += ', '+name
+ ret_arg_doc += (' * @' + name
+ + ': FIXME: document args in genginterface\n')
+
+ c_decl += ",\n"+pad+"DBusGMethodInvocation *context)"
+ method_decl += ",\n"+method_pad+"DBusGMethodInvocation *context);\n"
+ args += ', context'
+
+ ret_doc = ("""\
+/**
+ * %s:
+ * @dbus_context: The D-Bus method invocation context
+%s *
+ * Return successfully by calling dbus_g_method_return (@dbus_context,
+ * ...). This inline function is just a type-safe wrapper for
+ * dbus_g_method_return.
+ */
+""" % (ret_method_name, ret_arg_doc))
+
+ interface = method.parentNode.getAttribute("name");
+ ret_decl += ')\n'
+ ret_body += ');\n}\n'
+ header += (ret_doc + 'static inline\n/**/\n' + ret_decl + ';\n'
+ + 'static inline ' + ret_decl + ret_body)
+ body += (
+"""
+/**
+ * %(c_impl_name)s
+ * @self: The object implementing this interface
+%(arg_doc)s * @context: The D-Bus invocation context to use to return values
+ * or throw an error.
+ *
+ * Signature of an implementation of D-Bus method %(dbus_method_name)s
+ * on interface %(interface)s
+ */
+""" % locals())
+
+ body += c_decl+"\n{\n"
+ body += " %s impl = (%s_GET_CLASS (self)->%s);\n" % (
+ c_impl_name, prefix.upper(), lc_method_name)
+ body += " if (impl)\n"
+ body += " (impl) (%s);\n" % args
+ body += " else\n"
+ if not_implemented_func:
+ body += " %s (context);\n" % not_implemented_func
+ else:
+ # this seems as appropriate an error as any
+ body += """\
+ {
+ GError e = { DBUS_GERROR, DBUS_GERROR_UNKNOWN_METHOD,
+ "Method not implemented" };
+
+ dbus_g_method_return_error (context, &e);
+ }
+"""
+ body += "}\n\n"
+
+ dg_method_name = prefix + '_' + dbus_gutils_wincaps_to_uscore(dbus_method_name)
+ if dg_method_name != c_method_name:
+ body += ("""\
+#define %(dg_method_name)s %(c_method_name)s
+
+""" % {'dg_method_name': dg_method_name, 'c_method_name': c_method_name })
+
+ method_decl += 'void %s_implement_%s (%sClass *klass, %s impl);\n\n' \
+ % (prefix, lc_method_name, classname, c_impl_name)
+
+ body += ("""\
+/**
+ * %s_implement_%s:
+ * @klass: A class whose instances implement this interface
+ * @impl: A callback used to implement the %s method
+ *
+ * Register an implementation for the %s method in the vtable of an
+ * implementation of this interface. To be called from the interface
+ * init function.
+ */
+""" % (prefix, lc_method_name, dbus_method_name, dbus_method_name))
+ body += 'void\n%s_implement_%s (%sClass *klass, %s impl)\n{\n'\
+ % (prefix, lc_method_name, classname, c_impl_name)
+ body += ' klass->%s = impl;\n' % lc_method_name
+ body += '}\n\n'
+
+ return (method_decl, header, body)
+
+if __name__ == '__main__':
+ from getopt import gnu_getopt
+
+ options, argv = gnu_getopt(sys.argv[1:], '',
+ ['filename=', 'signal-marshal-prefix=',
+ 'include=',
+ 'not-implemented-func='])
+
+ try:
+ classname = argv[1]
+ except IndexError:
+ cmdline_error()
+
+ prefix = camelcase_to_lower(classname)
+
+ basename = prefix.replace('_', '-')
+ signal_marshal_prefix = prefix
+ headers = []
+ not_implemented_func = ''
+
+ for option, value in options:
+ if option == '--filename':
+ basename = value
+ elif option == '--signal-marshal-prefix':
+ signal_marshal_prefix = value
+ elif option == '--include':
+ if value[0] not in '<"':
+ value = '"%s"' % value
+ headers.append(value)
+ elif option == '--not-implemented-func':
+ not_implemented_func = value
+
+ outname_header = basename + ".h"
+ outname_body = basename + ".c"
+ outname_signal_marshal = basename + "-signals-marshal.list"
+
+ header=open(outname_header,'w')
+ body=open(outname_body, 'w')
+
+ signal_marshal=open(outname_signal_marshal, 'w')
+
+ try:
+ dom = xml.dom.minidom.parse(argv[0])
+ except IndexError:
+ cmdline_error()
+
+ signals = dom.getElementsByTagName("signal")
+ signals.sort(cmp_by_name)
+ methods = dom.getElementsByTagName("method")
+ methods.sort(cmp_by_name)
+
+ print_license(header, outname_header, "Header for " + classname, dom)
+ print_license(body, outname_body, "Source for " + classname, dom)
+ print_header_begin(header,prefix)
+
+ print_class_declaration(header, prefix, classname, methods)
+
+ # include my own header first, to ensure self-contained
+ body.write(
+"""#include "%s"
+
+""" % outname_header)
+
+ # required headers
+ body.write(
+"""#include <stdio.h>
+#include <stdlib.h>
+
+""")
+
+ for h in headers:
+ body.write('#include %s\n' % h)
+ body.write('\n')
+
+ if signal_marshal_prefix == prefix:
+ body.write('#include "%s-signals-marshal.h"\n' % basename)
+ # else assume the signal marshallers are declared in one of the headers
+
+ body.write('const DBusGObjectInfo dbus_glib_%s_object_info;\n'
+ % prefix)
+
+ print_class_definition(body, prefix, classname, methods)
+
+ if signals:
+ body.write('enum {\n')
+ for signal in signals:
+ dbus_name = signal.getAttributeNode("name").nodeValue
+ body.write(' SIGNAL_%s,\n' % (dbus_name))
+ body.write(' N_SIGNALS\n};\nstatic guint signals[N_SIGNALS] = {0};\n\n')
+
+ gtypename = '_TYPE_'.join(prefix.upper().split('_',1))
+
+ body.write(
+"""
+static void
+%(prefix)s_base_init (gpointer klass)
+{
+ static gboolean initialized = FALSE;
+
+ if (!initialized)
+ {
+ initialized = TRUE;
+""" % {'classname':classname, 'gtypename':gtypename, 'prefix':prefix, 'uprefix':prefix.upper()})
+
+ header.write("\n")
+
+ marshallers = {}
+ for signal in signals:
+ dbus_name = signal.getAttributeNode("name").nodeValue
+ gtypelist = signal_to_gtype_list(signal)
+ marshal_name = signal_to_marshal_name(signal, signal_marshal_prefix)
+
+ body.write(
+"""
+ signals[SIGNAL_%s] =
+ g_signal_new ("%s",
+ G_OBJECT_CLASS_TYPE (klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
+ 0,
+ NULL, NULL,
+ %s,
+ G_TYPE_NONE, %s);
+""" % (dbus_name,
+ (dbus_gutils_wincaps_to_uscore(dbus_name)).replace('_','-'),
+ marshal_name,
+ ', '.join([str(len(gtypelist))] + gtypelist)))
+
+ if not marshal_name.startswith('g_cclosure_marshal_VOID__'):
+ mtype = signal_to_marshal_type(signal)
+ assert(len(mtype))
+ marshallers[','.join(mtype)] = True
+
+ for marshaller in marshallers:
+ signal_marshal.write("VOID:"+marshaller+"\n")
+
+ body.write(
+"""
+ dbus_g_object_type_install_info (%(prefix)s_get_type (), &dbus_glib_%(prefix)s_object_info);
+ }
+}
+
+GType
+%(prefix)s_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0)) {
+ static const GTypeInfo info = {
+ sizeof (%(classname)sClass),
+ %(prefix)s_base_init, /* base_init */
+ NULL, /* base_finalize */
+ NULL, /* class_init */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ 0,
+ 0, /* n_preallocs */
+ NULL /* instance_init */
+ };
+
+ type = g_type_register_static (G_TYPE_INTERFACE, "%(classname)s", &info, 0);
+ }
+
+ return type;
+}
+
+""" % {'classname':classname,'prefix':prefix, 'uprefix':prefix.upper()})
+
+ for method in methods:
+ m, h, b = do_method(method)
+ header.write(m + '\n')
+ header.write(h)
+ body.write(b)
+
+ for signal in signals:
+ h, b = signal_emit_stub(signal)
+ header.write(h)
+ body.write(b)
+
+ header.write('\n')
+
+ body.write("""\
+#include "%s-glue.h"
+
+""" % (basename))
+
+ print_header_end(header,prefix)
+ header.close()
+ body.close()
diff --git a/tools/ls-interfaces.xsl b/tools/ls-interfaces.xsl
new file mode 100644
index 0000000..7b970ce
--- /dev/null
+++ b/tools/ls-interfaces.xsl
@@ -0,0 +1,33 @@
+<!--
+Extract a space-separated list of interface classnames from the Telepathy spec.
+
+Copyright (C) 2006, 2007 Collabora Limited
+
+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
+Library 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+-->
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+ <xsl:output method="text" indent="no" encoding="ascii"/>
+
+ <xsl:template match="text()"/>
+
+ <xsl:template match="node">
+ <xsl:value-of select="concat(' ', translate(@name, '/', ''), ' ')"/>
+ </xsl:template>
+
+</xsl:stylesheet>
+
+<!-- vim:set sw=2 sts=2 et noai noci: -->
diff --git a/tools/make-all-async.xsl b/tools/make-all-async.xsl
new file mode 100644
index 0000000..1dec391
--- /dev/null
+++ b/tools/make-all-async.xsl
@@ -0,0 +1,22 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+
+ <xsl:output method="xml" indent="yes" encoding="ascii"/>
+
+ <xsl:template match="method">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ <xsl:if test="not(annotation[name='org.freedesktop.DBus.GLib.Async'])">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ </xsl:if>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="@*|node()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*|node()"/>
+ </xsl:copy>
+ </xsl:template>
+
+</xsl:stylesheet>
+
+<!-- vim:set sw=2 sts=2 et: -->
diff --git a/tools/spec-to-introspect.xsl b/tools/spec-to-introspect.xsl
new file mode 100644
index 0000000..1eefd3d
--- /dev/null
+++ b/tools/spec-to-introspect.xsl
@@ -0,0 +1,26 @@
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
+ exclude-result-prefixes="tp">
+
+ <xsl:template match="*">
+ <xsl:copy>
+ <xsl:for-each select="@*">
+ <xsl:if test="not(starts-with(name(), 'tp:'))">
+ <xsl:copy/>
+ </xsl:if>
+ </xsl:for-each>
+ <xsl:apply-templates/>
+ </xsl:copy>
+ </xsl:template>
+
+ <xsl:template match="tp:*"/>
+ <xsl:template match="text()"/>
+
+ <xsl:output method="xml" indent="yes" encoding="UTF-8"
+ omit-xml-declaration="no"
+ doctype-system="http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"
+ doctype-public="-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" />
+
+</xsl:stylesheet>
+
+<!-- vim:set sw=2 sts=2 et: -->
diff --git a/tools/update-spec-gen-am.sh b/tools/update-spec-gen-am.sh
new file mode 100644
index 0000000..b484846
--- /dev/null
+++ b/tools/update-spec-gen-am.sh
@@ -0,0 +1,75 @@
+#!/bin/sh
+
+mk_specdir="extensions"
+mk_toolsdir="extensions/tools"
+
+test -n "$XSLTPROC" || XSLTPROC=xsltproc
+test -n "$TOP_SRCDIR" || TOP_SRCDIR=../..
+
+toolsdir="${TOP_SRCDIR}/${mk_toolsdir}"
+specdir="${TOP_SRCDIR}/${mk_specdir}"
+
+outfile="$1"
+gendir="$2"
+whitelist="$3"
+
+SPEC_INTERFACES="`$XSLTPROC --nonet --novalid --xinclude $toolsdir/ls-interfaces.xsl $specdir/all.xml`"
+
+install -d ./`dirname "$outfile"`
+exec > "$outfile.tmp"
+
+echo "# Rules to re-generate this file"
+printf "$outfile: \$(top_srcdir)/$mk_specdir/all.xml $whitelist \\\\\\n"
+printf "\\t\\t\$(top_srcdir)/$mk_specdir/all.xml \\\\\\n"
+printf "\\t\\t\$(SPEC_INTERFACE_XMLS) \\\\\\n"
+printf "\\t\\t\$(top_srcdir)/$mk_toolsdir/ls-interfaces.xsl \\\\\\n"
+printf "\\t\\t\$(top_builddir)/$mk_toolsdir/update-spec-gen-am.sh\\n"
+printf "\\tXSLTPROC=xsltproc TOP_SRCDIR=\$(top_srcdir) \$(SHELL) \$(top_builddir)/$mk_toolsdir/update-spec-gen-am.sh $outfile $gendir $whitelist\\n"
+echo
+
+for class in INTERFACES INTERFACE_XMLS GENERATED_CS GENERATED_HS \
+ GENERATED_LISTS GLUE_HS
+do
+ if test -z "$whitelist"
+ then
+ echo "SPEC_$class ="
+ else
+ echo "STABLE_SPEC_$class ="
+ echo "UNSTABLE_SPEC_$class ="
+ fi
+done
+
+for iface in $SPEC_INTERFACES
+do
+ if test -z "$whitelist"
+ then
+ # just output the combined variables directly
+ stability=
+ elif grep "^$iface\$" "$whitelist" >/dev/null
+ then
+ stability=STABLE_
+ else
+ stability=UNSTABLE_
+ fi
+ echo "${stability}SPEC_INTERFACES += $iface"
+ echo "${stability}SPEC_INTERFACE_XMLS += \$(top_srcdir)/$mk_specdir/$iface.xml"
+ if test -n "$gendir"
+ then
+ echo "${stability}SPEC_GENERATED_CS += $gendir/svc-$iface.c"
+ echo "${stability}SPEC_GENERATED_HS += $gendir/svc-$iface.h"
+ echo "${stability}SPEC_GLUE_HS += $gendir/svc-$iface-glue.h"
+ echo "${stability}SPEC_GENERATED_LISTS +="\
+ "$gendir/svc-$iface-signals-marshal.list"
+ fi
+done
+
+if test -n "$whitelist"
+then
+ for class in INTERFACES INTERFACE_XMLS GENERATED_CS GENERATED_HS \
+ GENERATED_LISTS GLUE_HS
+ do
+ echo "SPEC_$class = \$(STABLE_SPEC_$class) \$(UNSTABLE_SPEC_$class)"
+ done
+fi
+
+mv "$outfile.tmp" "$outfile"