[telepathy-gabble/master] Update code-gten tools from telepathy-glib 0.9.2

Sjoerd Simons sjoerd.simons at collabora.co.uk
Mon Dec 7 10:30:45 PST 2009


---
 tools/c-constants-gen.py       |   59 ++++++------
 tools/glib-ginterface-gen.py   |  166 ++++++++++++++++++++++++---------
 tools/glib-gtypes-generator.py |  205 ++++++++++++++++++++++++++--------------
 tools/glib-interfaces-gen.py   |   54 ++++++++---
 tools/libglibcodegen.py        |    5 +-
 tools/libtpcodegen.py          |   36 ++-----
 6 files changed, 337 insertions(+), 188 deletions(-)

diff --git a/tools/c-constants-gen.py b/tools/c-constants-gen.py
index f338257..8969ffd 100644
--- a/tools/c-constants-gen.py
+++ b/tools/c-constants-gen.py
@@ -3,7 +3,7 @@
 from sys import argv, stdout, stderr
 import xml.dom.minidom
 
-from libglibcodegen import NS_TP, camelcase_to_upper, get_docstring, \
+from libglibcodegen import NS_TP, get_docstring, \
         get_descendant_text, get_by_path
 
 class Generator(object):
@@ -16,21 +16,24 @@ class Generator(object):
         self.do_body()
         self.do_footer()
 
+    def write(self, code):
+        stdout.write(code.encode('utf-8'))
+
     # Header
     def do_header(self):
-        stdout.write('/* Generated from ')
-        stdout.write(get_descendant_text(get_by_path(self.spec, 'title')))
+        self.write('/* Generated from ')
+        self.write(get_descendant_text(get_by_path(self.spec, 'title')))
         version = get_by_path(self.spec, "version")
         if version:
-            stdout.write(', version ' + get_descendant_text(version))
-        stdout.write('\n\n')
+            self.write(', version ' + get_descendant_text(version))
+        self.write('\n\n')
         for copyright in get_by_path(self.spec, 'copyright'):
-            stdout.write(get_descendant_text(copyright))
-            stdout.write('\n')
-        stdout.write(get_descendant_text(get_by_path(self.spec, 'license')))
-        stdout.write('\n')
-        stdout.write(get_descendant_text(get_by_path(self.spec, 'docstring')))
-        stdout.write("""
+            self.write(get_descendant_text(copyright))
+            self.write('\n')
+        self.write(get_descendant_text(get_by_path(self.spec, 'license')))
+        self.write('\n')
+        self.write(get_descendant_text(get_by_path(self.spec, 'docstring')))
+        self.write("""
  */
 
 #ifdef __cplusplus
@@ -51,28 +54,28 @@ extern "C" {
         value_prefix = flags.getAttribute('singular') or \
                        flags.getAttribute('value-prefix') or \
                        flags.getAttribute('name')
-        stdout.write("""\
+        self.write("""\
 /**
  *
 %s:
 """ % (self.prefix + name).replace('_', ''))
         for flag in get_by_path(flags, 'flag'):
             self.do_gtkdoc(flag, value_prefix)
-        stdout.write(' *\n')
+        self.write(' *\n')
         docstrings = get_by_path(flags, 'docstring')
         if docstrings:
-            stdout.write("""\
+            self.write("""\
  * <![CDATA[%s]]>
  *
 """ % get_descendant_text(docstrings).replace('\n', ' '))
-        stdout.write("""\
+        self.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("""\
+        self.write("""\
 } %s;
 
 """ % (self.prefix + name).replace('_', ''))
@@ -84,7 +87,7 @@ typedef enum {
                        enum.getAttribute('name')
         name_plural = enum.getAttribute('plural') or \
                       enum.getAttribute('name') + 's'
-        stdout.write("""\
+        self.write("""\
 /**
  *
 %s:
@@ -92,21 +95,21 @@ typedef enum {
         vals = get_by_path(enum, 'enumvalue')
         for val in vals:
             self.do_gtkdoc(val, value_prefix)
-        stdout.write(' *\n')
+        self.write(' *\n')
         docstrings = get_by_path(enum, 'docstring')
         if docstrings:
-            stdout.write("""\
+            self.write("""\
  * <![CDATA[%s]]>
  *
 """ % get_descendant_text(docstrings).replace('\n', ' '))
-        stdout.write("""\
+        self.write("""\
  * Bitfield/set of flags generated from the Telepathy specification.
  */
 typedef enum {
 """)
         for val in vals:
             self.do_val(val, value_prefix)
-        stdout.write("""\
+        self.write("""\
 } %(mixed-name)s;
 
 /**
@@ -127,20 +130,20 @@ typedef enum {
                 (suffix or name)).upper()
         assert not (name and suffix) or name == suffix, \
                 'Flag/enumvalue name %s != suffix %s' % (name, suffix)
-        stdout.write('    %s = %s,\n' % (use_name, val.getAttribute('value')))
+        self.write('    %s = %s,\n' % (use_name, val.getAttribute('value')))
 
     def do_gtkdoc(self, node, value_prefix):
-        stdout.write(' * @')
-        stdout.write((self.prefix + value_prefix + '_' +
+        self.write(' * @')
+        self.write((self.prefix + value_prefix + '_' +
             node.getAttribute('suffix')).upper())
-        stdout.write(': <![CDATA[')
+        self.write(': <![CDATA[')
         docstring = get_by_path(node, 'docstring')
-        stdout.write(get_descendant_text(docstring).replace('\n', ' '))
-        stdout.write(']]>\n')
+        self.write(get_descendant_text(docstring).replace('\n', ' '))
+        self.write(']]>\n')
 
     # Footer
     def do_footer(self):
-        stdout.write("""
+        self.write("""
 #ifdef __cplusplus
 }
 #endif
diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py
index 9eb7af5..13f7f69 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
 
 
@@ -66,6 +66,7 @@ class Generator(object):
         self.prefix_ = prefix.lower()
         self.PREFIX_ = prefix.upper()
 
+        self.basename = basename
         self.signal_marshal_prefix = signal_marshal_prefix
         self.headers = headers
         self.end_headers = end_headers
@@ -170,7 +171,42 @@ class Generator(object):
         self.h(' * %s%sClass:' % (self.Prefix, node_name_mixed))
         self.h(' *')
         self.h(' * The class of %s%s.' % (self.Prefix, node_name_mixed))
+
+        if methods:
+            self.h(' *')
+            self.h(' * In a full implementation of this interface (i.e. all')
+            self.h(' * methods implemented), the interface initialization')
+            self.h(' * function used in G_IMPLEMENT_INTERFACE() would')
+            self.h(' * typically look like this:')
+            self.h(' *')
+            self.h(' * <programlisting>')
+            self.h(' * static void')
+            self.h(' * implement_%s (gpointer klass,' % self.node_name_lc)
+            self.h(' *     gpointer unused G_GNUC_UNUSED)')
+            self.h(' * {')
+            # "#" is special to gtkdoc under some circumstances; it appears
+            # that escaping "##" as "#<!---->#" or "&#35;&#35;" doesn't work,
+            # but adding an extra hash symbol does. Thanks, gtkdoc :-(
+            self.h(' * #define IMPLEMENT(x) %s%s_implement_###x (\\'
+                   % (self.prefix_, self.node_name_lc))
+            self.h(' *   klass, my_object_###x)')
+
+            for method in methods:
+                class_member_name = method.getAttribute('tp:name-for-bindings')
+                class_member_name = class_member_name.lower()
+                self.h(' *   IMPLEMENT (%s);' % class_member_name)
+
+            self.h(' * #undef IMPLEMENT')
+            self.h(' * }')
+            self.h(' * </programlisting>')
+        else:
+            self.h(' * This interface has no D-Bus methods, so an')
+            self.h(' * implementation can typically pass %NULL to')
+            self.h(' * G_IMPLEMENT_INTERFACE() as the interface')
+            self.h(' * initialization function.')
+
         self.h(' */')
+
         self.h('typedef struct _%s%sClass %s%sClass;'
                % (self.Prefix, node_name_mixed, self.Prefix, node_name_mixed))
         self.h('')
@@ -207,48 +243,56 @@ class Generator(object):
         self.b('%s%s_base_init_once (gpointer klass G_GNUC_UNUSED)'
                % (self.prefix_, node_name_lc))
         self.b('{')
-        self.b('  static TpDBusPropertiesMixinPropInfo properties[%d] = {'
-               % (len(properties) + 1))
 
-        for m in properties:
-            access = m.getAttribute('access')
-            assert access in ('read', 'write', 'readwrite')
+        if properties:
+            self.b('  static TpDBusPropertiesMixinPropInfo properties[%d] = {'
+                   % (len(properties) + 1))
 
-            if access == 'read':
-                flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_READ'
-            elif access == 'write':
-                flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE'
-            else:
-                flags = ('TP_DBUS_PROPERTIES_MIXIN_FLAG_READ | '
-                         'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE')
+            for m in properties:
+                access = m.getAttribute('access')
+                assert access in ('read', 'write', 'readwrite')
 
-            self.b('      { 0, %s, "%s", 0, NULL, NULL }, /* %s */'
-                   % (flags, m.getAttribute('type'), m.getAttribute('name')))
+                if access == 'read':
+                    flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_READ'
+                elif access == 'write':
+                    flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE'
+                else:
+                    flags = ('TP_DBUS_PROPERTIES_MIXIN_FLAG_READ | '
+                             'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE')
 
-        self.b('      { 0, 0, NULL, 0, NULL, NULL }')
-        self.b('  };')
-        self.b('  static TpDBusPropertiesMixinIfaceInfo interface =')
-        self.b('      { 0, properties, NULL, NULL };')
-        self.b('')
-        self.b('  interface.dbus_interface = g_quark_from_static_string '
-               '("%s");' % self.iface_name)
+                self.b('      { 0, %s, "%s", 0, NULL, NULL }, /* %s */'
+                       % (flags, m.getAttribute('type'), m.getAttribute('name')))
 
-        for i, m in enumerate(properties):
-            self.b('  properties[%d].name = g_quark_from_static_string ("%s");'
-                   % (i, m.getAttribute('name')))
-            self.b('  properties[%d].type = %s;'
-                   % (i, type_to_gtype(m.getAttribute('type'))[1]))
+            self.b('      { 0, 0, NULL, 0, NULL, NULL }')
+            self.b('  };')
+            self.b('  static TpDBusPropertiesMixinIfaceInfo interface =')
+            self.b('      { 0, properties, NULL, NULL };')
+            self.b('')
 
-        self.b('  tp_svc_interface_set_dbus_properties_info (%s, &interface);'
-               % self.current_gtype)
 
-        self.b('')
-        for s in base_init_code:
-            self.b(s)
         self.b('  dbus_g_object_type_install_info (%s%s_get_type (),'
                % (self.prefix_, node_name_lc))
         self.b('      &_%s%s_object_info);'
                % (self.prefix_, node_name_lc))
+        self.b('')
+
+        if properties:
+            self.b('  interface.dbus_interface = g_quark_from_static_string '
+                   '("%s");' % self.iface_name)
+
+            for i, m in enumerate(properties):
+                self.b('  properties[%d].name = g_quark_from_static_string ("%s");'
+                       % (i, m.getAttribute('name')))
+                self.b('  properties[%d].type = %s;'
+                           % (i, type_to_gtype(m.getAttribute('type'))[1]))
+
+            self.b('  tp_svc_interface_set_dbus_properties_info (%s, &interface);'
+                   % self.current_gtype)
+
+            self.b('')
+
+        for s in base_init_code:
+            self.b(s)
         self.b('}')
 
         self.b('static void')
@@ -276,6 +320,10 @@ class Generator(object):
         for method, offset in zip(methods, offsets):
             self.do_method_glue(method, offset)
 
+        if len(methods) == 0:
+            # empty arrays are a gcc extension, so put in a dummy member
+            self.b("  { NULL, NULL, 0 }")
+
         self.b('};')
         self.b('')
 
@@ -335,7 +383,11 @@ class Generator(object):
         return ''.join(info) + '\0', offsets
 
     def do_method_glue(self, method, offset):
-        lc_name = camelcase_to_lower(method.getAttribute('name'))
+        lc_name = method.getAttribute('tp:name-for-bindings')
+        if method.getAttribute('name') != lc_name.replace('_', ''):
+            raise AssertionError('Method %s tp:name-for-bindings (%s) does '
+                    'not match' % (method.getAttribute('name'), lc_name))
+        lc_name = lc_name.lower()
 
         marshaller = method_to_glue_marshal_name(method,
                 self.signal_marshal_prefix)
@@ -357,7 +409,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)
@@ -372,7 +430,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 + '_' +
@@ -533,8 +596,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
@@ -616,23 +686,33 @@ class Generator(object):
 
         return in_base_init
 
+    def have_properties(self, nodes):
+        for node in nodes:
+            interface =  node.getElementsByTagName('interface')[0]
+            if interface.getElementsByTagName('property'):
+                return True
+        return False
+
     def __call__(self):
+        nodes = self.dom.getElementsByTagName('node')
+        nodes.sort(cmp_by_name)
+
         self.h('#include <glib-object.h>')
         self.h('#include <dbus/dbus-glib.h>')
-        self.h('#include <telepathy-glib/dbus-properties-mixin.h>')
+
+        if self.have_properties(nodes):
+            self.h('#include <telepathy-glib/dbus-properties-mixin.h>')
+
         self.h('')
         self.h('G_BEGIN_DECLS')
         self.h('')
 
-        self.b('#include "%s.h"' % basename)
+        self.b('#include "%s.h"' % self.basename)
         self.b('')
         for header in self.headers:
             self.b('#include %s' % header)
         self.b('')
 
-        nodes = self.dom.getElementsByTagName('node')
-        nodes.sort(cmp_by_name)
-
         for node in nodes:
             self.do_node(node)
 
@@ -645,8 +725,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():
diff --git a/tools/glib-gtypes-generator.py b/tools/glib-gtypes-generator.py
index fcb46e8..ebc2ad4 100644
--- a/tools/glib-gtypes-generator.py
+++ b/tools/glib-gtypes-generator.py
@@ -51,9 +51,24 @@ 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 h(self, code):
+        self.header.write(code.encode("utf-8"))
+
+    def c(self, code):
+        self.body.write(code.encode("utf-8"))
 
     def do_mapping_header(self, mapping):
         members = mapping.getElementsByTagNameNS(NS_TP, 'member')
@@ -70,45 +85,59 @@ class GTypesGenerator(object):
 
         docstring = get_docstring(mapping) or '(Undocumented)'
 
-        self.header.write('/**\n * %s:\n *\n' % name)
-        self.header.write(' * %s\n' % xml_escape(docstring))
-        self.header.write(' *\n')
-        self.header.write(' * This macro expands to a call to a function\n')
-        self.header.write(' * that returns the #GType of a #GHashTable\n')
-        self.header.write(' * appropriate for representing a D-Bus\n')
-        self.header.write(' * dictionary of signature\n')
-        self.header.write(' * <literal>a{%s}</literal>.\n' % impl_sig)
-        self.header.write(' *\n')
+        self.h('/**\n * %s:\n *\n' % name)
+        self.h(' * %s\n' % xml_escape(docstring))
+        self.h(' *\n')
+        self.h(' * This macro expands to a call to a function\n')
+        self.h(' * that returns the #GType of a #GHashTable\n')
+        self.h(' * appropriate for representing a D-Bus\n')
+        self.h(' * dictionary of signature\n')
+        self.h(' * <literal>a{%s}</literal>.\n' % impl_sig)
+        self.h(' *\n')
 
         key, value = members
 
-        self.header.write(' * Keys (D-Bus type <literal>%s</literal>,\n'
+        self.h(' * Keys (D-Bus type <literal>%s</literal>,\n'
                           % key.getAttribute('type'))
         tp_type = key.getAttributeNS(NS_TP, 'type')
         if tp_type:
-            self.header.write(' * type <literal>%s</literal>,\n' % tp_type)
-        self.header.write(' * named <literal>%s</literal>):\n'
+            self.h(' * type <literal>%s</literal>,\n' % tp_type)
+        self.h(' * named <literal>%s</literal>):\n'
                           % key.getAttribute('name'))
         docstring = get_docstring(key) or '(Undocumented)'
-        self.header.write(' * %s\n' % xml_escape(docstring))
-        self.header.write(' *\n')
+        self.h(' * %s\n' % xml_escape(docstring))
+        self.h(' *\n')
 
-        self.header.write(' * Values (D-Bus type <literal>%s</literal>,\n'
+        self.h(' * Values (D-Bus type <literal>%s</literal>,\n'
                           % value.getAttribute('type'))
         tp_type = value.getAttributeNS(NS_TP, 'type')
         if tp_type:
-            self.header.write(' * type <literal>%s</literal>,\n' % tp_type)
-        self.header.write(' * named <literal>%s</literal>):\n'
+            self.h(' * type <literal>%s</literal>,\n' % tp_type)
+        self.h(' * named <literal>%s</literal>):\n'
                           % value.getAttribute('name'))
         docstring = get_docstring(value) or '(Undocumented)'
-        self.header.write(' * %s\n' % xml_escape(docstring))
-        self.header.write(' *\n')
+        self.h(' * %s\n' % xml_escape(docstring))
+        self.h(' *\n')
 
-        self.header.write(' */\n')
+        self.h(' */\n')
 
-        self.header.write('#define %s (%s ())\n\n' % (name, impl))
+        self.h('#define %s (%s ())\n\n' % (name, impl))
         self.need_mappings[impl_sig] = esc_impl_sig
 
+        array_name = mapping.getAttribute('array-name')
+        if array_name:
+            gtype_name = self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper()
+            contents_sig = 'a{' + impl_sig + '}'
+            esc_contents_sig = escape_as_identifier(contents_sig)
+            impl = self.prefix_ + 'type_dbus_array_of_' + esc_contents_sig
+            self.h('/**\n * %s:\n\n' % gtype_name)
+            self.h(' * Expands to a call to a function\n')
+            self.h(' * that returns the #GType of a #GPtrArray\n')
+            self.h(' * of #%s.\n' % name)
+            self.h(' */\n')
+            self.h('#define %s (%s ())\n\n' % (gtype_name, impl))
+            self.need_other_arrays[contents_sig] = esc_contents_sig
+
     def do_struct_header(self, struct):
         members = struct.getElementsByTagNameNS(NS_TP, 'member')
         impl_sig = ''.join([elt.getAttribute('type') for elt in members])
@@ -128,43 +157,43 @@ class GTypesGenerator(object):
                 docstring = '(Undocumented)'
         else:
             docstring = '(Undocumented)'
-        self.header.write('/**\n * %s:\n\n' % name)
-        self.header.write(' * %s\n' % xml_escape(docstring))
-        self.header.write(' *\n')
-        self.header.write(' * This macro expands to a call to a function\n')
-        self.header.write(' * that returns the #GType of a #GValueArray\n')
-        self.header.write(' * appropriate for representing a D-Bus struct\n')
-        self.header.write(' * with signature <literal>(%s)</literal>.\n'
+        self.h('/**\n * %s:\n\n' % name)
+        self.h(' * %s\n' % xml_escape(docstring))
+        self.h(' *\n')
+        self.h(' * This macro expands to a call to a function\n')
+        self.h(' * that returns the #GType of a #GValueArray\n')
+        self.h(' * appropriate for representing a D-Bus struct\n')
+        self.h(' * with signature <literal>(%s)</literal>.\n'
                           % impl_sig)
-        self.header.write(' *\n')
+        self.h(' *\n')
 
         for i, member in enumerate(members):
-            self.header.write(' * Member %d (D-Bus type '
+            self.h(' * Member %d (D-Bus type '
                               '<literal>%s</literal>,\n'
                               % (i, member.getAttribute('type')))
             tp_type = member.getAttributeNS(NS_TP, 'type')
             if tp_type:
-                self.header.write(' * type <literal>%s</literal>,\n' % tp_type)
-            self.header.write(' * named <literal>%s</literal>):\n'
+                self.h(' * type <literal>%s</literal>,\n' % tp_type)
+            self.h(' * named <literal>%s</literal>):\n'
                               % member.getAttribute('name'))
             docstring = get_docstring(member) or '(Undocumented)'
-            self.header.write(' * %s\n' % xml_escape(docstring))
-            self.header.write(' *\n')
+            self.h(' * %s\n' % xml_escape(docstring))
+            self.h(' *\n')
 
-        self.header.write(' */\n')
-        self.header.write('#define %s (%s ())\n\n' % (name, impl))
+        self.h(' */\n')
+        self.h('#define %s (%s ())\n\n' % (name, impl))
 
         array_name = struct.getAttribute('array-name')
         if array_name != '':
             array_name = (self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper())
             impl = self.prefix_ + 'type_dbus_array_' + esc_impl_sig
-            self.header.write('/**\n * %s:\n\n' % array_name)
-            self.header.write(' * Expands to a call to a function\n')
-            self.header.write(' * that returns the #GType of a #GPtrArray\n')
-            self.header.write(' * of #%s.\n' % name)
-            self.header.write(' */\n')
-            self.header.write('#define %s (%s ())\n\n' % (array_name, impl))
-            self.need_arrays[impl_sig] = esc_impl_sig
+            self.h('/**\n * %s:\n\n' % array_name)
+            self.h(' * Expands to a call to a function\n')
+            self.h(' * that returns the #GType of a #GPtrArray\n')
+            self.h(' * of #%s.\n' % name)
+            self.h(' */\n')
+            self.h('#define %s (%s ())\n\n' % (array_name, impl))
+            self.need_struct_arrays[impl_sig] = esc_impl_sig
 
         self.need_structs[impl_sig] = esc_impl_sig
 
@@ -176,51 +205,83 @@ class GTypesGenerator(object):
             self.do_mapping_header(mapping)
 
         for sig in self.need_mappings:
-            self.header.write('GType %stype_dbus_hash_%s (void);\n\n' %
+            self.h('GType %stype_dbus_hash_%s (void);\n\n' %
                               (self.prefix_, self.need_mappings[sig]))
-            self.body.write('GType\n%stype_dbus_hash_%s (void)\n{\n' %
+            self.c('GType\n%stype_dbus_hash_%s (void)\n{\n' %
                               (self.prefix_, self.need_mappings[sig]))
-            self.body.write('  static GType t = 0;\n\n')
-            self.body.write('  if (G_UNLIKELY (t == 0))\n')
+            self.c('  static GType t = 0;\n\n')
+            self.c('  if (G_UNLIKELY (t == 0))\n')
             # FIXME: translate sig into two GTypes
             items = tuple(Signature(sig))
             gtypes = types_to_gtypes(items)
-            self.body.write('    t = dbus_g_type_get_map ("GHashTable", '
+            self.c('    t = dbus_g_type_get_map ("GHashTable", '
                             '%s, %s);\n' % (gtypes[0], gtypes[1]))
-            self.body.write('  return t;\n')
-            self.body.write('}\n\n')
+            self.c('  return t;\n')
+            self.c('}\n\n')
 
         for struct in structs:
             self.do_struct_header(struct)
 
         for sig in self.need_structs:
-            self.header.write('GType %stype_dbus_struct_%s (void);\n\n' %
+            self.h('GType %stype_dbus_struct_%s (void);\n\n' %
                               (self.prefix_, self.need_structs[sig]))
-            self.body.write('GType\n%stype_dbus_struct_%s (void)\n{\n' %
+            self.c('GType\n%stype_dbus_struct_%s (void)\n{\n' %
                               (self.prefix_, self.need_structs[sig]))
-            self.body.write('  static GType t = 0;\n\n')
-            self.body.write('  if (G_UNLIKELY (t == 0))\n')
-            self.body.write('    t = dbus_g_type_get_struct ("GValueArray",\n')
+            self.c('  static GType t = 0;\n\n')
+            self.c('  if (G_UNLIKELY (t == 0))\n')
+            self.c('    t = dbus_g_type_get_struct ("GValueArray",\n')
             items = tuple(Signature(sig))
             gtypes = types_to_gtypes(items)
             for gtype in gtypes:
-                self.body.write('        %s,\n' % gtype)
-            self.body.write('        G_TYPE_INVALID);\n')
-            self.body.write('  return t;\n')
-            self.body.write('}\n\n')
-
-        for sig in self.need_arrays:
-            self.header.write('GType %stype_dbus_array_%s (void);\n\n' %
-                              (self.prefix_, self.need_structs[sig]))
-            self.body.write('GType\n%stype_dbus_array_%s (void)\n{\n' %
-                              (self.prefix_, self.need_structs[sig]))
-            self.body.write('  static GType t = 0;\n\n')
-            self.body.write('  if (G_UNLIKELY (t == 0))\n')
-            self.body.write('    t = dbus_g_type_get_collection ("GPtrArray", '
+                self.c('        %s,\n' % gtype)
+            self.c('        G_TYPE_INVALID);\n')
+            self.c('  return t;\n')
+            self.c('}\n\n')
+
+        for sig in self.need_struct_arrays:
+            self.h('GType %stype_dbus_array_%s (void);\n\n' %
+                              (self.prefix_, self.need_struct_arrays[sig]))
+            self.c('GType\n%stype_dbus_array_%s (void)\n{\n' %
+                              (self.prefix_, self.need_struct_arrays[sig]))
+            self.c('  static GType t = 0;\n\n')
+            self.c('  if (G_UNLIKELY (t == 0))\n')
+            self.c('    t = dbus_g_type_get_collection ("GPtrArray", '
                             '%stype_dbus_struct_%s ());\n' %
-                            (self.prefix_, self.need_structs[sig]))
-            self.body.write('  return t;\n')
-            self.body.write('}\n\n')
+                            (self.prefix_, self.need_struct_arrays[sig]))
+            self.c('  return t;\n')
+            self.c('}\n\n')
+
+        for sig in self.need_other_arrays:
+            self.h('GType %stype_dbus_array_of_%s (void);\n\n' %
+                              (self.prefix_, self.need_other_arrays[sig]))
+            self.c('GType\n%stype_dbus_array_of_%s (void)\n{\n' %
+                              (self.prefix_, self.need_other_arrays[sig]))
+            self.c('  static GType t = 0;\n\n')
+            self.c('  if (G_UNLIKELY (t == 0))\n')
+
+            if sig[:2] == 'a{' and sig[-1:] == '}':
+                # array of mappings
+                self.c('    t = dbus_g_type_get_collection ('
+                            '"GPtrArray", '
+                            '%stype_dbus_hash_%s ());\n' %
+                            (self.prefix_, escape_as_identifier(sig[2:-1])))
+            elif sig[:2] == 'a(' and sig[-1:] == ')':
+                # array of arrays of struct
+                self.c('    t = dbus_g_type_get_collection ('
+                            '"GPtrArray", '
+                            '%stype_dbus_array_%s ());\n' %
+                            (self.prefix_, escape_as_identifier(sig[2:-1])))
+            elif sig[:1] == 'a':
+                # array of arrays of non-struct
+                self.c('    t = dbus_g_type_get_collection ('
+                            '"GPtrArray", '
+                            '%stype_dbus_array_of_%s ());\n' %
+                            (self.prefix_, escape_as_identifier(sig[1:])))
+            else:
+                raise AssertionError("array of '%s' not supported" % sig)
+
+            self.c('  return t;\n')
+            self.c('}\n\n')
 
 if __name__ == '__main__':
     argv = sys.argv[1:]
diff --git a/tools/glib-interfaces-gen.py b/tools/glib-interfaces-gen.py
index 9b23764..9543968 100644
--- a/tools/glib-interfaces-gen.py
+++ b/tools/glib-interfaces-gen.py
@@ -13,26 +13,32 @@ class Generator(object):
         self.decls = open(declfile, 'w')
         self.spec = get_by_path(dom, "spec")[0]
 
+    def h(self, code):
+        self.decls.write(code.encode('utf-8'))
+
+    def c(self, code):
+        self.impls.write(code.encode('utf-8'))
+
     def __call__(self):
-        for file in self.decls, self.impls:
-            self.do_header(file)
+        for f in self.h, self.c:
+            self.do_header(f)
         self.do_body()
 
     # Header
-    def do_header(self, file):
-        file.write('/* Generated from: ')
-        file.write(get_descendant_text(get_by_path(self.spec, 'title')))
+    def do_header(self, f):
+        f('/* Generated from: ')
+        f(get_descendant_text(get_by_path(self.spec, 'title')))
         version = get_by_path(self.spec, "version")
         if version:
-            file.write(' version ' + get_descendant_text(version))
-        file.write('\n\n')
+            f(' version ' + get_descendant_text(version))
+        f('\n\n')
         for copyright in get_by_path(self.spec, 'copyright'):
-            file.write(get_descendant_text(copyright))
-            file.write('\n')
-        file.write('\n')
-        file.write(get_descendant_text(get_by_path(self.spec, 'license')))
-        file.write(get_descendant_text(get_by_path(self.spec, 'docstring')))
-        file.write("""
+            f(get_descendant_text(copyright))
+            f('\n')
+        f('\n')
+        f(get_descendant_text(get_by_path(self.spec, 'license')))
+        f(get_descendant_text(get_by_path(self.spec, 'docstring')))
+        f("""
  */
 
 """)
@@ -44,7 +50,7 @@ class Generator(object):
 
     def do_iface(self, iface):
         parent_name = get_by_path(iface, '../@name')
-        self.decls.write("""\
+        self.h("""\
 /**
  * %(IFACE_DEFINE)s:
  *
@@ -56,7 +62,7 @@ class Generator(object):
             parent_name).upper().replace('/', ''),
        'name' : iface.getAttribute('name')})
 
-        self.decls.write("""
+        self.h("""
 /**
  * %(IFACE_QUARK_DEFINE)s:
  *
@@ -74,7 +80,7 @@ GQuark %(iface_quark_func)s (void);
             parent_name).lower().replace('/', ''),
        'name' : iface.getAttribute('name')})
 
-        self.impls.write("""\
+        self.c("""\
 GQuark
 %(iface_quark_func)s (void)
 {
@@ -92,6 +98,22 @@ GQuark
             parent_name).lower().replace('/', ''),
        'name' : iface.getAttribute('name')})
 
+        for prop in iface.getElementsByTagNameNS(None, 'property'):
+            self.decls.write("""
+/**
+ * %(IFACE_PREFIX)s_%(PROP_UC)s:
+ *
+ * The fully-qualified property name "%(name)s.%(prop)s"
+ */
+#define %(IFACE_PREFIX)s_%(PROP_UC)s \\
+"%(name)s.%(prop)s"
+""" % {'IFACE_PREFIX' : (self.prefix + 'PROP_' + \
+                parent_name).upper().replace('/', ''),
+           'PROP_UC': prop.getAttributeNS(NS_TP, "name-for-bindings").upper(),
+           'name' : iface.getAttribute('name'),
+           'prop' : prop.getAttribute('name'),
+           })
+
 if __name__ == '__main__':
     argv = argv[1:]
     Generator(argv[0], argv[1], argv[2], xml.dom.minidom.parse(argv[3]))()
diff --git a/tools/libglibcodegen.py b/tools/libglibcodegen.py
index 129c179..6a9d214 100644
--- a/tools/libglibcodegen.py
+++ b/tools/libglibcodegen.py
@@ -23,14 +23,13 @@ please make any changes there.
 
 from libtpcodegen import NS_TP, \
                          Signature, \
-                         camelcase_to_lower, \
-                         camelcase_to_upper, \
                          cmp_by_name, \
                          escape_as_identifier, \
                          get_by_path, \
                          get_descendant_text, \
                          get_docstring, \
-                         xml_escape
+                         xml_escape, \
+                         get_deprecated
 
 def dbus_gutils_wincaps_to_uscore(s):
     """Bug-for-bug compatible Python port of _dbus_gutils_wincaps_to_uscore
diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py
index 6391f1a..837ff2f 100644
--- a/tools/libtpcodegen.py
+++ b/tools/libtpcodegen.py
@@ -29,32 +29,6 @@ NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
 _ASCII_ALNUM = ascii_letters + digits
 
 
-def camelcase_to_lower(s):
-    out ="";
-    out += s[0].lower()
-    last_upper=False
-    if s[0].isupper():
-        last_upper=True
-    for i in range(1,len(s)):
-        if s[i].isupper():
-            if last_upper:
-                if (i+1) < len(s) and  s[i+1].islower():
-                    out += "_" + s[i].lower()
-                else:
-                    out += s[i].lower()
-            else:
-                out += "_" + s[i].lower()
-            last_upper=True
-        else:
-            out += s[i]
-            last_upper=False
-    return out
-
-
-def camelcase_to_upper(s):
-    return camelcase_to_lower(s).upper()
-
-
 def cmp_by_name(node1, node2):
     return cmp(node1.getAttributeNode("name").nodeValue,
                node2.getAttributeNode("name").nodeValue)
@@ -146,6 +120,16 @@ def get_docstring(element):
             docstring = ''
     return docstring
 
+def get_deprecated(element):
+    text = []
+    for x in element.childNodes:
+        if hasattr(x, 'data'):
+            text.append(x.data.replace('\n', ' ').strip())
+        else:
+            # This caters for tp:dbus-ref elements, but little else.
+            if x.childNodes and hasattr(x.childNodes[0], 'data'):
+                text.append(x.childNodes[0].data.replace('\n', ' ').strip())
+    return ' '.join(text)
 
 def get_descendant_text(element_or_elements):
     if not element_or_elements:
-- 
1.5.6.5



More information about the telepathy-commits mailing list