empathy r1883 - in trunk: extensions tools



Author: xclaesse
Date: Fri Nov 21 16:23:11 2008
New Revision: 1883
URL: http://svn.gnome.org/viewvc/empathy?rev=1883&view=rev

Log:
Update tools to latest version of tp-glib and include a gitignore

Added:
   trunk/tools/c-constants-gen.py
   trunk/tools/glib-errors-enum-body-gen.py
   trunk/tools/glib-errors-enum-header-gen.py
   trunk/tools/glib-interfaces-gen.py
   trunk/tools/lcov.am
   trunk/tools/libtpcodegen.py
   trunk/tools/make-version-script.py
   trunk/tools/telepathy.am
Removed:
   trunk/tools/c-constants-generator.xsl
   trunk/tools/c-interfaces-generator.xsl
   trunk/tools/glib-errors-enum-body.xsl
   trunk/tools/glib-errors-enum-header.xsl
   trunk/tools/glib-interfaces-body-generator.xsl
   trunk/tools/glib-interfaces-generator.xsl
   trunk/tools/ls-interfaces.xsl
   trunk/tools/make-all-async.xsl
   trunk/tools/spec-to-introspect.xsl
Modified:
   trunk/extensions/Makefile.am
   trunk/tools/.gitignore
   trunk/tools/Makefile.am
   trunk/tools/check-c-style.sh
   trunk/tools/check-coding-style.mk
   trunk/tools/doc-generator.xsl
   trunk/tools/glib-client-gen.py
   trunk/tools/glib-ginterface-gen.py
   trunk/tools/libglibcodegen.py
   trunk/tools/with-session-bus.sh

Modified: trunk/extensions/Makefile.am
==============================================================================
--- trunk/extensions/Makefile.am	(original)
+++ trunk/extensions/Makefile.am	Fri Nov 21 16:23:11 2008
@@ -86,27 +86,16 @@
 	$(PYTHON) $(tools_dir)/glib-client-marshaller-gen.py $< \
 		_emp_ext > $@
 
-_gen/enums.h: _gen/all.xml $(tools_dir)/c-constants-generator.xsl
-	$(XSLTPROC) $(XSLTPROCFLAGS) \
-		--stringparam mixed-case-prefix Emp \
-		$(tools_dir)/c-constants-generator.xsl \
+_gen/enums.h: _gen/all.xml \
+	$(tools_dir)/c-constants-gen.py
+	$(PYTHON) $(tools_dir)/c-constants-gen.py \
+		Emp \
 		$< > $@
 
-_gen/interfaces.h: _gen/all.xml \
-	$(tools_dir)/glib-interfaces-generator.xsl \
-	$(tools_dir)/c-interfaces-generator.xsl
-	$(XSLTPROC) $(XSLTPROCFLAGS) \
-		--stringparam mixed-case-prefix Emp \
-		$(tools_dir)/glib-interfaces-generator.xsl \
-		$< > $@
-
-_gen/interfaces-body.h: _gen/all.xml \
-	$(tools_dir)/glib-interfaces-body-generator.xsl \
-	$(tools_dir)/c-interfaces-generator.xsl
-	$(XSLTPROC) $(XSLTPROCFLAGS) \
-		--stringparam mixed-case-prefix Emp \
-		$(tools_dir)/glib-interfaces-body-generator.xsl \
-		$< > $@
+_gen/interfaces-body.h _gen/interfaces.h: _gen/all.xml \
+	$(tools_dir)/glib-interfaces-gen.py
+	$(PYTHON) $(tools_dir)/glib-interfaces-gen.py \
+		Emp _gen/interfaces-body.h _gen/interfaces.h $<
 
 # Generated files which must be generated per "category". Each TpProxy
 # subclass you want to use with --subclass will need to have its own category,

Modified: trunk/tools/.gitignore
==============================================================================
--- trunk/tools/.gitignore	(original)
+++ trunk/tools/.gitignore	Fri Nov 21 16:23:11 2008
@@ -1,2 +1,3 @@
-.py[co]
+_gen
+extensions.html
 telepathy-glib-env

Modified: trunk/tools/Makefile.am
==============================================================================
--- trunk/tools/Makefile.am	(original)
+++ trunk/tools/Makefile.am	Fri Nov 21 16:23:11 2008
@@ -7,41 +7,50 @@
 	chmod +x $@
 
 EXTRA_DIST = \
-    c-constants-generator.xsl \
+    c-constants-gen.py \
     check-coding-style.mk \
     check-c-style.sh \
     check-misc.sh \
     check-whitespace.sh \
-    c-interfaces-generator.xsl \
     doc-generator.xsl \
     glib-client-gen.py \
     glib-client-marshaller-gen.py \
-    glib-errors-enum-body.xsl \
-    glib-errors-enum-header.xsl \
-    glib-interfaces-generator.xsl \
-    glib-interfaces-body-generator.xsl \
+    glib-errors-enum-body-gen.py \
+    glib-errors-enum-header-gen.py \
     glib-ginterface-gen.py \
     glib-gtypes-generator.py \
+    glib-interfaces-gen.py \
     glib-signals-marshal-gen.py \
     gobject-foo.py \
     identity.xsl \
+    lcov.am \
+    libtpcodegen.py \
     libglibcodegen.py \
-    ls-interfaces.xsl \
-    make-all-async.xsl \
-    spec-to-introspect.xsl \
+    make-version-script.py \
+    telepathy.am \
     telepathy-glib-env.in \
     with-session-bus.sh
 
-CLEANFILES = libglibcodegen.pyc libglibcodegen.pyo $(noinst_SCRIPTS)
+CLEANFILES = libtpcodegen.pyc libtpcodegen.pyo libglibcodegen.pyc libglibcodegen.pyo $(noinst_SCRIPTS)
 
 all: $(EXTRA_DIST)
 
+libglibcodegen.py: libtpcodegen.py
+	touch $@
+c-constants-gen.py: libglibcodegen.py
+	touch $@
 glib-client-marshaller-gen.py: libglibcodegen.py
 	touch $@
+glib-errors-enum-body-gen.py: libglibcodegen.py
+	touch $@
+glib-errors-enum-header-gen.py: libglibcodegen.py
+	touch $@
 glib-ginterface-gen.py: libglibcodegen.py
 	touch $@
 glib-gtypes-generator.py: libglibcodegen.py
 	touch $@
+glib-interfaces-gen.py: libglibcodegen.py
+	touch $@
 glib-signals-marshal-gen.py: libglibcodegen.py
 	touch $@
 

Added: trunk/tools/c-constants-gen.py
==============================================================================
--- (empty file)
+++ trunk/tools/c-constants-gen.py	Fri Nov 21 16:23:11 2008
@@ -0,0 +1,151 @@
+#!/usr/bin/python
+
+from sys import argv, stdout, stderr
+import xml.dom.minidom
+
+from libglibcodegen import NS_TP, camelcase_to_upper, get_docstring, \
+        get_descendant_text, get_by_path
+
+class Generator(object):
+    def __init__(self, prefix, dom):
+        self.prefix = prefix + '_'
+        self.spec = get_by_path(dom, "spec")[0]
+
+    def __call__(self):
+        self.do_header()
+        self.do_body()
+        self.do_footer()
+
+    # Header
+    def do_header(self):
+        stdout.write('/* Generated from ')
+        stdout.write(get_descendant_text(get_by_path(self.spec, 'title')))
+        version = get_by_path(self.spec, "version")
+        if version:
+            stdout.write(', version ' + get_descendant_text(version))
+        stdout.write('\n\n')
+        for copyright in get_by_path(self.spec, 'copyright'):
+            stdout.write(get_descendant_text(copyright))
+            stdout.write('\n')
+        stdout.write(get_descendant_text(get_by_path(self.spec, 'license')))
+        stdout.write('\n')
+        stdout.write(get_descendant_text(get_by_path(self.spec, 'docstring')))
+        stdout.write("""
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+\n""")
+
+    # Body
+    def do_body(self):
+        for elem in self.spec.getElementsByTagNameNS(NS_TP, '*'):
+            if elem.localName == 'flags':
+                self.do_flags(elem)
+            elif elem.localName == 'enum':
+                self.do_enum(elem)
+
+    def do_flags(self, flags):
+        name = flags.getAttribute('plural') or flags.getAttribute('name')
+        value_prefix = flags.getAttribute('singular') or \
+                       flags.getAttribute('value-prefix') or \
+                       flags.getAttribute('name')
+        stdout.write("""\
+/**
+ *
+%s:
+""" % (self.prefix + name).replace('_', ''))
+        for flag in get_by_path(flags, 'flag'):
+            self.do_gtkdoc(flag, value_prefix)
+        stdout.write(' *\n')
+        docstrings = get_by_path(flags, 'docstring')
+        if docstrings:
+            stdout.write("""\
+ * <![CDATA[%s]]>
+ *
+""" % get_descendant_text(docstrings).replace('\n', ' '))
+        stdout.write("""\
+ * Bitfield/set of flags generated from the Telepathy specification.
+ */
+typedef enum {
+""")
+        for flag in get_by_path(flags, 'flag'):
+            self.do_val(flag, value_prefix)
+        stdout.write("""\
+} %s;
+
+""" % (self.prefix + name).replace('_', ''))
+
+    def do_enum(self, enum):
+        name = enum.getAttribute('singular') or enum.getAttribute('name')
+        value_prefix = enum.getAttribute('singular') or \
+                       enum.getAttribute('value-prefix') or \
+                       enum.getAttribute('name')
+        name_plural = enum.getAttribute('plural') or \
+                      enum.getAttribute('name') + 's'
+        stdout.write("""\
+/**
+ *
+%s:
+""" % (self.prefix + name).replace('_', ''))
+        vals = get_by_path(enum, 'enumvalue')
+        for val in vals:
+            self.do_gtkdoc(val, value_prefix)
+        stdout.write(' *\n')
+        docstrings = get_by_path(enum, 'docstring')
+        if docstrings:
+            stdout.write("""\
+ * <![CDATA[%s]]>
+ *
+""" % get_descendant_text(docstrings).replace('\n', ' '))
+        stdout.write("""\
+ * Bitfield/set of flags generated from the Telepathy specification.
+ */
+typedef enum {
+""")
+        for val in vals:
+            self.do_val(val, value_prefix)
+        stdout.write("""\
+} %(mixed-name)s;
+
+/**
+ * NUM_%(upper-plural)s:
+ *
+ * 1 higher than the highest valid value of #%(mixed-name)s.
+ */
+#define NUM_%(upper-plural)s (%(last-val)s+1)
+
+""" % {'mixed-name' : (self.prefix + name).replace('_', ''),
+       'upper-plural' : (self.prefix + name_plural).upper(),
+       'last-val' : vals[-1].getAttribute('value')})
+
+    def do_val(self, val, value_prefix):
+        name = val.getAttribute('name')
+        suffix = val.getAttribute('suffix')
+        use_name = (self.prefix + value_prefix + '_' + \
+                (suffix or name)).upper()
+        assert not (name and suffix) or name == suffix, \
+                'Flag/enumvalue name %s != suffix %s' % (name, suffix)
+        stdout.write('    %s = %s,\n' % (use_name, val.getAttribute('value')))
+
+    def do_gtkdoc(self, node, value_prefix):
+        stdout.write(' * @')
+        stdout.write((self.prefix + value_prefix + '_' +
+            node.getAttribute('suffix')).upper())
+        stdout.write(': <![CDATA[')
+        docstring = get_by_path(node, 'docstring')
+        stdout.write(get_descendant_text(docstring).replace('\n', ' '))
+        stdout.write(']]>\n')
+
+    # Footer
+    def do_footer(self):
+        stdout.write("""
+#ifdef __cplusplus
+}
+#endif
+""")
+
+if __name__ == '__main__':
+    argv = argv[1:]
+    Generator(argv[0], xml.dom.minidom.parse(argv[1]))()

Modified: trunk/tools/check-c-style.sh
==============================================================================
--- trunk/tools/check-c-style.sh	(original)
+++ trunk/tools/check-c-style.sh	Fri Nov 21 16:23:11 2008
@@ -24,6 +24,26 @@
   fail=1
 fi
 
+if grep -En '[(][[:alnum:]_]+ ?\*[)][(]?[[:alpha:]_]' "$@"; then
+  echo "^^^ Our coding style is to have a space between a cast and the "
+  echo "    thing being cast"
+  fail=1
+fi
+
+# this only spots casts
+if grep -En '[(][[:alnum:]_]+\*+[)]' "$@"; then
+  echo "^^^ Our coding style is to have a space before the * of pointer types"
+  echo "    (regex 1)"
+  fail=1
+fi
+# ... and this only spots variable declarations and function return types
+if grep -En '^ *(static |const |)* *[[:alnum:]_]+\*+([[:alnum:]_]|;|$)' \
+    "$@"; then
+  echo "^^^ Our coding style is to have a space before the * of pointer types"
+  echo "    (regex 2)"
+  fail=1
+fi
+
 if test -n "$CHECK_FOR_LONG_LINES"
 then
   if egrep -n '.{80,}' "$@"

Modified: trunk/tools/check-coding-style.mk
==============================================================================
--- trunk/tools/check-coding-style.mk	(original)
+++ trunk/tools/check-coding-style.mk	Fri Nov 21 16:23:11 2008
@@ -1,4 +1,4 @@
-check-local::
+check-coding-style:
 	@fail=0; \
 	if test -n "$(check_misc_sources)"; then \
 		tools_dir=$(top_srcdir)/tools \

Modified: trunk/tools/doc-generator.xsl
==============================================================================
--- trunk/tools/doc-generator.xsl	(original)
+++ trunk/tools/doc-generator.xsl	Fri Nov 21 16:23:11 2008
@@ -23,16 +23,104 @@
   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:template match="html:*" mode="html">
+  <xsl:param name="allow-undefined-interfaces" select="false()"/>
+
+  <xsl:template match="html:* | @*" mode="html">
     <xsl:copy>
       <xsl:apply-templates mode="html"/>
     </xsl:copy>
   </xsl:template>
 
+  <xsl:template match="tp:type" mode="html">
+    <xsl:call-template name="tp-type">
+      <xsl:with-param name="tp-type" select="string(.)"/>
+    </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>'&#10;</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> &lt;interface&gt;&#10;</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>&#10;</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"/>
@@ -40,11 +128,36 @@
   </xsl:template>
 
   <xsl:template match="tp:docstring">
-    <xsl:apply-templates select="text() | html:*" mode="html"/>
-    <xsl:apply-templates select="tp:rationale"/>
+    <xsl:apply-templates mode="html"/>
+  </xsl:template>
+
+  <xsl:template match="tp:added">
+    <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:rationale">
+  <xsl:template match="tp:changed">
+    <xsl:choose>
+      <xsl:when test="node()">
+        <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>
+        <p class="changed">Changed in version
+          <xsl:value-of select="@version"/></p>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="tp:deprecated">
+    <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>
+
+  <xsl:template match="tp:rationale" mode="html">
     <div xmlns="http://www.w3.org/1999/xhtml"; class="rationale">
       <xsl:apply-templates select="node()" mode="html"/>
     </div>
@@ -95,11 +208,14 @@
   <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:apply-templates select="tp:added"/>
+    <xsl:apply-templates select="tp:changed"/>
+    <xsl:apply-templates select="tp:deprecated"/>
   </xsl:template>
 
   <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">
@@ -132,6 +248,9 @@
     </xsl:if>
 
     <xsl:apply-templates select="tp:docstring" />
+    <xsl:apply-templates select="tp:added"/>
+    <xsl:apply-templates select="tp:changed"/>
+    <xsl:apply-templates select="tp:deprecated"/>
 
     <xsl:choose>
       <xsl:when test="method">
@@ -189,12 +308,30 @@
   </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&#10;</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>&#10;</xsl:text>
+      </xsl:message>
+    </xsl:if>
+
     <h3>
       <a name="type-{ name}">
         <xsl:value-of select="@name"/>
       </a>
     </h3>
     <xsl:apply-templates select="tp:docstring" />
+    <xsl:apply-templates select="tp:added"/>
+    <xsl:apply-templates select="tp:changed"/>
+    <xsl:apply-templates select="tp:deprecated"/>
     <dl xmlns="http://www.w3.org/1999/xhtml";>
         <xsl:variable name="value-prefix">
           <xsl:choose>
@@ -210,7 +347,12 @@
         <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>
+            <dd xmlns="http://www.w3.org/1999/xhtml";>
+              <xsl:apply-templates select="tp:docstring" />
+              <xsl:apply-templates select="tp:added"/>
+              <xsl:apply-templates select="tp:changed"/>
+              <xsl:apply-templates select="tp:deprecated"/>
+            </dd>
           </xsl:when>
           <xsl:otherwise>
             <dd xmlns="http://www.w3.org/1999/xhtml";>(Undocumented)</dd>
@@ -221,12 +363,30 @@
   </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&#10;</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>&#10;</xsl:text>
+      </xsl:message>
+    </xsl:if>
+
     <h3 xmlns="http://www.w3.org/1999/xhtml";>
       <a name="type-{ name}">
         <xsl:value-of select="@name"/>
       </a>
     </h3>
     <xsl:apply-templates select="tp:docstring" />
+    <xsl:apply-templates select="tp:added"/>
+    <xsl:apply-templates select="tp:changed"/>
+    <xsl:apply-templates select="tp:deprecated"/>
     <dl xmlns="http://www.w3.org/1999/xhtml";>
         <xsl:variable name="value-prefix">
           <xsl:choose>
@@ -242,7 +402,12 @@
         <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>
+            <dd xmlns="http://www.w3.org/1999/xhtml";>
+              <xsl:apply-templates select="tp:docstring" />
+              <xsl:apply-templates select="tp:added"/>
+              <xsl:apply-templates select="tp:changed"/>
+              <xsl:apply-templates select="tp:deprecated"/>
+            </dd>
           </xsl:when>
           <xsl:otherwise>
             <dd xmlns="http://www.w3.org/1999/xhtml";>(Undocumented)</dd>
@@ -253,11 +418,38 @@
   </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&#10;</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>&#10;</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>'&#10;</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>
@@ -272,25 +464,37 @@
           <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>'&#10;</xsl:text>
+          </xsl:message>
         </xsl:otherwise>
       </xsl:choose>
     </dt>
     <dd xmlns="http://www.w3.org/1999/xhtml";>
       <xsl:apply-templates select="tp:docstring"/>
+      <xsl:apply-templates select="tp:added"/>
+      <xsl:apply-templates select="tp:changed"/>
+      <xsl:apply-templates select="tp:deprecated"/>
     </dd>
   </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> -
+        <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"/>
+      <xsl:apply-templates select="tp:added"/>
+      <xsl:apply-templates select="tp:changed"/>
+      <xsl:apply-templates select="tp:deprecated"/>
     </dd>
   </xsl:template>
 
@@ -299,7 +503,7 @@
       <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>
@@ -310,6 +514,11 @@
       </h3>
       <div class="docstring">
         <xsl:apply-templates select="tp:docstring"/>
+        <xsl:if test="string(@array-name) != ''">
+          <p>In bindings that need a separate name, arrays of
+            <xsl:value-of select="@name"/> should be called
+            <xsl:value-of select="@array-name"/>.</p>
+        </xsl:if>
       </div>
       <div>
         <h4>Members</h4>
@@ -324,42 +533,75 @@
 
   <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&#10;</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>&#10;</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"/>
+        <xsl:apply-templates select="tp:added"/>
+        <xsl:apply-templates select="tp:changed"/>
+        <xsl:apply-templates select="tp:deprecated"/>
       </div>
     </div>
   </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&#10;</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>&#10;</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()"> &#x2192; </xsl:if>
         </xsl:for-each> }
@@ -370,7 +612,7 @@
       <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>
@@ -381,6 +623,9 @@
       </h3>
       <div class="docstring">
         <xsl:apply-templates select="tp:docstring"/>
+        <xsl:apply-templates select="tp:added"/>
+        <xsl:apply-templates select="tp:changed"/>
+        <xsl:apply-templates select="tp:deprecated"/>
       </div>
       <xsl:choose>
         <xsl:when test="string(@array-name) != ''">
@@ -403,6 +648,64 @@
   </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&#10;</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>&#10;</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))}">
@@ -425,6 +728,9 @@
       </h3>
       <div xmlns="http://www.w3.org/1999/xhtml"; class="docstring">
         <xsl:apply-templates select="tp:docstring" />
+        <xsl:apply-templates select="tp:added"/>
+        <xsl:apply-templates select="tp:changed"/>
+        <xsl:apply-templates select="tp:deprecated"/>
       </div>
 
       <xsl:if test="arg[ direction='in']">
@@ -459,31 +765,55 @@
     </div>
   </xsl:template>
 
-  <xsl:template name="parenthesized-tp-type">
-    <xsl:if test="@tp:type">
-      <xsl:variable name="tp-type" select="@tp:type"/>
-      <xsl:variable name="single-type">
-        <xsl:choose>
-          <xsl:when test="contains($tp-type, '[]')">
-            <xsl:value-of select="substring-before($tp-type, '[]')"/>
-          </xsl:when>
-          <xsl:otherwise>
-            <xsl:value-of select="$tp-type"/>
-          </xsl:otherwise>
-        </xsl:choose>
-      </xsl:variable>
+  <xsl:template name="tp-type">
+    <xsl:param name="tp-type"/>
+    <xsl:param name="type"/>
+
+    <xsl:variable name="single-type">
       <xsl:choose>
-        <xsl:when test="//tp:simple-type[ name=$tp-type]" />
-        <xsl:when test="//tp:simple-type[concat(@name, '[]')=$tp-type]" />
-        <xsl:when test="//tp:struct[concat(@name, '[]')=$tp-type][string(@array-name) != '']" />
-        <xsl:when test="//tp:struct[ name=$tp-type]" />
-        <xsl:when test="//tp:enum[ name=$tp-type]" />
-        <xsl:when test="//tp:enum[concat(@name, '[]')=$tp-type]" />
-        <xsl:when test="//tp:flags[ name=$tp-type]" />
-        <xsl:when test="//tp:flags[concat(@name, '[]')=$tp-type]" />
-        <xsl:when test="//tp:mapping[ name=$tp-type]" />
-        <xsl:when test="//tp:external-type[concat(@name, '[]')=$tp-type]" />
-        <xsl:when test="//tp:external-type[ name=$tp-type]" />
+        <xsl:when test="contains($tp-type, '[]')">
+          <xsl:value-of select="substring-before($tp-type, '[]')"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="$tp-type"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+
+    <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>
@@ -492,13 +822,39 @@
           </xsl:message>
         </xsl:otherwise>
       </xsl:choose>
-      (<a href="#type-{$single-type}"><xsl:value-of select="$tp-type"/></a>)
+    </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>'&#10;</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: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>
   </xsl:template>
 
   <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>
@@ -516,7 +872,7 @@
 
   <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>
@@ -528,7 +884,7 @@
   <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"/>
@@ -559,6 +915,57 @@
   </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&#10;</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>&#10;</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))}">
@@ -569,8 +976,12 @@
           <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"/>
+        <xsl:apply-templates select="tp:added"/>
+        <xsl:apply-templates select="tp:changed"/>
+        <xsl:apply-templates select="tp:deprecated"/>
       </div>
 
       <xsl:if test="arg">
@@ -699,6 +1110,18 @@
             padding-left: 0.5em;
           }
 
+          .added {
+            color: #006600;
+            background: #ffffff;
+          }
+          .deprecated {
+            color: #ff0000;
+            background: #ffffff;
+          }
+          table, tr, td, th {
+            border: 1px solid #666;
+          }
+
         </style>
       </head>
       <body>
@@ -706,7 +1129,7 @@
           <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"/>
@@ -748,6 +1171,29 @@
     </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>}}}&#10;</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>&#10;</xsl:text>
+      </xsl:message>
+  </xsl:template>
 </xsl:stylesheet>
 
 <!-- vim:set sw=2 sts=2 et: -->

Modified: trunk/tools/glib-client-gen.py
==============================================================================
--- trunk/tools/glib-client-gen.py	(original)
+++ trunk/tools/glib-client-gen.py	Fri Nov 21 16:23:11 2008
@@ -57,9 +57,13 @@
             self.proxy_arg = 'gpointer '
 
     def h(self, s):
+        if isinstance(s, unicode):
+            s = s.encode('utf-8')
         self.__header.append(s)
 
     def b(self, s):
+        if isinstance(s, unicode):
+            s = s.encode('utf-8')
         self.__body.append(s)
 
     def get_iface_quark(self):
@@ -656,13 +660,18 @@
             self.b(' * @%s: Used to pass an \'in\' argument: %s'
                    % (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
 
-        self.b(' * @callback: called when the method call succeeds or fails')
-        self.b(' * @user_data: user-supplied data passed to the callback')
+        self.b(' * @callback: called when the method call succeeds or fails;')
+        self.b(' *   may be %NULL to make a "fire and forget" call with no ')
+        self.b(' *   reply tracking')
+        self.b(' * @user_data: user-supplied data passed to the callback;')
+        self.b(' *   must be %NULL if @callback is %NULL')
         self.b(' * @destroy: called with the user_data as argument, after the')
-        self.b(' *   call has succeeded, failed or been cancelled')
-        self.b(' * @weak_object: A #GObject which will be weakly referenced; ')
-        self.b(' *   if it is destroyed, this callback will automatically be')
-        self.b(' *   disconnected')
+        self.b(' *   call has succeeded, failed or been cancelled;')
+        self.b(' *   must be %NULL if @callback is %NULL')
+        self.b(' * @weak_object: If not %NULL, a #GObject which will be ')
+        self.b(' *   weakly referenced; if it is destroyed, this call ')
+        self.b(' *   will automatically be cancelled. Must be %NULL if ')
+        self.b(' *   @callback is %NULL')
         self.b(' *')
         self.b(' * Start a %s method call.' % member)
         self.b(' *')
@@ -703,6 +712,12 @@
         self.b('')
         self.b('  g_return_val_if_fail (%s (proxy), NULL);'
                % self.proxy_assert)
+        self.b('  g_return_val_if_fail (callback != NULL || '
+               'user_data == NULL, NULL);')
+        self.b('  g_return_val_if_fail (callback != NULL || '
+               'destroy == NULL, NULL);')
+        self.b('  g_return_val_if_fail (callback != NULL || '
+               'weak_object == NULL, NULL);')
         self.b('')
         self.b('  iface = tp_proxy_borrow_interface_by_id (')
         self.b('      (TpProxy *) proxy,')
@@ -723,6 +738,10 @@
                 self.b('            0,')
 
         self.b('            error, user_data, weak_object);')
+        self.b('')
+        self.b('      if (destroy != NULL)')
+        self.b('        destroy (user_data);')
+        self.b('')
         self.b('      g_error_free (error);')
         self.b('      return NULL;')
         self.b('    }')
@@ -794,8 +813,8 @@
 
             self.b('    %s*%s;' % (ctype, name))
 
-        self.b('    gboolean success:1;')
-        self.b('    gboolean completed:1;')
+        self.b('    unsigned success:1;')
+        self.b('    unsigned completed:1;')
         self.b('} _%s_%s_run_state_%s;'
                % (self.prefix_lc, iface_lc, member_lc))
 

Added: trunk/tools/glib-errors-enum-body-gen.py
==============================================================================
--- (empty file)
+++ trunk/tools/glib-errors-enum-body-gen.py	Fri Nov 21 16:23:11 2008
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+
+import sys
+import xml.dom.minidom
+
+from libglibcodegen import NS_TP, camelcase_to_upper, get_docstring, \
+        get_descendant_text
+
+class Generator(object):
+    def __init__(self, dom):
+        self.dom = dom
+        self.errors = self.dom.getElementsByTagNameNS(NS_TP, 'errors')[0]
+
+    def do_header(self):
+        print '/* Generated from the Telepathy spec\n'
+        copyrights = self.errors.getElementsByTagNameNS(NS_TP, 'copyright')
+        for copyright in copyrights:
+            print get_descendant_text(copyright)
+        license = self.errors.getElementsByTagNameNS(NS_TP, 'license')[0]
+        print '\n' + get_descendant_text(license) + '\n*/'
+
+    def do_enum_values(self):
+        for error in self.errors.getElementsByTagNameNS(NS_TP, 'error'):
+            print ''
+            nick = error.getAttribute('name').replace(' ', '')
+            name = camelcase_to_upper(nick.replace('.', ''))
+            ns = error.parentNode.getAttribute('namespace')
+            enum = 'TP_ERROR_' + name
+            print '        /* ' + ns + '.' + name
+            print '    ' + get_docstring(error)
+            print '     */'
+            print '        { %s, "%s", "%s" },' % (enum, enum, nick)
+
+
+    def do_get_type(self):
+        print """
+#include <_gen/telepathy-errors.h>
+
+GType
+tp_error_get_type (void)
+{
+  static GType etype = 0;
+  if (G_UNLIKELY (etype == 0))
+    {
+      static const GEnumValue values[] = {"""
+        self.do_enum_values()
+        print """\
+      };
+
+      etype = g_enum_register_static ("TpError", values);
+    }
+  return etype;
+}
+"""
+
+    def __call__(self):
+        self.do_header()
+        self.do_get_type()
+
+if __name__ == '__main__':
+    argv = sys.argv[1:]
+    Generator(xml.dom.minidom.parse(argv[0]))()

Added: trunk/tools/glib-errors-enum-header-gen.py
==============================================================================
--- (empty file)
+++ trunk/tools/glib-errors-enum-header-gen.py	Fri Nov 21 16:23:11 2008
@@ -0,0 +1,75 @@
+#!/usr/bin/python
+
+import sys
+import xml.dom.minidom
+
+from libglibcodegen import NS_TP, camelcase_to_upper, get_docstring, \
+        get_descendant_text
+
+class Generator(object):
+    def __init__(self, dom):
+        self.dom = dom
+        self.errors = self.dom.getElementsByTagNameNS(NS_TP, 'errors')[0]
+
+    def do_header(self):
+        print '/* Generated from the Telepathy spec\n'
+        copyrights = self.errors.getElementsByTagNameNS(NS_TP, 'copyright')
+        for copyright in copyrights:
+            print get_descendant_text(copyright)
+        license = self.errors.getElementsByTagNameNS(NS_TP, 'license')[0]
+        print '\n' + get_descendant_text(license) + '\n*/'
+
+    def do_gtkdoc(self):
+        for error in self.errors.getElementsByTagNameNS(NS_TP, 'error'):
+            ns = error.parentNode.getAttribute('namespace')
+            nick = error.getAttribute('name').replace(' ', '')
+            enum = 'TP_ERROR_' + camelcase_to_upper(nick.replace('.', ''))
+            print ' * @' + enum + ': ' + ns + '.' + nick + ':'
+            print ' *     ' + get_docstring(error) + '    '
+
+    def do_enumnames(self):
+        for error in self.errors.getElementsByTagNameNS(NS_TP, 'error'):
+            nick = error.getAttribute('name').replace(' ', '')
+            enum = 'TP_ERROR_' + camelcase_to_upper(nick.replace('.', ''))
+            print '    ' + enum + ','
+
+    def do_get_type(self):
+        print """
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+GType tp_error_get_type (void);
+
+/**
+ * TP_TYPE_ERROR:
+ *
+ * The GType of the Telepathy error enumeration.
+ */
+#define TP_TYPE_ERROR (tp_error_get_type())
+"""
+
+    def do_enum(self):
+        print """\
+/**
+ * TpError:"""
+        self.do_gtkdoc()
+        print """\
+ *
+ * Enumerated type representing the Telepathy D-Bus errors.
+ */
+typedef enum {"""
+        self.do_enumnames()
+        print """\
+} TpError;
+
+G_END_DECLS"""
+
+    def __call__(self):
+        self.do_header()
+        self.do_get_type()
+        self.do_enum()
+
+if __name__ == '__main__':
+    argv = sys.argv[1:]
+    Generator(xml.dom.minidom.parse(argv[0]))()

Modified: trunk/tools/glib-ginterface-gen.py
==============================================================================
--- trunk/tools/glib-ginterface-gen.py	(original)
+++ trunk/tools/glib-ginterface-gen.py	Fri Nov 21 16:23:11 2008
@@ -588,10 +588,21 @@
         self.b('}')
         self.b('')
 
+        signal_name = dbus_gutils_wincaps_to_uscore(dbus_name).replace('_',
+                '-')
+        in_base_init.append('  /**')
+        in_base_init.append('   * %s%s::%s:'
+                % (self.Prefix, self.node_name_mixed, signal_name))
+        for (ctype, name, gtype) in args:
+            in_base_init.append('   * @%s: %s (FIXME, generate documentation)'
+                   % (name, ctype))
+        in_base_init.append('   *')
+        in_base_init.append('   * The %s D-Bus signal is emitted whenever '
+                'this GObject signal is.' % dbus_name)
+        in_base_init.append('   */')
         in_base_init.append('  %s_signals[%s] ='
                             % (self.node_name_lc, const_name))
-        in_base_init.append('  g_signal_new ("%s",'
-                % (dbus_gutils_wincaps_to_uscore(dbus_name).replace('_', '-')))
+        in_base_init.append('  g_signal_new ("%s",' % signal_name)
         in_base_init.append('      G_OBJECT_CLASS_TYPE (klass),')
         in_base_init.append('      G_SIGNAL_RUN_LAST|G_SIGNAL_DETAILED,')
         in_base_init.append('      0,')

Added: trunk/tools/glib-interfaces-gen.py
==============================================================================
--- (empty file)
+++ trunk/tools/glib-interfaces-gen.py	Fri Nov 21 16:23:11 2008
@@ -0,0 +1,97 @@
+#!/usr/bin/python
+
+from sys import argv, stdout, stderr
+import xml.dom.minidom
+
+from libglibcodegen import NS_TP, camelcase_to_upper, get_docstring, \
+        get_descendant_text, get_by_path
+
+class Generator(object):
+    def __init__(self, prefix, implfile, declfile, dom):
+        self.prefix = prefix + '_'
+        self.impls = open(implfile, 'w')
+        self.decls = open(declfile, 'w')
+        self.spec = get_by_path(dom, "spec")[0]
+
+    def __call__(self):
+        for file in self.decls, self.impls:
+            self.do_header(file)
+        self.do_body()
+
+    # Header
+    def do_header(self, file):
+        file.write('/* Generated from: ')
+        file.write(get_descendant_text(get_by_path(self.spec, 'title')))
+        version = get_by_path(self.spec, "version")
+        if version:
+            file.write(' version ' + get_descendant_text(version))
+        file.write('\n\n')
+        for copyright in get_by_path(self.spec, 'copyright'):
+            stdout.write(get_descendant_text(copyright))
+            stdout.write('\n')
+        file.write('\n')
+        file.write(get_descendant_text(get_by_path(self.spec, 'license')))
+        file.write(get_descendant_text(get_by_path(self.spec, 'docstring')))
+        file.write("""
+ */
+
+""")
+
+    # Body
+    def do_body(self):
+        for iface in self.spec.getElementsByTagName('interface'):
+            self.do_iface(iface)
+
+    def do_iface(self, iface):
+        parent_name = get_by_path(iface, '../@name')
+        self.decls.write("""\
+/**
+ * %(IFACE_DEFINE)s:
+ * 
+ * The interface name "%(name)s"
+ */
+#define %(IFACE_DEFINE)s \\
+"%(name)s"
+""" % {'IFACE_DEFINE' : (self.prefix + 'IFACE_' + \
+            parent_name).upper().replace('/', ''),
+       'name' : iface.getAttribute('name')})
+
+        self.decls.write("""
+/**
+ * %(IFACE_QUARK_DEFINE)s:
+ * 
+ * Expands to a call to a function that returns a quark for the interface \
+name "%(name)s"
+ */
+#define %(IFACE_QUARK_DEFINE)s \\
+  (%(iface_quark_func)s ())
+
+GQuark %(iface_quark_func)s (void);
+
+""" % {'IFACE_QUARK_DEFINE' : (self.prefix + 'IFACE_QUARK_' + \
+            parent_name).upper().replace('/', ''),
+       'iface_quark_func' : (self.prefix + 'iface_quark_' + \
+            parent_name).lower().replace('/', ''),
+       'name' : iface.getAttribute('name')})
+
+        self.impls.write("""\
+GQuark
+%(iface_quark_func)s (void)
+{
+  static GQuark quark = 0;
+
+  if (G_UNLIKELY (quark == 0))
+    {
+      quark = g_quark_from_static_string ("%(name)s");
+    }
+
+  return quark;
+}
+
+""" % {'iface_quark_func' : (self.prefix + 'iface_quark_' + \
+            parent_name).lower().replace('/', ''),
+       'name' : iface.getAttribute('name')})
+
+if __name__ == '__main__':
+    argv = argv[1:]
+    Generator(argv[0], argv[1], argv[2], xml.dom.minidom.parse(argv[3]))()

Added: trunk/tools/lcov.am
==============================================================================
--- (empty file)
+++ trunk/tools/lcov.am	Fri Nov 21 16:23:11 2008
@@ -0,0 +1,23 @@
+lcov-reset:
+	lcov --directory @top_srcdir@ --zerocounters
+
+lcov-report:
+	lcov --directory @top_srcdir@ --capture \
+		--output-file @top_builddir@/lcov.info.tmp
+	lcov --directory @top_srcdir@ --output-file @top_builddir@/lcov.info \
+		--remove @top_builddir@/lcov.info.tmp telepathy-glib-scan.c
+	rm @top_builddir@/lcov.info.tmp
+	$(mkdir_p) @top_builddir@/lcov.html
+	genhtml --title telepathy-glib \
+		--output-directory @top_builddir@/lcov.html lcov.info
+	@echo
+	@echo 'lcov report can be found in:'
+	@echo 'file://@abs_top_builddir@/lcov.html/index.html'
+	@echo
+
+lcov-check:
+	$(MAKE) lcov-reset
+	$(MAKE) check
+	$(MAKE) lcov-report
+
+## vim:set ft=automake:

Modified: trunk/tools/libglibcodegen.py
==============================================================================
--- trunk/tools/libglibcodegen.py	(original)
+++ trunk/tools/libglibcodegen.py	Fri Nov 21 16:23:11 2008
@@ -4,7 +4,7 @@
 please make any changes there.
 """
 
-# Copyright (C) 2006, 2007 Collabora Limited
+# Copyright (C) 2006-2008 Collabora Limited
 #
 # This library is free software; you can redistribute it and/or
 # modify it under the terms of the GNU Lesser General Public
@@ -21,44 +21,16 @@
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 
-from string import ascii_letters, digits
-
-
-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)
-
+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
 
 def dbus_gutils_wincaps_to_uscore(s):
     """Bug-for-bug compatible Python port of _dbus_gutils_wincaps_to_uscore
@@ -77,60 +49,6 @@
     return ret
 
 
-def escape_as_identifier(identifier):
-    """Escape the given string to be a valid D-Bus object path or service
-    name component, using a reversible encoding to ensure uniqueness.
-
-    The reversible encoding is as follows:
-
-    * The empty string becomes '_'
-    * Otherwise, each non-alphanumeric character is replaced by '_' plus
-      two lower-case hex digits; the same replacement is carried out on
-      the first character, if it's a digit
-    """
-    # '' -> '_'
-    if not identifier:
-        return '_'
-
-    # A bit of a fast path for strings which are already OK.
-    # We deliberately omit '_' because, for reversibility, that must also
-    # be escaped.
-    if (identifier.strip(_ASCII_ALNUM) == '' and
-        identifier[0] in ascii_letters):
-        return identifier
-
-    # The first character may not be a digit
-    if identifier[0] not in ascii_letters:
-        ret = ['_%02x' % ord(identifier[0])]
-    else:
-        ret = [identifier[0]]
-
-    # Subsequent characters may be digits or ASCII letters
-    for c in identifier[1:]:
-        if c in _ASCII_ALNUM:
-            ret.append(c)
-        else:
-            ret.append('_%02x' % ord(c))
-
-    return ''.join(ret)
-
-
-def get_docstring(element):
-    docstring = None
-    for x in element.childNodes:
-        if x.namespaceURI == NS_TP and x.localName == 'docstring':
-            docstring = x
-    if docstring is not None:
-        docstring = docstring.toxml().replace('\n', ' ').strip()
-        if docstring.startswith('<tp:docstring>'):
-            docstring = docstring[14:].lstrip()
-        if docstring.endswith('</tp:docstring>'):
-            docstring = docstring[:-15].rstrip()
-        if docstring in ('<tp:docstring/>', ''):
-            docstring = ''
-    return docstring
-
-
 def signal_to_marshal_type(signal):
     """
     return a list of strings indicating the marshalling type for this signal.
@@ -183,69 +101,6 @@
         return prefix + '_marshal_VOID__' + name
 
 
-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):
-    """A string, iteration over which is by D-Bus single complete types
-    rather than characters.
-    """
-    def __iter__(self):
-        return _SignatureIter(self)
-
-
 def type_to_gtype(s):
     if s == 'y': #byte
         return ("guchar ", "G_TYPE_UCHAR","UCHAR", False)
@@ -292,7 +147,10 @@
     elif s == 'ab': #boolean array
         return ("GArray *", "DBUS_TYPE_G_BOOLEAN_ARRAY", "BOXED", True)
     elif s == 'ao': #object path array
-        return ("GArray *", "DBUS_TYPE_G_OBJECT_ARRAY", "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
@@ -313,8 +171,3 @@
 
     # we just don't know ..
     raise Exception, "don't know the GType for " + s
-
-
-def xml_escape(s):
-    s = s.replace('&', '&amp;').replace("'", '&apos;').replace('"', '&quot;')
-    return s.replace('<', '&lt;').replace('>', '&gt;')

Added: trunk/tools/libtpcodegen.py
==============================================================================
--- (empty file)
+++ trunk/tools/libtpcodegen.py	Fri Nov 21 16:23:11 2008
@@ -0,0 +1,231 @@
+"""Library code for language-independent D-Bus-related code generation.
+
+The master copy of this library is in the telepathy-glib repository -
+please make any changes there.
+"""
+
+# Copyright (C) 2006-2008 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
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+
+from string import ascii_letters, digits
+
+
+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)
+
+
+def escape_as_identifier(identifier):
+    """Escape the given string to be a valid D-Bus object path or service
+    name component, using a reversible encoding to ensure uniqueness.
+
+    The reversible encoding is as follows:
+
+    * The empty string becomes '_'
+    * Otherwise, each non-alphanumeric character is replaced by '_' plus
+      two lower-case hex digits; the same replacement is carried out on
+      the first character, if it's a digit
+    """
+    # '' -> '_'
+    if not identifier:
+        return '_'
+
+    # A bit of a fast path for strings which are already OK.
+    # We deliberately omit '_' because, for reversibility, that must also
+    # be escaped.
+    if (identifier.strip(_ASCII_ALNUM) == '' and
+        identifier[0] in ascii_letters):
+        return identifier
+
+    # The first character may not be a digit
+    if identifier[0] not in ascii_letters:
+        ret = ['_%02x' % ord(identifier[0])]
+    else:
+        ret = [identifier[0]]
+
+    # Subsequent characters may be digits or ASCII letters
+    for c in identifier[1:]:
+        if c in _ASCII_ALNUM:
+            ret.append(c)
+        else:
+            ret.append('_%02x' % ord(c))
+
+    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:
+        if x.namespaceURI == NS_TP and x.localName == 'docstring':
+            docstring = x
+    if docstring is not None:
+        docstring = docstring.toxml().replace('\n', ' ').strip()
+        if docstring.startswith('<tp:docstring>'):
+            docstring = docstring[14:].lstrip()
+        if docstring.endswith('</tp:docstring>'):
+            docstring = docstring[:-15].rstrip()
+        if docstring in ('<tp:docstring/>', ''):
+            docstring = ''
+    return docstring
+
+
+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_or_elements.childNodes:
+        if x.nodeType == x.TEXT_NODE:
+            parts.append(x.nodeValue)
+        elif x.nodeType == x.ELEMENT_NODE:
+            parts.append(get_descendant_text(x))
+        else:
+            pass
+    return ''.join(parts)
+
+
+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):
+    """A string, iteration over which is by D-Bus single complete types
+    rather than characters.
+    """
+    def __iter__(self):
+        return _SignatureIter(self)
+
+
+def xml_escape(s):
+    s = s.replace('&', '&amp;').replace("'", '&apos;').replace('"', '&quot;')
+    return s.replace('<', '&lt;').replace('>', '&gt;')

Added: trunk/tools/make-version-script.py
==============================================================================
--- (empty file)
+++ trunk/tools/make-version-script.py	Fri Nov 21 16:23:11 2008
@@ -0,0 +1,205 @@
+#!/usr/bin/python
+
+"""Construct a GNU ld or Debian dpkg version-script from a set of
+RFC822-style symbol lists.
+
+Usage:
+    make-version-script.py [--symbols SYMBOLS] [--unreleased-version VER]
+        [--dpkg "LIBRARY.so.0 LIBRARY0 #MINVER#"]
+        [--dpkg-build-depends-package LIBRARY-dev]
+        [FILES...]
+
+Each FILE starts with RFC822-style headers "Version:" (the name of the
+symbol version, e.g. FOO_1.2.3) and "Extends:" (either the previous
+version, or "-" if this is the first version). Next there is a blank
+line, then a list of C symbols one per line.
+
+Comments (lines starting with whitespace + "#") are allowed and ignored.
+
+If --symbols is given, SYMBOLS lists the symbols actually exported by
+the library (one per line). If --unreleased-version is given, any symbols
+in SYMBOLS but not in FILES are assigned to that version; otherwise, any
+such symbols cause an error.
+
+If --dpkg is given, produce a Debian dpkg-gensymbols file instead of a
+GNU ld version-script. The argument to --dpkg is the first line of the
+resulting symbols file, and --dpkg-build-depends-package can optionally
+be used to set the Build-Depends-Package field.
+
+This script originates in telepathy-glib <http://telepathy.freedesktop.org/> -
+please send us any changes that are needed.
+"""
+
+# Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
+# Copyright (C) 2008 Nokia Corporation
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+
+import sys
+from getopt import gnu_getopt
+from sets import Set as set
+
+
+def e(format, *args):
+    sys.stderr.write((format + '\n') % args)
+
+
+def main(abifiles, symbols=None, unreleased_version=None,
+         dpkg=False, dpkg_first_line=None, dpkg_build_depends_package=None):
+
+    gnuld = not dpkg
+    symbol_set = None
+
+    if symbols is not None:
+        symbol_set = open(symbols, 'r').readlines()
+        symbol_set = map(str.strip, symbol_set)
+        symbol_set = set(symbol_set)
+
+    versioned_symbols = set()
+
+    dpkg_symbols = []
+    dpkg_versions = []
+
+    if dpkg:
+        assert dpkg_first_line is not None
+        print dpkg_first_line
+        if dpkg_build_depends_package is not None:
+            print "* Build-Depends-Package: %s" % dpkg_build_depends_package
+
+    for filename in abifiles:
+        lines = open(filename, 'r').readlines()
+
+        version = None
+        extends = None
+        release = None
+
+        for i, line in enumerate(lines):
+            line = line.strip()
+
+            if line.startswith('#'):
+                continue
+            elif not line:
+                # the transition betwen headers and symbols
+                cut = i + 1
+                break
+            elif line.lower().startswith('version:'):
+                line = line[8:].strip()
+                version = line
+                continue
+            elif line.lower().startswith('extends:'):
+                line = line[8:].strip()
+                extends = line
+                continue
+            elif line.lower().startswith('release:'):
+                release = line[8:].strip()
+                continue
+            else:
+                e('Could not understand line in %s header: %s', filename, line)
+                raise SystemExit(1)
+
+        else:
+            e('No symbols in %s', filename)
+            raise SystemExit(1)
+
+        if version is None:
+            e('No Versions: header in %s', filename)
+            raise SystemExit(1)
+
+        if extends is None:
+            e('No Extends: header in %s', filename)
+            raise SystemExit(1)
+
+        if release is None and dpkg:
+            e('No Release: header in %s', filename)
+            raise SystemExit(1)
+
+        if dpkg:
+            dpkg_versions.append('%s %s %s' % (version, version, release))
+
+        lines = lines[cut:]
+
+        if gnuld:
+            print "%s {" % version
+            print "    global:"
+
+        for symbol in lines:
+            symbol = symbol.strip()
+
+            if symbol.startswith('#'):
+                continue
+
+            if gnuld:
+                print "        %s;" % symbol
+            elif dpkg:
+                dpkg_symbols.append('%s %s %s' % (symbol, version, release))
+
+            versioned_symbols.add(symbol)
+
+        if gnuld:
+            if extends == '-':
+                print "    local:"
+                print "        *;"
+                print "};"
+            else:
+                print "} %s;" % extends
+                print
+
+    if dpkg:
+        dpkg_symbols.sort()
+        dpkg_versions.sort()
+
+        for x in dpkg_versions:
+            print " %s" % x
+
+        for x in dpkg_symbols:
+            print " %s" % x
+
+    if symbol_set is not None:
+        missing = versioned_symbols - symbol_set
+
+        if missing:
+            e('These symbols have disappeared:')
+
+            for symbol in missing:
+                e('    %s', symbol)
+
+            raise SystemExit(1)
+
+        unreleased = symbol_set - versioned_symbols
+
+        if unreleased:
+            if unreleased_version is None:
+                e('Unversioned symbols are not allowed in releases:')
+
+                for symbol in unreleased:
+                    e('    %s', symbol)
+
+                raise SystemExit(1)
+
+            if gnuld:
+                print "%s {" % unreleased_version
+                print "    global:"
+
+                for symbol in unreleased:
+                    print "        %s;" % symbol
+
+                print "} %s;" % version
+
+
+if __name__ == '__main__':
+    options, argv = gnu_getopt (sys.argv[1:], '',
+                                ['symbols=', 'unreleased-version=',
+                                 'dpkg=', 'dpkg-build-depends-package='])
+
+    opts = {'dpkg': False}
+
+    for option, value in options:
+        if option == '--dpkg':
+            opts['dpkg'] = True
+            opts['dpkg_first_line'] = value
+        else:
+            opts[option.lstrip('-').replace('-', '_')] = value
+
+    main(argv, **opts)

Added: trunk/tools/telepathy.am
==============================================================================
--- (empty file)
+++ trunk/tools/telepathy.am	Fri Nov 21 16:23:11 2008
@@ -0,0 +1,27 @@
+## Useful top-level Makefile.am snippets for Telepathy projects.
+
+dist-hook:
+	chmod u+w ${distdir}/ChangeLog
+	if test -d ${top_srcdir}/.git; then \
+		git log --stat > ${distdir}/ChangeLog || \
+		git log > ${distdir}/ChangeLog; \
+	fi
+
+maintainer-upload-release: _maintainer-upload-release
+
+_maintainer-upload-release-check:
+	@case @VERSION@ in \
+		(*.*.*.*) \
+			echo "@VERSION@ is not a release" >&2; \
+			exit 2; \
+			;; \
+	esac
+	test -f @PACKAGE -@VERSION  tar gz
+	test -f @PACKAGE -@VERSION  tar gz asc
+	gpg --verify @PACKAGE -@VERSION  tar gz asc
+
+_maintainer-upload-release: _maintainer-upload-release-check
+	rsync -vzP @PACKAGE -@VERSION  tar gz telepathy.freedesktop.org:/srv/telepathy.freedesktop.org/www/releases/@PACKAGE@/@PACKAGE -@VERSION  tar gz
+	rsync -vzP @PACKAGE -@VERSION  tar gz asc telepathy.freedesktop.org:/srv/telepathy.freedesktop.org/www/releases/@PACKAGE@/@PACKAGE -@VERSION  tar gz asc
+
+## vim:set ft=automake:

Modified: trunk/tools/with-session-bus.sh
==============================================================================
--- trunk/tools/with-session-bus.sh	(original)
+++ trunk/tools/with-session-bus.sh	Fri Nov 21 16:23:11 2008
@@ -4,7 +4,7 @@
 # The canonical location of this program is the telepathy-glib tools/
 # directory, please synchronize any changes with that copy.
 #
-# Copyright (C) 2007 Collabora Ltd. <http://www.collabora.co.uk/>
+# Copyright (C) 2007-2008 Collabora Ltd. <http://www.collabora.co.uk/>
 #
 # Copying and distribution of this file, with or without modification,
 # are permitted in any medium without royalty provided the copyright
@@ -20,6 +20,10 @@
 {
   echo "usage: $me [options] -- program [program_options]" >&2
   echo "Requires write access to the current directory." >&2
+  echo "" >&2
+  echo "If \$WITH_SESSION_BUS_FORK_DBUS_MONITOR is set, fork dbus-monitor" >&2
+  echo "with the arguments in \$WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT." >&2
+  echo "The output of dbus-monitor is saved in $me-<pid>.dbus-monitor-logs" >&2
   exit 2
 }
 
@@ -65,6 +69,13 @@
 e=0
 DBUS_SESSION_BUS_ADDRESS="`cat $me-$$.address`"
 export DBUS_SESSION_BUS_ADDRESS
+
+if [ -n "$WITH_SESSION_BUS_FORK_DBUS_MONITOR" ] ; then
+  echo -n "Forking dbus-monitor $WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT" >&2
+  dbus-monitor $WITH_SESSION_BUS_FORK_DBUS_MONITOR_OPT \
+        &> $me-$$.dbus-monitor-logs &
+fi
+
 "$@" || e=$?
 
 trap - INT HUP TERM



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]