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 libtpcodegen
import file_set_contents
, u
27 from libglibcodegen
import escape_as_identifier
, \
35 def types_to_gtypes(types
):
36 return [type_to_gtype(t
)[1] for t
in types
]
39 class GTypesGenerator(object):
40 def __init__(self
, dom
, output
, mixed_case_prefix
):
42 self
.Prefix
= mixed_case_prefix
43 self
.PREFIX_
= self
.Prefix
.upper() + '_'
44 self
.prefix_
= self
.Prefix
.lower() + '_'
51 for f
in (self
.header
, self
.body
, self
.docs
):
52 f
.append('/* Auto-generated, do not edit.\n *\n'
53 ' * This file may be distributed under the same terms\n'
54 ' * as the specification from which it was generated.\n'
57 # keys are e.g. 'sv', values are the key escaped
58 self
.need_mappings
= {}
59 # keys are the contents of the struct (e.g. 'sssu'), values are the
61 self
.need_structs
= {}
62 # keys are the contents of the struct (e.g. 'sssu'), values are the
64 self
.need_struct_arrays
= {}
66 # keys are the contents of the array (unlike need_struct_arrays!),
67 # values are the key escaped
68 self
.need_other_arrays
= {}
71 self
.header
.append(code
)
74 self
.body
.append(code
)
77 self
.docs
.append(code
)
79 def do_mapping_header(self
, mapping
):
80 members
= mapping
.getElementsByTagNameNS(NS_TP
, 'member')
81 assert len(members
) == 2
83 impl_sig
= ''.join([elt
.getAttribute('type')
86 esc_impl_sig
= escape_as_identifier(impl_sig
)
88 name
= (self
.PREFIX_
+ 'HASH_TYPE_' +
89 mapping
.getAttribute('name').upper())
90 impl
= self
.prefix_
+ 'type_dbus_hash_' + esc_impl_sig
92 docstring
= get_docstring(mapping
) or '(Undocumented)'
94 self
.d('/**\n * %s:\n *\n' % name
.strip())
95 self
.d(' * %s\n' % xml_escape(docstring
))
97 self
.d(' * This macro expands to a call to a function\n')
98 self
.d(' * that returns the #GType of a #GHashTable\n')
99 self
.d(' * appropriate for representing a D-Bus\n')
100 self
.d(' * dictionary of signature\n')
101 self
.d(' * <literal>a{%s}</literal>.\n' % impl_sig
)
106 self
.d(' * Keys (D-Bus type <literal>%s</literal>,\n'
107 % key
.getAttribute('type'))
108 tp_type
= key
.getAttributeNS(NS_TP
, 'type')
110 self
.d(' * type <literal>%s</literal>,\n' % tp_type
)
111 self
.d(' * named <literal>%s</literal>):\n'
112 % key
.getAttribute('name'))
113 docstring
= get_docstring(key
) or '(Undocumented)'
114 self
.d(' * %s\n' % xml_escape(docstring
))
117 self
.d(' * Values (D-Bus type <literal>%s</literal>,\n'
118 % value
.getAttribute('type'))
119 tp_type
= value
.getAttributeNS(NS_TP
, 'type')
121 self
.d(' * type <literal>%s</literal>,\n' % tp_type
)
122 self
.d(' * named <literal>%s</literal>):\n'
123 % value
.getAttribute('name'))
124 docstring
= get_docstring(value
) or '(Undocumented)'
125 self
.d(' * %s\n' % xml_escape(docstring
))
130 self
.h('#define %s (%s ())\n\n' % (name
, impl
))
131 self
.need_mappings
[impl_sig
] = esc_impl_sig
133 array_name
= mapping
.getAttribute('array-name')
135 gtype_name
= self
.PREFIX_
+ 'ARRAY_TYPE_' + array_name
.upper()
136 contents_sig
= 'a{' + impl_sig
+ '}'
137 esc_contents_sig
= escape_as_identifier(contents_sig
)
138 impl
= self
.prefix_
+ 'type_dbus_array_of_' + esc_contents_sig
139 self
.d('/**\n * %s:\n\n' % gtype_name
)
140 self
.d(' * Expands to a call to a function\n')
141 self
.d(' * that returns the #GType of a #GPtrArray\n')
142 self
.d(' * of #%s.\n' % name
)
145 self
.h('#define %s (%s ())\n\n' % (gtype_name
, impl
))
146 self
.need_other_arrays
[contents_sig
] = esc_contents_sig
148 def do_struct_header(self
, struct
):
149 members
= struct
.getElementsByTagNameNS(NS_TP
, 'member')
150 impl_sig
= ''.join([elt
.getAttribute('type') for elt
in members
])
151 esc_impl_sig
= escape_as_identifier(impl_sig
)
153 name
= (self
.PREFIX_
+ 'STRUCT_TYPE_' +
154 struct
.getAttribute('name').upper())
155 impl
= self
.prefix_
+ 'type_dbus_struct_' + esc_impl_sig
156 docstring
= struct
.getElementsByTagNameNS(NS_TP
, 'docstring')
158 docstring
= docstring
[0].toprettyxml()
159 if docstring
.startswith('<tp:docstring>'):
160 docstring
= docstring
[14:]
161 if docstring
.endswith('</tp:docstring>\n'):
162 docstring
= docstring
[:-16]
163 if docstring
.strip() in ('<tp:docstring/>', ''):
164 docstring
= '(Undocumented)'
166 docstring
= '(Undocumented)'
167 self
.d('/**\n * %s:\n\n' % name
)
168 self
.d(' * %s\n' % xml_escape(docstring
))
170 self
.d(' * This macro expands to a call to a function\n')
171 self
.d(' * that returns the #GType of a #GValueArray\n')
172 self
.d(' * appropriate for representing a D-Bus struct\n')
173 self
.d(' * with signature <literal>(%s)</literal>.\n'
177 for i
, member
in enumerate(members
):
178 self
.d(' * Member %d (D-Bus type '
179 '<literal>%s</literal>,\n'
180 % (i
, member
.getAttribute('type')))
181 tp_type
= member
.getAttributeNS(NS_TP
, 'type')
183 self
.d(' * type <literal>%s</literal>,\n' % tp_type
)
184 self
.d(' * named <literal>%s</literal>):\n'
185 % member
.getAttribute('name'))
186 docstring
= get_docstring(member
) or '(Undocumented)'
187 self
.d(' * %s\n' % xml_escape(docstring
))
192 self
.h('#define %s (%s ())\n\n' % (name
, impl
))
194 array_name
= struct
.getAttribute('array-name')
196 array_name
= (self
.PREFIX_
+ 'ARRAY_TYPE_' + array_name
.upper())
197 impl
= self
.prefix_
+ 'type_dbus_array_' + esc_impl_sig
198 self
.d('/**\n * %s:\n\n' % array_name
)
199 self
.d(' * Expands to a call to a function\n')
200 self
.d(' * that returns the #GType of a #GPtrArray\n')
201 self
.d(' * of #%s.\n' % name
)
204 self
.h('#define %s (%s ())\n\n' % (array_name
, impl
))
205 self
.need_struct_arrays
[impl_sig
] = esc_impl_sig
207 self
.need_structs
[impl_sig
] = esc_impl_sig
210 mappings
= self
.dom
.getElementsByTagNameNS(NS_TP
, 'mapping')
211 structs
= self
.dom
.getElementsByTagNameNS(NS_TP
, 'struct')
213 for mapping
in mappings
:
214 self
.do_mapping_header(mapping
)
216 for sig
in self
.need_mappings
:
217 self
.h('GType %stype_dbus_hash_%s (void);\n\n' %
218 (self
.prefix_
, self
.need_mappings
[sig
]))
219 self
.c('GType\n%stype_dbus_hash_%s (void)\n{\n' %
220 (self
.prefix_
, self
.need_mappings
[sig
]))
221 self
.c(' static GType t = 0;\n\n')
222 self
.c(' if (G_UNLIKELY (t == 0))\n')
223 # FIXME: translate sig into two GTypes
224 items
= tuple(Signature(sig
))
225 gtypes
= types_to_gtypes(items
)
226 self
.c(' t = dbus_g_type_get_map ("GHashTable", '
227 '%s, %s);\n' % (gtypes
[0], gtypes
[1]))
228 self
.c(' return t;\n')
231 for struct
in structs
:
232 self
.do_struct_header(struct
)
234 for sig
in self
.need_structs
:
235 self
.h('GType %stype_dbus_struct_%s (void);\n\n' %
236 (self
.prefix_
, self
.need_structs
[sig
]))
237 self
.c('GType\n%stype_dbus_struct_%s (void)\n{\n' %
238 (self
.prefix_
, self
.need_structs
[sig
]))
239 self
.c(' static GType t = 0;\n\n')
240 self
.c(' if (G_UNLIKELY (t == 0))\n')
241 self
.c(' t = dbus_g_type_get_struct ("GValueArray",\n')
242 items
= tuple(Signature(sig
))
243 gtypes
= types_to_gtypes(items
)
245 self
.c(' %s,\n' % gtype
)
246 self
.c(' G_TYPE_INVALID);\n')
247 self
.c(' return t;\n')
250 for sig
in self
.need_struct_arrays
:
251 self
.h('GType %stype_dbus_array_%s (void);\n\n' %
252 (self
.prefix_
, self
.need_struct_arrays
[sig
]))
253 self
.c('GType\n%stype_dbus_array_%s (void)\n{\n' %
254 (self
.prefix_
, self
.need_struct_arrays
[sig
]))
255 self
.c(' static GType t = 0;\n\n')
256 self
.c(' if (G_UNLIKELY (t == 0))\n')
257 self
.c(' t = dbus_g_type_get_collection ("GPtrArray", '
258 '%stype_dbus_struct_%s ());\n' %
259 (self
.prefix_
, self
.need_struct_arrays
[sig
]))
260 self
.c(' return t;\n')
263 for sig
in self
.need_other_arrays
:
264 self
.h('GType %stype_dbus_array_of_%s (void);\n\n' %
265 (self
.prefix_
, self
.need_other_arrays
[sig
]))
266 self
.c('GType\n%stype_dbus_array_of_%s (void)\n{\n' %
267 (self
.prefix_
, self
.need_other_arrays
[sig
]))
268 self
.c(' static GType t = 0;\n\n')
269 self
.c(' if (G_UNLIKELY (t == 0))\n')
271 if sig
[:2] == 'a{' and sig
[-1:] == '}':
273 self
.c(' t = dbus_g_type_get_collection ('
275 '%stype_dbus_hash_%s ());\n' %
276 (self
.prefix_
, escape_as_identifier(sig
[2:-1])))
277 elif sig
[:2] == 'a(' and sig
[-1:] == ')':
278 # array of arrays of struct
279 self
.c(' t = dbus_g_type_get_collection ('
281 '%stype_dbus_array_%s ());\n' %
282 (self
.prefix_
, escape_as_identifier(sig
[2:-1])))
284 # array of arrays of non-struct
285 self
.c(' t = dbus_g_type_get_collection ('
287 '%stype_dbus_array_of_%s ());\n' %
288 (self
.prefix_
, escape_as_identifier(sig
[1:])))
290 raise AssertionError("array of '%s' not supported" % sig
)
292 self
.c(' return t;\n')
295 file_set_contents(self
.output
+ '.h', u('').join(self
.header
).encode('utf-8'))
296 file_set_contents(self
.output
+ '-body.h', u('').join(self
.body
).encode('utf-8'))
297 file_set_contents(self
.output
+ '-gtk-doc.h', u('').join(self
.docs
).encode('utf-8'))
299 if __name__
== '__main__':
302 dom
= xml
.dom
.minidom
.parse(argv
[0])
304 GTypesGenerator(dom
, argv
[1], argv
[2])()