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.
7
# Copyright (C) 2006, 2007 Collabora Limited
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.
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.
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
24
import xml.dom.minidom
26
from libglibcodegen import escape_as_identifier, \
34
def types_to_gtypes(types):
35
return [type_to_gtype(t)[1] for t in types]
38
class GTypesGenerator(object):
39
def __init__(self, dom, output, mixed_case_prefix):
41
self.Prefix = mixed_case_prefix
42
self.PREFIX_ = self.Prefix.upper() + '_'
43
self.prefix_ = self.Prefix.lower() + '_'
45
self.header = open(output + '.h', 'w')
46
self.body = open(output + '-body.h', 'w')
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'
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
58
self.need_structs = {}
59
# keys are the contents of the struct (e.g. 'sssu'), values are the
61
self.need_struct_arrays = {}
63
# keys are the contents of the array (unlike need_struct_arrays!),
64
# values are the key escaped
65
self.need_other_arrays = {}
67
def do_mapping_header(self, mapping):
68
members = mapping.getElementsByTagNameNS(NS_TP, 'member')
69
assert len(members) == 2
71
impl_sig = ''.join([elt.getAttribute('type')
74
esc_impl_sig = escape_as_identifier(impl_sig)
76
name = (self.PREFIX_ + 'HASH_TYPE_' +
77
mapping.getAttribute('name').upper())
78
impl = self.prefix_ + 'type_dbus_hash_' + esc_impl_sig
80
docstring = get_docstring(mapping) or '(Undocumented)'
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')
94
self.header.write(' * Keys (D-Bus type <literal>%s</literal>,\n'
95
% key.getAttribute('type'))
96
tp_type = key.getAttributeNS(NS_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')
105
self.header.write(' * Values (D-Bus type <literal>%s</literal>,\n'
106
% value.getAttribute('type'))
107
tp_type = value.getAttributeNS(NS_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')
116
self.header.write(' */\n')
118
self.header.write('#define %s (%s ())\n\n' % (name, impl))
119
self.need_mappings[impl_sig] = esc_impl_sig
121
array_name = mapping.getAttribute('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
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)
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')
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)'
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'
162
self.header.write(' *\n')
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')
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')
177
self.header.write(' */\n')
178
self.header.write('#define %s (%s ())\n\n' % (name, impl))
180
array_name = struct.getAttribute('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
192
self.need_structs[impl_sig] = esc_impl_sig
195
mappings = self.dom.getElementsByTagNameNS(NS_TP, 'mapping')
196
structs = self.dom.getElementsByTagNameNS(NS_TP, 'struct')
198
for mapping in mappings:
199
self.do_mapping_header(mapping)
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')
216
for struct in structs:
217
self.do_struct_header(struct)
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)
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')
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')
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')
256
if sig[:2] == 'a{' and sig[-1:] == '}':
258
self.body.write(' t = dbus_g_type_get_collection ('
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 ('
266
'%stype_dbus_array_%s ());\n' %
267
(self.prefix_, escape_as_identifier(sig[2:-1])))
269
# array of arrays of non-struct
270
self.body.write(' t = dbus_g_type_get_collection ('
272
'%stype_dbus_array_of_%s ());\n' %
273
(self.prefix_, escape_as_identifier(sig[1:])))
275
raise AssertionError("array of '%s' not supported" % sig)
277
self.body.write(' return t;\n')
278
self.body.write('}\n\n')
280
if __name__ == '__main__':
283
dom = xml.dom.minidom.parse(argv[0])
285
GTypesGenerator(dom, argv[1], argv[2])()