diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2009-06-10 16:32:14 +0100 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2009-06-10 16:32:14 +0100 |
commit | dc8913f12aae3ec6fcd3f054317c786dfe5f7788 (patch) | |
tree | c5b32ad7f980d4cd3b65dd501a3b3f64caa7e00c /tools | |
parent | cdd588d0774111f3f8975ac4643b5a77f728dbcc (diff) |
tools: update from telepathy-glib
This requires a minor change to the invocation: when making docs,
explicitly allow dangling references to interfaces.
Diffstat (limited to 'tools')
-rw-r--r-- | tools/doc-generator.xsl | 432 | ||||
-rw-r--r-- | tools/glib-client-gen.py | 597 | ||||
-rw-r--r-- | tools/glib-ginterface-gen.py | 101 | ||||
-rw-r--r-- | tools/glib-gtypes-generator.py | 82 | ||||
-rw-r--r-- | tools/libglibcodegen.py | 9 | ||||
-rw-r--r-- | tools/libtpcodegen.py | 67 |
6 files changed, 821 insertions, 467 deletions
diff --git a/tools/doc-generator.xsl b/tools/doc-generator.xsl index 24e85456..76fc9696 100644 --- a/tools/doc-generator.xsl +++ b/tools/doc-generator.xsl @@ -23,10 +23,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" xmlns:html="http://www.w3.org/1999/xhtml" exclude-result-prefixes="tp html"> - <!--Don't move the declaration of the HTML namespace up here - XMLNSs + <!--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:param name="allow-undefined-interfaces" select="false()"/> + <xsl:template match="html:* | @*" mode="html"> <xsl:copy> <xsl:apply-templates mode="html"/> @@ -39,6 +41,86 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA </xsl:call-template> </xsl:template> + <!-- tp:dbus-ref: reference a D-Bus interface, signal, method or property --> + <xsl:template match="tp:dbus-ref" mode="html"> + <xsl:variable name="name"> + <xsl:choose> + <xsl:when test="@namespace"> + <xsl:value-of select="@namespace"/> + <xsl:text>.</xsl:text> + </xsl:when> + </xsl:choose> + <xsl:value-of select="string(.)"/> + </xsl:variable> + + <xsl:choose> + <xsl:when test="//interface[@name=$name] + or //interface/method[concat(../@name, '.', @name)=$name] + or //interface/signal[concat(../@name, '.', @name)=$name] + or //interface/property[concat(../@name, '.', @name)=$name] + or //interface[@name=concat($name, '.DRAFT')] + or //interface/method[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + or //interface/signal[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + or //interface/property[ + concat(../@name, '.', @name)=concat($name, '.DRAFT')] + "> + <a xmlns="http://www.w3.org/1999/xhtml" href="#{$name}"> + <xsl:value-of select="string(.)"/> + </a> + </xsl:when> + + <xsl:when test="$allow-undefined-interfaces"> + <span xmlns="http://www.w3.org/1999/xhtml" title="defined elsewhere"> + <xsl:value-of select="string(.)"/> + </span> + </xsl:when> + + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: cannot find D-Bus interface, method, </xsl:text> + <xsl:text>signal or property called '</xsl:text> + <xsl:value-of select="$name"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:template> + + <!-- tp:member-ref: reference a property of the current interface --> + <xsl:template match="tp:member-ref" mode="html"> + <xsl:variable name="prefix" select="concat(ancestor::interface/@name, + '.')"/> + <xsl:variable name="name" select="string(.)"/> + + <xsl:if test="not(ancestor::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: Cannot use tp:member-ref when not in an</xsl:text> + <xsl:text> <interface> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:choose> + <xsl:when test="ancestor::interface/signal[@name=$name]"/> + <xsl:when test="ancestor::interface/method[@name=$name]"/> + <xsl:when test="ancestor::interface/property[@name=$name]"/> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: interface </xsl:text> + <xsl:value-of select="ancestor::interface/@name"/> + <xsl:text> has no signal/method/property called </xsl:text> + <xsl:value-of select="$name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + + <a xmlns="http://www.w3.org/1999/xhtml" href="#{$prefix}{$name}"> + <xsl:value-of select="$name"/> + </a> + </xsl:template> + <xsl:template match="*" mode="identity"> <xsl:copy> <xsl:apply-templates mode="identity"/> @@ -46,18 +128,20 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA </xsl:template> <xsl:template match="tp:docstring"> - <xsl:apply-templates select="text() | html:* | tp:rationale" mode="html"/> + <xsl:apply-templates mode="html"/> </xsl:template> <xsl:template match="tp:added"> - <p class="added">Added in version <xsl:value-of select="@version"/>. + <p class="added" xmlns="http://www.w3.org/1999/xhtml">Added in + version <xsl:value-of select="@version"/>. <xsl:apply-templates select="node()" mode="html"/></p> </xsl:template> <xsl:template match="tp:changed"> <xsl:choose> <xsl:when test="node()"> - <p class="changed">Changed in version <xsl:value-of select="@version"/>: + <p class="changed" xmlns="http://www.w3.org/1999/xhtml">Changed in + version <xsl:value-of select="@version"/>: <xsl:apply-templates select="node()" mode="html"/></p> </xsl:when> <xsl:otherwise> @@ -68,8 +152,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA </xsl:template> <xsl:template match="tp:deprecated"> - <p class="deprecated">Deprecated since version - <xsl:value-of select="@version"/>. + <p class="deprecated" xmlns="http://www.w3.org/1999/xhtml">Deprecated + since version <xsl:value-of select="@version"/>. <xsl:apply-templates select="node()" mode="html"/></p> </xsl:template> @@ -131,7 +215,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <xsl:template match="/tp:spec/tp:copyright"> <div xmlns="http://www.w3.org/1999/xhtml"> - <xsl:apply-templates/> + <xsl:apply-templates mode="text"/> </div> </xsl:template> <xsl:template match="/tp:spec/tp:license"> @@ -224,6 +308,21 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA </xsl:template> <xsl:template match="tp:flags"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:flags type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:flags type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + <h3> <a name="type-{@name}"> <xsl:value-of select="@name"/> @@ -264,6 +363,21 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA </xsl:template> <xsl:template match="tp:enum"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:enum type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:enum type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + <h3 xmlns="http://www.w3.org/1999/xhtml"> <a name="type-{@name}"> <xsl:value-of select="@name"/> @@ -304,11 +418,38 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA </xsl:template> <xsl:template match="property"> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: property </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a property of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on property </xsl:text> + <xsl:value-of select="concat(../@name, '.', @name)"/> + <xsl:text>: '</xsl:text> + <xsl:value-of select="@access"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:if> + <dt xmlns="http://www.w3.org/1999/xhtml"> <a name="{concat(../@name, '.', @name)}"> <code><xsl:value-of select="@name"/></code> </a> - <xsl:text> - </xsl:text> + <xsl:text> − </xsl:text> <code><xsl:value-of select="@type"/></code> <xsl:call-template name="parenthesized-tp-type"/> <xsl:text>, </xsl:text> @@ -323,8 +464,14 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <xsl:text>read/write</xsl:text> </xsl:when> <xsl:otherwise> - <xsl:text>access: </xsl:text> - <code><xsl:value-of select="@access"/></code> + <xsl:message terminate="yes"> + <xsl:text>ERR: unknown or missing value for </xsl:text> + <xsl:text>@access on property </xsl:text> + <xsl:value-of select="concat(../@name, '.', @name)"/> + <xsl:text>: '</xsl:text> + <xsl:value-of select="@access"/> + <xsl:text>' </xsl:text> + </xsl:message> </xsl:otherwise> </xsl:choose> </dt> @@ -339,7 +486,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <xsl:template match="tp:property"> <dt xmlns="http://www.w3.org/1999/xhtml"> <xsl:if test="@name"> - <code><xsl:value-of select="@name"/></code> - + <code><xsl:value-of select="@name"/></code> − </xsl:if> <code><xsl:value-of select="@type"/></code> </dt> @@ -356,7 +503,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <h3> <a name="type-{@name}"> <xsl:value-of select="@name"/> - </a> - a{ + </a> − a{ <xsl:for-each select="tp:member"> <xsl:value-of select="@type"/> <xsl:text>: </xsl:text> @@ -386,15 +533,30 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <xsl:template match="tp:simple-type | tp:enum | tp:flags | tp:external-type" mode="in-index"> - - <xsl:value-of select="@type"/> + − <xsl:value-of select="@type"/> </xsl:template> <xsl:template match="tp:simple-type"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:simple-type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:simple-type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + <div xmlns="http://www.w3.org/1999/xhtml" class="simple-type"> <h3> <a name="type-{@name}"> <xsl:value-of select="@name"/> - </a> - <xsl:value-of select="@type"/> + </a> − <xsl:value-of select="@type"/> </h3> <div class="docstring"> <xsl:apply-templates select="tp:docstring"/> @@ -406,25 +568,40 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA </xsl:template> <xsl:template match="tp:external-type"> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a tp:external-type </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @type on tp:external-type</xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + <div xmlns="http://www.w3.org/1999/xhtml" class="external-type"> <dt> <a name="type-{@name}"> <xsl:value-of select="@name"/> - </a> - <xsl:value-of select="@type"/> + </a> − <xsl:value-of select="@type"/> </dt> <dd>Defined by: <xsl:value-of select="@from"/></dd> </div> </xsl:template> <xsl:template match="tp:struct" mode="in-index"> - - ( <xsl:for-each select="tp:member"> + − ( <xsl:for-each select="tp:member"> <xsl:value-of select="@type"/> <xsl:if test="position() != last()">, </xsl:if> </xsl:for-each> ) </xsl:template> <xsl:template match="tp:mapping" mode="in-index"> - - a{ <xsl:for-each select="tp:member"> + − a{ <xsl:for-each select="tp:member"> <xsl:value-of select="@type"/> <xsl:if test="position() != last()"> → </xsl:if> </xsl:for-each> } @@ -435,7 +612,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <h3> <a name="type-{@name}"> <xsl:value-of select="@name"/> - </a> - ( + </a> − ( <xsl:for-each select="tp:member"> <xsl:value-of select="@type"/> <xsl:text>: </xsl:text> @@ -471,6 +648,64 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA </xsl:template> <xsl:template match="method"> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: method </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a method of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:for-each select="arg"> + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no type</xsl:text> + </xsl:message> + </xsl:if> + <xsl:choose> + <xsl:when test="@direction='in'"> + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an 'in' arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if> + </xsl:when> + <xsl:when test="@direction='out'"> + <!-- FIXME: This is commented out until someone with a lot of time + on their hands goes through the spec adding names to all the "out" + arguments + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="no"> + <xsl:text>INFO: an 'out' arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if>--> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of method </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has direction neither 'in' nor 'out'</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + <div xmlns="http://www.w3.org/1999/xhtml" class="method"> <h3 xmlns="http://www.w3.org/1999/xhtml"> <a name="{concat(../@name, concat('.', @name))}"> @@ -532,6 +767,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <xsl:template name="tp-type"> <xsl:param name="tp-type"/> + <xsl:param name="type"/> <xsl:variable name="single-type"> <xsl:choose> @@ -544,30 +780,73 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA </xsl:choose> </xsl:variable> - <xsl:choose> - <xsl:when test="//tp:simple-type[@name=$single-type]" /> - <xsl:when test="//tp:struct[@name=$single-type]" /> - <xsl:when test="//tp:enum[@name=$single-type]" /> - <xsl:when test="//tp:flags[@name=$single-type]" /> - <xsl:when test="//tp:mapping[@name=$single-type]" /> - <xsl:when test="//tp:external-type[@name=$single-type]" /> - <xsl:otherwise> - <xsl:message terminate="yes"> - <xsl:text>ERR: Unable to find type '</xsl:text> - <xsl:value-of select="$tp-type"/> - <xsl:text>' </xsl:text> - </xsl:message> - </xsl:otherwise> - </xsl:choose> + <xsl:variable name="type-of-tp-type"> + <xsl:if test="contains($tp-type, '[]')"> + <!-- one 'a', plus one for each [ after the [], and delete all ] --> + <xsl:value-of select="concat('a', + translate(substring-after($tp-type, '[]'), '[]', 'a'))"/> + </xsl:if> + + <xsl:choose> + <xsl:when test="//tp:simple-type[@name=$single-type]"> + <xsl:value-of select="string(//tp:simple-type[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:struct[@name=$single-type]"> + <xsl:text>(</xsl:text> + <xsl:for-each select="//tp:struct[@name=$single-type]/tp:member"> + <xsl:value-of select="@type"/> + </xsl:for-each> + <xsl:text>)</xsl:text> + </xsl:when> + <xsl:when test="//tp:enum[@name=$single-type]"> + <xsl:value-of select="string(//tp:enum[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:flags[@name=$single-type]"> + <xsl:value-of select="string(//tp:flags[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:when test="//tp:mapping[@name=$single-type]"> + <xsl:text>a{</xsl:text> + <xsl:for-each select="//tp:mapping[@name=$single-type]/tp:member"> + <xsl:value-of select="@type"/> + </xsl:for-each> + <xsl:text>}</xsl:text> + </xsl:when> + <xsl:when test="//tp:external-type[@name=$single-type]"> + <xsl:value-of select="string(//tp:external-type[@name=$single-type]/@type)"/> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: Unable to find type '</xsl:text> + <xsl:value-of select="$tp-type"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:variable> + + <xsl:if test="string($type) != '' and + string($type-of-tp-type) != string($type)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: tp:type '</xsl:text> + <xsl:value-of select="$tp-type"/> + <xsl:text>' has D-Bus type '</xsl:text> + <xsl:value-of select="$type-of-tp-type"/> + <xsl:text>' but has been used with type='</xsl:text> + <xsl:value-of select="$type"/> + <xsl:text>' </xsl:text> + </xsl:message> + </xsl:if> + <a href="#type-{$single-type}"><xsl:value-of select="$tp-type"/></a> </xsl:template> <xsl:template name="parenthesized-tp-type"> <xsl:if test="@tp:type"> - <xsl:text>(</xsl:text> + <xsl:text> (</xsl:text> <xsl:call-template name="tp-type"> <xsl:with-param name="tp-type" select="@tp:type"/> + <xsl:with-param name="type" select="@type"/> </xsl:call-template> <xsl:text>)</xsl:text> </xsl:if> @@ -575,7 +854,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <xsl:template match="tp:member" mode="members-in-docstring"> <dt xmlns="http://www.w3.org/1999/xhtml"> - <code><xsl:value-of select="@name"/></code> - + <code><xsl:value-of select="@name"/></code> − <code><xsl:value-of select="@type"/></code> <xsl:call-template name="parenthesized-tp-type"/> </dt> @@ -593,7 +872,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <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="@name"/></code> − <code><xsl:value-of select="@type"/></code> <xsl:call-template name="parenthesized-tp-type"/> </dt> @@ -605,7 +884,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <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> - + <code><xsl:value-of select="@name"/></code> − </xsl:if> <code><xsl:value-of select="@type"/></code> <xsl:call-template name="parenthesized-tp-type"/> @@ -636,6 +915,57 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA </xsl:template> <xsl:template match="signal"> + + <xsl:if test="not(parent::interface)"> + <xsl:message terminate="yes"> + <xsl:text>ERR: signal </xsl:text> + <xsl:value-of select="@name"/> + <xsl:text> does not have an interface as parent </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: missing @name on a signal of </xsl:text> + <xsl:value-of select="../@name"/> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:if> + + <xsl:for-each select="arg"> + <xsl:if test="not(@type) or @type = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no type</xsl:text> + </xsl:message> + </xsl:if> + <xsl:if test="not(@name) or @name = ''"> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has no name</xsl:text> + </xsl:message> + </xsl:if> + <xsl:choose> + <xsl:when test="not(@direction)"/> + <xsl:when test="@direction='in'"> + <xsl:message terminate="no"> + <xsl:text>INFO: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has unnecessary direction 'in'</xsl:text> + </xsl:message> + </xsl:when> + <xsl:otherwise> + <xsl:message terminate="yes"> + <xsl:text>ERR: an arg of signal </xsl:text> + <xsl:value-of select="concat(../../@name, '.', ../@name)"/> + <xsl:text> has direction other than 'in'</xsl:text> + </xsl:message> + </xsl:otherwise> + </xsl:choose> + </xsl:for-each> + <div xmlns="http://www.w3.org/1999/xhtml" class="signal"> <h3 xmlns="http://www.w3.org/1999/xhtml"> <a name="{concat(../@name, concat('.', @name))}"> @@ -788,6 +1118,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA color: #ff0000; background: #ffffff; } + table, tr, td, th { + border: 1px solid #666; + } </style> </head> @@ -796,7 +1129,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA <xsl:value-of select="tp:title" /> </h1> <xsl:if test="tp:version"> - <h2>Version <xsl:apply-templates select="tp:version"/></h2> + <h2>Version <xsl:value-of select="string(tp:version)"/></h2> </xsl:if> <xsl:apply-templates select="tp:copyright"/> <xsl:apply-templates select="tp:license"/> @@ -838,6 +1171,29 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA </html> </xsl:template> + <xsl:template match="node"> + <xsl:apply-templates /> + </xsl:template> + + <xsl:template match="text()"> + <xsl:if test="normalize-space(.) != ''"> + <xsl:message terminate="yes"> + <xsl:text>Stray text: {{{</xsl:text> + <xsl:value-of select="." /> + <xsl:text>}}} </xsl:text> + </xsl:message> + </xsl:if> + </xsl:template> + + <xsl:template match="*"> + <xsl:message terminate="yes"> + <xsl:text>Unrecognised element: {</xsl:text> + <xsl:value-of select="namespace-uri(.)" /> + <xsl:text>}</xsl:text> + <xsl:value-of select="local-name(.)" /> + <xsl:text> </xsl:text> + </xsl:message> + </xsl:template> </xsl:stylesheet> <!-- vim:set sw=2 sts=2 et: --> diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py index b4e9de32..69885968 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 NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0" @@ -55,8 +55,9 @@ class Generator(object): % opts.get('--subclass', 'TpProxy')) if self.proxy_arg == 'void *': self.proxy_arg = 'gpointer ' - self.generate_reentrant = '--generate-reentrant' in opts - self.generate_blocking = '--generate-blocking' in opts + self.generate_reentrant = ('--generate-reentrant' in opts or + '--deprecate-reentrant' in opts) + self.deprecate_reentrant = opts.get('--deprecate-reentrant', None) def h(self, s): if isinstance(s, unicode): @@ -80,7 +81,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 @@ -356,353 +361,15 @@ class Generator(object): 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 - # (gpointer proxy, - # gint timeout_ms, - # const GArray *in_properties, - # GPtrArray **out0, - # GError **error, - # GMainLoop **loop); - - self.b('typedef struct {') - self.b(' GMainLoop *loop;') - self.b(' GError **error;') - - for arg in out_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - self.b(' %s*%s;' % (ctype, name)) - - self.b(' unsigned success:1;') - self.b(' unsigned completed:1;') - self.b('} _%s_%s_run_state_%s;' - % (self.prefix_lc, iface_lc, member_lc)) - - reentrant_invoke = '_%s_%s_finish_running_%s' % (self.prefix_lc, - iface_lc, - member_lc) - - self.b('static void') - self.b('%s (TpProxy *self G_GNUC_UNUSED,' % reentrant_invoke) - self.b(' GError *error,') - self.b(' GValueArray *args,') - self.b(' GCallback unused G_GNUC_UNUSED,') - self.b(' gpointer user_data G_GNUC_UNUSED,') - self.b(' GObject *unused2 G_GNUC_UNUSED)') - self.b('{') - self.b(' _%s_%s_run_state_%s *state = user_data;' - % (self.prefix_lc, iface_lc, member_lc)) - self.b('') - self.b(' state->success = (error == NULL);') - self.b(' state->completed = TRUE;') - self.b(' g_main_loop_quit (state->loop);') - self.b('') - self.b(' if (error != NULL)') - self.b(' {') - self.b(' if (state->error != NULL)') - self.b(' *state->error = error;') - self.b(' else') - self.b(' g_error_free (error);') - self.b('') - self.b(' return;') - self.b(' }') - self.b('') - - for i, arg in enumerate(out_args): - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - self.b(' if (state->%s != NULL)' % name) - if marshaller == 'BOXED': - self.b(' *state->%s = g_value_dup_boxed (' - 'args->values + %d);' % (name, i)) - elif marshaller == 'STRING': - self.b(' *state->%s = g_value_dup_string ' - '(args->values + %d);' % (name, i)) - elif marshaller in ('UCHAR', 'BOOLEAN', 'INT', 'UINT', - 'INT64', 'UINT64', 'DOUBLE'): - self.b(' *state->%s = g_value_get_%s (args->values + %d);' - % (name, marshaller.lower(), i)) - else: - assert False, "Don't know how to copy %s" % gtype - - self.b('') - - if len(out_args) > 0: - self.b(' g_value_array_free (args);') - else: - self.b(' if (args != NULL)') - self.b(' g_value_array_free (args);') - - self.b('}') - self.b('') - - 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') - - 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' - % (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 ' - '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.b('gboolean\n%s_%s_run_%s (%sproxy,' - % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) - self.b(' gint timeout_ms,') - - for arg in in_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - const = pointer and 'const ' or '' - - self.h(' %s%s%s,' % (const, ctype, name)) - self.b(' %s%s%s,' % (const, ctype, name)) - - for arg in out_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - self.h(' %s*%s,' % (ctype, name)) - self.b(' %s*%s,' % (ctype, name)) - - self.h(' GError **error,') - self.h(' GMainLoop **loop);') - self.h('') - - self.b(' GError **error,') - self.b(' GMainLoop **loop)') - self.b('{') - self.b(' DBusGProxy *iface;') - self.b(' GQuark interface = %s;' % self.get_iface_quark()) - self.b(' TpProxyPendingCall *pc;') - self.b(' _%s_%s_run_state_%s state = {' - % (self.prefix_lc, iface_lc, member_lc)) - self.b(' NULL /* loop */, error,') - - for arg in out_args: - name, info, tp_type, elt = arg - - self.b(' %s,' % name) - - self.b(' FALSE /* completed */, FALSE /* success */ };') - self.b('') - self.b(' g_return_val_if_fail (%s (proxy), FALSE);' - % self.proxy_assert) - self.b('') - self.b(' iface = tp_proxy_borrow_interface_by_id') - self.b(' ((TpProxy *) proxy, interface, error);') - self.b('') - self.b(' if (iface == NULL)') - self.b(' return FALSE;') - self.b('') - self.b(' state.loop = g_main_loop_new (NULL, FALSE);') - self.b('') - self.b(' pc = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,') - self.b(' interface, "%s", iface,' % member) - self.b(' %s,' % reentrant_invoke) - self.b(' NULL, &state, NULL, NULL, TRUE);') - self.b('') - self.b(' if (loop != NULL)') - self.b(' *loop = state.loop;') - self.b('') - self.b(' tp_proxy_pending_call_v0_take_pending_call (pc,') - self.b(' dbus_g_proxy_begin_call_with_timeout (iface,') - self.b(' "%s",' % member) - self.b(' %s,' % collect_callback) - self.b(' pc,') - self.b(' tp_proxy_pending_call_v0_completed,') - self.b(' timeout_ms,') - - for arg in in_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - const = pointer and 'const ' or '' - - self.b(' %s, %s,' % (gtype, name)) - - self.b(' G_TYPE_INVALID));') - self.b('') - self.b(' if (!state.completed)') - self.b(' g_main_loop_run (state.loop);') - self.b('') - self.b(' if (!state.completed)') - self.b(' tp_proxy_pending_call_cancel (pc);') - self.b('') - self.b(' if (loop != NULL)') - self.b(' *loop = NULL;') - self.b('') - self.b(' g_main_loop_unref (state.loop);') - self.b('') - self.b(' return state.success;') - self.b('}') - self.b('') - - def do_method_blocking(self, method, iface_lc, member, member_lc, - in_args, out_args): - # Non reentrant blocking calls - # Example: - # gboolean tp_cli_properties_interface_do_get_properties - # (gpointer proxy, - # gint timeout_ms, - # const GArray *in_properties, - # GPtrArray **out0, - # GError **error); - - self.h('gboolean %s_%s_do_%s (%sproxy,' - % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) - self.h(' gint timeout_ms,') - - self.b('/**') - self.b(' * %s_%s_do_%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') - - 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' - % (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 ' - '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(' *') - self.b(' * Call the method %s and block' % member) - self.b(' * until it returns.') - 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.b('gboolean\n%s_%s_do_%s (%sproxy,' - % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) - self.b(' gint timeout_ms,') - - for arg in in_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - const = pointer and 'const ' or '' - - self.h(' %s%s%s,' % (const, ctype, name)) - self.b(' %s%s%s,' % (const, ctype, name)) - - for arg in out_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - self.h(' %s*%s,' % (ctype, name)) - self.b(' %s*%s,' % (ctype, name)) - - self.h(' GError **error);') - self.h('') - - self.b(' GError **error)') - self.b('{') - self.b(' DBusGProxy *iface;') - self.b(' GQuark interface = %s;' % self.get_iface_quark()) - for arg in out_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - self.b(' %si_%s;' % (ctype, name)) - self.b('') - self.b(' g_return_val_if_fail (%s (proxy), FALSE);' - % self.proxy_assert) - self.b('') - self.b(' iface = tp_proxy_borrow_interface_by_id') - self.b(' ((TpProxy *) proxy, interface, error);') - self.b('') - self.b(' if (iface == NULL)') - self.b(' return FALSE;') - self.b('') - self.b(' if (dbus_g_proxy_call_with_timeout (iface,') - self.b(' "%s",' % member) - self.b(' timeout_ms,') - self.b(' error,') - - for arg in in_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - const = pointer and 'const ' or '' - - self.b(' %s, %s,' % (gtype, name)) - - self.b(' G_TYPE_INVALID,') - - for arg in out_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - self.b(' %s, &i_%s,' % (gtype, name)) - self.b(' G_TYPE_INVALID))') - self.b(' {') - for arg in out_args: - name, info, tp_type, elt = arg - ctype, gtype, marshaller, pointer = info - - self.b(' *%s = i_%s;' % (name, name)) - self.b(' return TRUE;') - self.b(' }') - self.b(' else') - self.b(' return FALSE;') - self.b('}') - self.b('') - 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 @@ -1141,14 +808,240 @@ class Generator(object): self.do_method_reentrant(method, iface_lc, member, member_lc, in_args, out_args, collect_callback) - if self.generate_blocking: - self.do_method_blocking(method, iface_lc, member, member_lc, - in_args, out_args) - # leave a gap for the end of the method 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 + # (gpointer proxy, + # gint timeout_ms, + # const GArray *in_properties, + # GPtrArray **out0, + # GError **error, + # GMainLoop **loop); + + self.b('typedef struct {') + self.b(' GMainLoop *loop;') + self.b(' GError **error;') + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' %s*%s;' % (ctype, name)) + + self.b(' unsigned success:1;') + self.b(' unsigned completed:1;') + self.b('} _%s_%s_run_state_%s;' + % (self.prefix_lc, iface_lc, member_lc)) + + reentrant_invoke = '_%s_%s_finish_running_%s' % (self.prefix_lc, + iface_lc, + member_lc) + + self.b('static void') + self.b('%s (TpProxy *self G_GNUC_UNUSED,' % reentrant_invoke) + self.b(' GError *error,') + self.b(' GValueArray *args,') + self.b(' GCallback unused G_GNUC_UNUSED,') + self.b(' gpointer user_data G_GNUC_UNUSED,') + self.b(' GObject *unused2 G_GNUC_UNUSED)') + self.b('{') + self.b(' _%s_%s_run_state_%s *state = user_data;' + % (self.prefix_lc, iface_lc, member_lc)) + self.b('') + self.b(' state->success = (error == NULL);') + self.b(' state->completed = TRUE;') + self.b(' g_main_loop_quit (state->loop);') + self.b('') + self.b(' if (error != NULL)') + self.b(' {') + self.b(' if (state->error != NULL)') + self.b(' *state->error = error;') + self.b(' else') + self.b(' g_error_free (error);') + self.b('') + self.b(' return;') + self.b(' }') + self.b('') + + for i, arg in enumerate(out_args): + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.b(' if (state->%s != NULL)' % name) + if marshaller == 'BOXED': + self.b(' *state->%s = g_value_dup_boxed (' + 'args->values + %d);' % (name, i)) + elif marshaller == 'STRING': + self.b(' *state->%s = g_value_dup_string ' + '(args->values + %d);' % (name, i)) + elif marshaller in ('UCHAR', 'BOOLEAN', 'INT', 'UINT', + 'INT64', 'UINT64', 'DOUBLE'): + self.b(' *state->%s = g_value_get_%s (args->values + %d);' + % (name, marshaller.lower(), i)) + else: + assert False, "Don't know how to copy %s" % gtype + + self.b('') + + if len(out_args) > 0: + self.b(' g_value_array_free (args);') + else: + self.b(' if (args != NULL)') + self.b(' g_value_array_free (args);') + + self.b('}') + 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') + + 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' + % (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 ' + '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.b('gboolean\n%s_%s_run_%s (%sproxy,' + % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg)) + self.b(' gint timeout_ms,') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.h(' %s%s%s,' % (const, ctype, name)) + self.b(' %s%s%s,' % (const, ctype, name)) + + for arg in out_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + self.h(' %s*%s,' % (ctype, name)) + self.b(' %s*%s,' % (ctype, name)) + + self.h(' GError **error,') + + if self.deprecate_reentrant: + self.h(' GMainLoop **loop) G_GNUC_DEPRECATED;') + self.h('#endif /* not %s */' % self.deprecate_reentrant) + else: + self.h(' GMainLoop **loop);') + + self.h('') + + self.b(' GError **error,') + self.b(' GMainLoop **loop)') + self.b('{') + self.b(' DBusGProxy *iface;') + self.b(' GQuark interface = %s;' % self.get_iface_quark()) + self.b(' TpProxyPendingCall *pc;') + self.b(' _%s_%s_run_state_%s state = {' + % (self.prefix_lc, iface_lc, member_lc)) + self.b(' NULL /* loop */, error,') + + for arg in out_args: + name, info, tp_type, elt = arg + + self.b(' %s,' % name) + + self.b(' FALSE /* completed */, FALSE /* success */ };') + self.b('') + self.b(' g_return_val_if_fail (%s (proxy), FALSE);' + % self.proxy_assert) + self.b('') + self.b(' iface = tp_proxy_borrow_interface_by_id') + self.b(' ((TpProxy *) proxy, interface, error);') + self.b('') + self.b(' if (iface == NULL)') + self.b(' return FALSE;') + self.b('') + self.b(' state.loop = g_main_loop_new (NULL, FALSE);') + self.b('') + self.b(' pc = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,') + self.b(' interface, "%s", iface,' % member) + self.b(' %s,' % reentrant_invoke) + self.b(' NULL, &state, NULL, NULL, TRUE);') + self.b('') + self.b(' if (loop != NULL)') + self.b(' *loop = state.loop;') + self.b('') + self.b(' tp_proxy_pending_call_v0_take_pending_call (pc,') + self.b(' dbus_g_proxy_begin_call_with_timeout (iface,') + self.b(' "%s",' % member) + self.b(' %s,' % collect_callback) + self.b(' pc,') + self.b(' tp_proxy_pending_call_v0_completed,') + self.b(' timeout_ms,') + + for arg in in_args: + name, info, tp_type, elt = arg + ctype, gtype, marshaller, pointer = info + + const = pointer and 'const ' or '' + + self.b(' %s, %s,' % (gtype, name)) + + self.b(' G_TYPE_INVALID));') + self.b('') + self.b(' if (!state.completed)') + self.b(' g_main_loop_run (state.loop);') + self.b('') + self.b(' if (!state.completed)') + self.b(' tp_proxy_pending_call_cancel (pc);') + self.b('') + self.b(' if (loop != NULL)') + self.b(' *loop = NULL;') + self.b('') + self.b(' g_main_loop_unref (state.loop);') + self.b('') + self.b(' return state.success;') + self.b('}') + self.b('') + def do_signal_add(self, signal): marshaller_items = [] gtypes = [] @@ -1279,7 +1172,7 @@ if __name__ == '__main__': options, argv = gnu_getopt(sys.argv[1:], '', ['group=', 'subclass=', 'subclass-assert=', 'iface-quark-prefix=', 'tp-proxy-api=', - 'generate-reentrant', 'generate-blocking']) + 'generate-reentrant', 'deprecate-reentrant=']) opts = {} diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py index 7e288c3c..b361c7f4 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 @@ -37,7 +37,7 @@ class Generator(object): def __init__(self, dom, prefix, basename, signal_marshal_prefix, headers, end_headers, not_implemented_func, - allow_havoc, write_properties): + allow_havoc): self.dom = dom self.__header = [] self.__body = [] @@ -66,12 +66,12 @@ 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 self.not_implemented_func = not_implemented_func self.allow_havoc = allow_havoc - self.write_properties = write_properties def h(self, s): self.__header.append(s) @@ -208,7 +208,8 @@ class Generator(object): self.b('%s%s_base_init_once (gpointer klass G_GNUC_UNUSED)' % (self.prefix_, node_name_lc)) self.b('{') - if self.write_properties: + + if properties: self.b(' static TpDBusPropertiesMixinPropInfo properties[%d] = {' % (len(properties) + 1)) @@ -225,34 +226,38 @@ class Generator(object): 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE') self.b(' { 0, %s, "%s", 0, NULL, NULL }, /* %s */' - % (flags, m.getAttribute('type'), - m.getAttribute('name'))) + % (flags, m.getAttribute('type'), m.getAttribute('name'))) 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(' 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].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])) + % (i, type_to_gtype(m.getAttribute('type'))[1])) - self.b(' tp_svc_interface_set_dbus_properties_info (%s, ' - '&interface);' % self.current_gtype) + 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('}') self.b('static void') @@ -280,6 +285,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('') @@ -339,7 +348,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) @@ -361,7 +374,13 @@ 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) @@ -376,7 +395,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 + '_' + @@ -537,8 +561,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 @@ -620,24 +651,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>') - if self.write_properties: + + 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) @@ -650,8 +690,8 @@ 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)) def cmdline_error(): @@ -686,8 +726,7 @@ if __name__ == '__main__': ['filename=', 'signal-marshal-prefix=', 'include=', 'include-end=', 'allow-unstable', - 'not-implemented-func=', - 'no-properties']) + 'not-implemented-func=']) try: prefix = argv[1] @@ -700,7 +739,6 @@ if __name__ == '__main__': end_headers = [] not_implemented_func = '' allow_havoc = False - write_properties = True for option, value in options: if option == '--filename': @@ -719,8 +757,6 @@ if __name__ == '__main__': not_implemented_func = value elif option == '--allow-unstable': allow_havoc = True - elif option == '--no-properties': - write_properties = False try: dom = xml.dom.minidom.parse(argv[0]) @@ -728,5 +764,4 @@ if __name__ == '__main__': cmdline_error() Generator(dom, prefix, basename, signal_marshal_prefix, headers, - end_headers, not_implemented_func, allow_havoc, - write_properties)() + end_headers, not_implemented_func, allow_havoc)() diff --git a/tools/glib-gtypes-generator.py b/tools/glib-gtypes-generator.py index a73ec8fc..29debf17 100644 --- a/tools/glib-gtypes-generator.py +++ b/tools/glib-gtypes-generator.py @@ -27,7 +27,8 @@ from libglibcodegen import escape_as_identifier, \ get_docstring, \ NS_TP, \ Signature, \ - type_to_gtype + type_to_gtype, \ + xml_escape def types_to_gtypes(types): @@ -50,9 +51,18 @@ class GTypesGenerator(object): ' * 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 do_mapping_header(self, mapping): members = mapping.getElementsByTagNameNS(NS_TP, 'member') @@ -70,7 +80,7 @@ class GTypesGenerator(object): docstring = get_docstring(mapping) or '(Undocumented)' self.header.write('/**\n * %s:\n *\n' % name) - self.header.write(' * <![CDATA[%s]]>\n' % docstring) + 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') @@ -89,7 +99,7 @@ class GTypesGenerator(object): self.header.write(' * named <literal>%s</literal>):\n' % key.getAttribute('name')) docstring = get_docstring(key) or '(Undocumented)' - self.header.write(' * <![CDATA[%s]]>\n' % docstring) + self.header.write(' * %s\n' % xml_escape(docstring)) self.header.write(' *\n') self.header.write(' * Values (D-Bus type <literal>%s</literal>,\n' @@ -100,7 +110,7 @@ class GTypesGenerator(object): self.header.write(' * named <literal>%s</literal>):\n' % value.getAttribute('name')) docstring = get_docstring(value) or '(Undocumented)' - self.header.write(' * <![CDATA[%s]]>\n' % docstring) + self.header.write(' * %s\n' % xml_escape(docstring)) self.header.write(' *\n') self.header.write(' */\n') @@ -108,6 +118,20 @@ class GTypesGenerator(object): self.header.write('#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.header.write('/**\n * %s:\n\n' % gtype_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' % (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]) @@ -125,8 +149,10 @@ class GTypesGenerator(object): docstring = docstring[:-16] if docstring.strip() in ('<tp:docstring/>', ''): docstring = '(Undocumented)' + else: + docstring = '(Undocumented)' self.header.write('/**\n * %s:\n\n' % name) - self.header.write(' * <![CDATA[%s]]>\n' % docstring) + 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') @@ -145,7 +171,7 @@ class GTypesGenerator(object): self.header.write(' * named <literal>%s</literal>):\n' % member.getAttribute('name')) docstring = get_docstring(member) or '(Undocumented)' - self.header.write(' * <![CDATA[%s]]>\n' % docstring) + self.header.write(' * %s\n' % xml_escape(docstring)) self.header.write(' *\n') self.header.write(' */\n') @@ -161,7 +187,7 @@ class GTypesGenerator(object): 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.need_struct_arrays[impl_sig] = esc_impl_sig self.need_structs[impl_sig] = esc_impl_sig @@ -206,16 +232,48 @@ class GTypesGenerator(object): self.body.write(' return t;\n') self.body.write('}\n\n') - for sig in self.need_arrays: + for sig in self.need_struct_arrays: self.header.write('GType %stype_dbus_array_%s (void);\n\n' % - (self.prefix_, self.need_structs[sig])) + (self.prefix_, self.need_struct_arrays[sig])) self.body.write('GType\n%stype_dbus_array_%s (void)\n{\n' % - (self.prefix_, self.need_structs[sig])) + (self.prefix_, self.need_struct_arrays[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", ' '%stype_dbus_struct_%s ());\n' % - (self.prefix_, self.need_structs[sig])) + (self.prefix_, self.need_struct_arrays[sig])) + self.body.write(' return t;\n') + self.body.write('}\n\n') + + for sig in self.need_other_arrays: + self.header.write('GType %stype_dbus_array_of_%s (void);\n\n' % + (self.prefix_, self.need_other_arrays[sig])) + self.body.write('GType\n%stype_dbus_array_of_%s (void)\n{\n' % + (self.prefix_, self.need_other_arrays[sig])) + self.body.write(' static GType t = 0;\n\n') + self.body.write(' if (G_UNLIKELY (t == 0))\n') + + if sig[:2] == 'a{' and sig[-1:] == '}': + # array of mappings + self.body.write(' 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.body.write(' 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.body.write(' 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.body.write(' return t;\n') self.body.write('}\n\n') diff --git a/tools/libglibcodegen.py b/tools/libglibcodegen.py index 0703d92d..0cf52a82 100644 --- a/tools/libglibcodegen.py +++ b/tools/libglibcodegen.py @@ -23,10 +23,9 @@ 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 @@ -146,8 +145,10 @@ def type_to_gtype(s): elif s == 'ab': #boolean array return ("GArray *", "DBUS_TYPE_G_BOOLEAN_ARRAY", "BOXED", True) elif s == 'ao': #object path array - return ("GPtrArray *", "dbus_g_type_get_collection (\"GPtrArray\", " - "DBUS_TYPE_G_OBJECT_PATH)", "BOXED", True) + return ("GPtrArray *", + 'dbus_g_type_get_collection ("GPtrArray",' + ' DBUS_TYPE_G_OBJECT_PATH)', + "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 diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py index e7527c8a..e5114b7a 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) @@ -98,6 +72,39 @@ def escape_as_identifier(identifier): return ''.join(ret) +def get_by_path(element, path): + branches = path.split('/') + branch = branches[0] + + # Is the current branch an attribute, if so, return the attribute value + if branch[0] == '@': + return element.getAttribute(branch[1:]) + + # Find matching children for the branch + children = [] + if branch == '..': + children.append(element.parentNode) + else: + for x in element.childNodes: + if x.localName == branch: + children.append(x) + + ret = [] + # If this is not the last path element, recursively gather results from + # children + if len(branches) > 1: + for x in children: + add = get_by_path(x, '/'.join(branches[1:])) + if isinstance(add, list): + ret += add + else: + return add + else: + ret = children + + return ret + + def get_docstring(element): docstring = None for x in element.childNodes: @@ -114,9 +121,13 @@ def get_docstring(element): return docstring -def get_descendant_text(element): +def get_descendant_text(element_or_elements): + if not element_or_elements: + return '' + if isinstance(element_or_elements, list): + return ''.join(map(get_descendant_text, element_or_elements)) parts = [] - for x in element.childNodes: + for x in element_or_elements.childNodes: if x.nodeType == x.TEXT_NODE: parts.append(x.nodeValue) elif x.nodeType == x.ELEMENT_NODE: |