~ubuntu-branches/ubuntu/precise/telepathy-mission-control-5/precise

« back to all changes in this revision

Viewing changes to tools/glib-gtypes-generator.py

  • Committer: Bazaar Package Importer
  • Author(s): Simon McVittie
  • Date: 2009-07-30 12:11:55 UTC
  • mto: (0.4.1 upstream) (7.1.1 lucid) (1.1.6 upstream)
  • mto: This revision was merged to the branch mainline in revision 6.
  • Revision ID: james.westby@ubuntu.com-20090730121155-6745f645s3fg1mpk
ImportĀ upstreamĀ versionĀ 5.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
 
 
3
# Generate GLib GInterfaces from the Telepathy specification.
 
4
# The master copy of this program is in the telepathy-glib repository -
 
5
# please make any changes there.
 
6
#
 
7
# Copyright (C) 2006, 2007 Collabora Limited
 
8
#
 
9
# This library is free software; you can redistribute it and/or
 
10
# modify it under the terms of the GNU Lesser General Public
 
11
# License as published by the Free Software Foundation; either
 
12
# version 2.1 of the License, or (at your option) any later version.
 
13
#
 
14
# This library is distributed in the hope that it will be useful,
 
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
17
# Lesser General Public License for more details.
 
18
#
 
19
# You should have received a copy of the GNU Lesser General Public
 
20
# License along with this library; if not, write to the Free Software
 
21
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
22
 
 
23
import sys
 
24
import xml.dom.minidom
 
25
 
 
26
from libglibcodegen import escape_as_identifier, \
 
27
                           get_docstring, \
 
28
                           NS_TP, \
 
29
                           Signature, \
 
30
                           type_to_gtype, \
 
31
                           xml_escape
 
32
 
 
33
 
 
34
def types_to_gtypes(types):
 
35
    return [type_to_gtype(t)[1] for t in types]
 
36
 
 
37
 
 
38
class GTypesGenerator(object):
 
39
    def __init__(self, dom, output, mixed_case_prefix):
 
40
        self.dom = dom
 
41
        self.Prefix = mixed_case_prefix
 
42
        self.PREFIX_ = self.Prefix.upper() + '_'
 
43
        self.prefix_ = self.Prefix.lower() + '_'
 
44
 
 
45
        self.header = open(output + '.h', 'w')
 
46
        self.body = open(output + '-body.h', 'w')
 
47
 
 
48
        for f in (self.header, self.body):
 
49
            f.write('/* Auto-generated, do not edit.\n *\n'
 
50
                    ' * This file may be distributed under the same terms\n'
 
51
                    ' * as the specification from which it was generated.\n'
 
52
                    ' */\n\n')
 
53
 
 
54
        # keys are e.g. 'sv', values are the key escaped
 
55
        self.need_mappings = {}
 
56
        # keys are the contents of the struct (e.g. 'sssu'), values are the
 
57
        # key escaped
 
58
        self.need_structs = {}
 
59
        # keys are the contents of the struct (e.g. 'sssu'), values are the
 
60
        # key escaped
 
61
        self.need_struct_arrays = {}
 
62
 
 
63
        # keys are the contents of the array (unlike need_struct_arrays!),
 
64
        # values are the key escaped
 
65
        self.need_other_arrays = {}
 
66
 
 
67
    def do_mapping_header(self, mapping):
 
68
        members = mapping.getElementsByTagNameNS(NS_TP, 'member')
 
69
        assert len(members) == 2
 
70
 
 
71
        impl_sig = ''.join([elt.getAttribute('type')
 
72
                            for elt in members])
 
73
 
 
74
        esc_impl_sig = escape_as_identifier(impl_sig)
 
75
 
 
76
        name = (self.PREFIX_ + 'HASH_TYPE_' +
 
77
                mapping.getAttribute('name').upper())
 
78
        impl = self.prefix_ + 'type_dbus_hash_' + esc_impl_sig
 
79
 
 
80
        docstring = get_docstring(mapping) or '(Undocumented)'
 
81
 
 
82
        self.header.write('/**\n * %s:\n *\n' % name)
 
83
        self.header.write(' * %s\n' % xml_escape(docstring))
 
84
        self.header.write(' *\n')
 
85
        self.header.write(' * This macro expands to a call to a function\n')
 
86
        self.header.write(' * that returns the #GType of a #GHashTable\n')
 
87
        self.header.write(' * appropriate for representing a D-Bus\n')
 
88
        self.header.write(' * dictionary of signature\n')
 
89
        self.header.write(' * <literal>a{%s}</literal>.\n' % impl_sig)
 
90
        self.header.write(' *\n')
 
91
 
 
92
        key, value = members
 
93
 
 
94
        self.header.write(' * Keys (D-Bus type <literal>%s</literal>,\n'
 
95
                          % key.getAttribute('type'))
 
96
        tp_type = key.getAttributeNS(NS_TP, 'type')
 
97
        if tp_type:
 
98
            self.header.write(' * type <literal>%s</literal>,\n' % tp_type)
 
99
        self.header.write(' * named <literal>%s</literal>):\n'
 
100
                          % key.getAttribute('name'))
 
101
        docstring = get_docstring(key) or '(Undocumented)'
 
102
        self.header.write(' * %s\n' % xml_escape(docstring))
 
103
        self.header.write(' *\n')
 
104
 
 
105
        self.header.write(' * Values (D-Bus type <literal>%s</literal>,\n'
 
106
                          % value.getAttribute('type'))
 
107
        tp_type = value.getAttributeNS(NS_TP, 'type')
 
108
        if tp_type:
 
109
            self.header.write(' * type <literal>%s</literal>,\n' % tp_type)
 
110
        self.header.write(' * named <literal>%s</literal>):\n'
 
111
                          % value.getAttribute('name'))
 
112
        docstring = get_docstring(value) or '(Undocumented)'
 
113
        self.header.write(' * %s\n' % xml_escape(docstring))
 
114
        self.header.write(' *\n')
 
115
 
 
116
        self.header.write(' */\n')
 
117
 
 
118
        self.header.write('#define %s (%s ())\n\n' % (name, impl))
 
119
        self.need_mappings[impl_sig] = esc_impl_sig
 
120
 
 
121
        array_name = mapping.getAttribute('array-name')
 
122
        if array_name:
 
123
            gtype_name = self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper()
 
124
            contents_sig = 'a{' + impl_sig + '}'
 
125
            esc_contents_sig = escape_as_identifier(contents_sig)
 
126
            impl = self.prefix_ + 'type_dbus_array_of_' + esc_contents_sig
 
127
            self.header.write('/**\n * %s:\n\n' % gtype_name)
 
128
            self.header.write(' * Expands to a call to a function\n')
 
129
            self.header.write(' * that returns the #GType of a #GPtrArray\n')
 
130
            self.header.write(' * of #%s.\n' % name)
 
131
            self.header.write(' */\n')
 
132
            self.header.write('#define %s (%s ())\n\n' % (gtype_name, impl))
 
133
            self.need_other_arrays[contents_sig] = esc_contents_sig
 
134
 
 
135
    def do_struct_header(self, struct):
 
136
        members = struct.getElementsByTagNameNS(NS_TP, 'member')
 
137
        impl_sig = ''.join([elt.getAttribute('type') for elt in members])
 
138
        esc_impl_sig = escape_as_identifier(impl_sig)
 
139
 
 
140
        name = (self.PREFIX_ + 'STRUCT_TYPE_' +
 
141
                struct.getAttribute('name').upper())
 
142
        impl = self.prefix_ + 'type_dbus_struct_' + esc_impl_sig
 
143
        docstring = struct.getElementsByTagNameNS(NS_TP, 'docstring')
 
144
        if docstring:
 
145
            docstring = docstring[0].toprettyxml()
 
146
            if docstring.startswith('<tp:docstring>'):
 
147
                docstring = docstring[14:]
 
148
            if docstring.endswith('</tp:docstring>\n'):
 
149
                docstring = docstring[:-16]
 
150
            if docstring.strip() in ('<tp:docstring/>', ''):
 
151
                docstring = '(Undocumented)'
 
152
        else:
 
153
            docstring = '(Undocumented)'
 
154
        self.header.write('/**\n * %s:\n\n' % name)
 
155
        self.header.write(' * %s\n' % xml_escape(docstring))
 
156
        self.header.write(' *\n')
 
157
        self.header.write(' * This macro expands to a call to a function\n')
 
158
        self.header.write(' * that returns the #GType of a #GValueArray\n')
 
159
        self.header.write(' * appropriate for representing a D-Bus struct\n')
 
160
        self.header.write(' * with signature <literal>(%s)</literal>.\n'
 
161
                          % impl_sig)
 
162
        self.header.write(' *\n')
 
163
 
 
164
        for i, member in enumerate(members):
 
165
            self.header.write(' * Member %d (D-Bus type '
 
166
                              '<literal>%s</literal>,\n'
 
167
                              % (i, member.getAttribute('type')))
 
168
            tp_type = member.getAttributeNS(NS_TP, 'type')
 
169
            if tp_type:
 
170
                self.header.write(' * type <literal>%s</literal>,\n' % tp_type)
 
171
            self.header.write(' * named <literal>%s</literal>):\n'
 
172
                              % member.getAttribute('name'))
 
173
            docstring = get_docstring(member) or '(Undocumented)'
 
174
            self.header.write(' * %s\n' % xml_escape(docstring))
 
175
            self.header.write(' *\n')
 
176
 
 
177
        self.header.write(' */\n')
 
178
        self.header.write('#define %s (%s ())\n\n' % (name, impl))
 
179
 
 
180
        array_name = struct.getAttribute('array-name')
 
181
        if array_name != '':
 
182
            array_name = (self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper())
 
183
            impl = self.prefix_ + 'type_dbus_array_' + esc_impl_sig
 
184
            self.header.write('/**\n * %s:\n\n' % array_name)
 
185
            self.header.write(' * Expands to a call to a function\n')
 
186
            self.header.write(' * that returns the #GType of a #GPtrArray\n')
 
187
            self.header.write(' * of #%s.\n' % name)
 
188
            self.header.write(' */\n')
 
189
            self.header.write('#define %s (%s ())\n\n' % (array_name, impl))
 
190
            self.need_struct_arrays[impl_sig] = esc_impl_sig
 
191
 
 
192
        self.need_structs[impl_sig] = esc_impl_sig
 
193
 
 
194
    def __call__(self):
 
195
        mappings = self.dom.getElementsByTagNameNS(NS_TP, 'mapping')
 
196
        structs = self.dom.getElementsByTagNameNS(NS_TP, 'struct')
 
197
 
 
198
        for mapping in mappings:
 
199
            self.do_mapping_header(mapping)
 
200
 
 
201
        for sig in self.need_mappings:
 
202
            self.header.write('GType %stype_dbus_hash_%s (void);\n\n' %
 
203
                              (self.prefix_, self.need_mappings[sig]))
 
204
            self.body.write('GType\n%stype_dbus_hash_%s (void)\n{\n' %
 
205
                              (self.prefix_, self.need_mappings[sig]))
 
206
            self.body.write('  static GType t = 0;\n\n')
 
207
            self.body.write('  if (G_UNLIKELY (t == 0))\n')
 
208
            # FIXME: translate sig into two GTypes
 
209
            items = tuple(Signature(sig))
 
210
            gtypes = types_to_gtypes(items)
 
211
            self.body.write('    t = dbus_g_type_get_map ("GHashTable", '
 
212
                            '%s, %s);\n' % (gtypes[0], gtypes[1]))
 
213
            self.body.write('  return t;\n')
 
214
            self.body.write('}\n\n')
 
215
 
 
216
        for struct in structs:
 
217
            self.do_struct_header(struct)
 
218
 
 
219
        for sig in self.need_structs:
 
220
            self.header.write('GType %stype_dbus_struct_%s (void);\n\n' %
 
221
                              (self.prefix_, self.need_structs[sig]))
 
222
            self.body.write('GType\n%stype_dbus_struct_%s (void)\n{\n' %
 
223
                              (self.prefix_, self.need_structs[sig]))
 
224
            self.body.write('  static GType t = 0;\n\n')
 
225
            self.body.write('  if (G_UNLIKELY (t == 0))\n')
 
226
            self.body.write('    t = dbus_g_type_get_struct ("GValueArray",\n')
 
227
            items = tuple(Signature(sig))
 
228
            gtypes = types_to_gtypes(items)
 
229
            for gtype in gtypes:
 
230
                self.body.write('        %s,\n' % gtype)
 
231
            self.body.write('        G_TYPE_INVALID);\n')
 
232
            self.body.write('  return t;\n')
 
233
            self.body.write('}\n\n')
 
234
 
 
235
        for sig in self.need_struct_arrays:
 
236
            self.header.write('GType %stype_dbus_array_%s (void);\n\n' %
 
237
                              (self.prefix_, self.need_struct_arrays[sig]))
 
238
            self.body.write('GType\n%stype_dbus_array_%s (void)\n{\n' %
 
239
                              (self.prefix_, self.need_struct_arrays[sig]))
 
240
            self.body.write('  static GType t = 0;\n\n')
 
241
            self.body.write('  if (G_UNLIKELY (t == 0))\n')
 
242
            self.body.write('    t = dbus_g_type_get_collection ("GPtrArray", '
 
243
                            '%stype_dbus_struct_%s ());\n' %
 
244
                            (self.prefix_, self.need_struct_arrays[sig]))
 
245
            self.body.write('  return t;\n')
 
246
            self.body.write('}\n\n')
 
247
 
 
248
        for sig in self.need_other_arrays:
 
249
            self.header.write('GType %stype_dbus_array_of_%s (void);\n\n' %
 
250
                              (self.prefix_, self.need_other_arrays[sig]))
 
251
            self.body.write('GType\n%stype_dbus_array_of_%s (void)\n{\n' %
 
252
                              (self.prefix_, self.need_other_arrays[sig]))
 
253
            self.body.write('  static GType t = 0;\n\n')
 
254
            self.body.write('  if (G_UNLIKELY (t == 0))\n')
 
255
 
 
256
            if sig[:2] == 'a{' and sig[-1:] == '}':
 
257
                # array of mappings
 
258
                self.body.write('    t = dbus_g_type_get_collection ('
 
259
                            '"GPtrArray", '
 
260
                            '%stype_dbus_hash_%s ());\n' %
 
261
                            (self.prefix_, escape_as_identifier(sig[2:-1])))
 
262
            elif sig[:2] == 'a(' and sig[-1:] == ')':
 
263
                # array of arrays of struct
 
264
                self.body.write('    t = dbus_g_type_get_collection ('
 
265
                            '"GPtrArray", '
 
266
                            '%stype_dbus_array_%s ());\n' %
 
267
                            (self.prefix_, escape_as_identifier(sig[2:-1])))
 
268
            elif sig[:1] == 'a':
 
269
                # array of arrays of non-struct
 
270
                self.body.write('    t = dbus_g_type_get_collection ('
 
271
                            '"GPtrArray", '
 
272
                            '%stype_dbus_array_of_%s ());\n' %
 
273
                            (self.prefix_, escape_as_identifier(sig[1:])))
 
274
            else:
 
275
                raise AssertionError("array of '%s' not supported" % sig)
 
276
 
 
277
            self.body.write('  return t;\n')
 
278
            self.body.write('}\n\n')
 
279
 
 
280
if __name__ == '__main__':
 
281
    argv = sys.argv[1:]
 
282
 
 
283
    dom = xml.dom.minidom.parse(argv[0])
 
284
 
 
285
    GTypesGenerator(dom, argv[1], argv[2])()