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')
47 self
.docs
= open(output
+ '-gtk-doc.h', 'w')
49 for f
in (self
.header
, self
.body
, self
.docs
):
50 f
.write('/* Auto-generated, do not edit.\n *\n'
51 ' * This file may be distributed under the same terms\n'
52 ' * as the specification from which it was generated.\n'
55 # keys are e.g. 'sv', values are the key escaped
56 self
.need_mappings
= {}
57 # keys are the contents of the struct (e.g. 'sssu'), values are the
59 self
.need_structs
= {}
60 # keys are the contents of the struct (e.g. 'sssu'), values are the
62 self
.need_struct_arrays
= {}
64 # keys are the contents of the array (unlike need_struct_arrays!),
65 # values are the key escaped
66 self
.need_other_arrays
= {}
69 self
.header
.write(code
.encode("utf-8"))
72 self
.body
.write(code
.encode("utf-8"))
75 self
.docs
.write(code
.encode('utf-8'))
77 def do_mapping_header(self
, mapping
):
78 members
= mapping
.getElementsByTagNameNS(NS_TP
, 'member')
79 assert len(members
) == 2
81 impl_sig
= ''.join([elt
.getAttribute('type')
84 esc_impl_sig
= escape_as_identifier(impl_sig
)
86 name
= (self
.PREFIX_
+ 'HASH_TYPE_' +
87 mapping
.getAttribute('name').upper())
88 impl
= self
.prefix_
+ 'type_dbus_hash_' + esc_impl_sig
90 docstring
= get_docstring(mapping
) or '(Undocumented)'
92 self
.d('/**\n * %s:\n *\n' % name
)
93 self
.d(' * %s\n' % xml_escape(docstring
))
95 self
.d(' * This macro expands to a call to a function\n')
96 self
.d(' * that returns the #GType of a #GHashTable\n')
97 self
.d(' * appropriate for representing a D-Bus\n')
98 self
.d(' * dictionary of signature\n')
99 self
.d(' * <literal>a{%s}</literal>.\n' % impl_sig
)
104 self
.d(' * Keys (D-Bus type <literal>%s</literal>,\n'
105 % key
.getAttribute('type'))
106 tp_type
= key
.getAttributeNS(NS_TP
, 'type')
108 self
.d(' * type <literal>%s</literal>,\n' % tp_type
)
109 self
.d(' * named <literal>%s</literal>):\n'
110 % key
.getAttribute('name'))
111 docstring
= get_docstring(key
) or '(Undocumented)'
112 self
.d(' * %s\n' % xml_escape(docstring
))
115 self
.d(' * Values (D-Bus type <literal>%s</literal>,\n'
116 % value
.getAttribute('type'))
117 tp_type
= value
.getAttributeNS(NS_TP
, 'type')
119 self
.d(' * type <literal>%s</literal>,\n' % tp_type
)
120 self
.d(' * named <literal>%s</literal>):\n'
121 % value
.getAttribute('name'))
122 docstring
= get_docstring(value
) or '(Undocumented)'
123 self
.d(' * %s\n' % xml_escape(docstring
))
128 self
.h('#define %s (%s ())\n\n' % (name
, impl
))
129 self
.need_mappings
[impl_sig
] = esc_impl_sig
131 array_name
= mapping
.getAttribute('array-name')
133 gtype_name
= self
.PREFIX_
+ 'ARRAY_TYPE_' + array_name
.upper()
134 contents_sig
= 'a{' + impl_sig
+ '}'
135 esc_contents_sig
= escape_as_identifier(contents_sig
)
136 impl
= self
.prefix_
+ 'type_dbus_array_of_' + esc_contents_sig
137 self
.d('/**\n * %s:\n\n' % gtype_name
)
138 self
.d(' * Expands to a call to a function\n')
139 self
.d(' * that returns the #GType of a #GPtrArray\n')
140 self
.d(' * of #%s.\n' % name
)
143 self
.h('#define %s (%s ())\n\n' % (gtype_name
, impl
))
144 self
.need_other_arrays
[contents_sig
] = esc_contents_sig
146 def do_struct_header(self
, struct
):
147 members
= struct
.getElementsByTagNameNS(NS_TP
, 'member')
148 impl_sig
= ''.join([elt
.getAttribute('type') for elt
in members
])
149 esc_impl_sig
= escape_as_identifier(impl_sig
)
151 name
= (self
.PREFIX_
+ 'STRUCT_TYPE_' +
152 struct
.getAttribute('name').upper())
153 impl
= self
.prefix_
+ 'type_dbus_struct_' + esc_impl_sig
154 docstring
= struct
.getElementsByTagNameNS(NS_TP
, 'docstring')
156 docstring
= docstring
[0].toprettyxml()
157 if docstring
.startswith('<tp:docstring>'):
158 docstring
= docstring
[14:]
159 if docstring
.endswith('</tp:docstring>\n'):
160 docstring
= docstring
[:-16]
161 if docstring
.strip() in ('<tp:docstring/>', ''):
162 docstring
= '(Undocumented)'
164 docstring
= '(Undocumented)'
165 self
.d('/**\n * %s:\n\n' % name
)
166 self
.d(' * %s\n' % xml_escape(docstring
))
168 self
.d(' * This macro expands to a call to a function\n')
169 self
.d(' * that returns the #GType of a #GValueArray\n')
170 self
.d(' * appropriate for representing a D-Bus struct\n')
171 self
.d(' * with signature <literal>(%s)</literal>.\n'
175 for i
, member
in enumerate(members
):
176 self
.d(' * Member %d (D-Bus type '
177 '<literal>%s</literal>,\n'
178 % (i
, member
.getAttribute('type')))
179 tp_type
= member
.getAttributeNS(NS_TP
, 'type')
181 self
.d(' * type <literal>%s</literal>,\n' % tp_type
)
182 self
.d(' * named <literal>%s</literal>):\n'
183 % member
.getAttribute('name'))
184 docstring
= get_docstring(member
) or '(Undocumented)'
185 self
.d(' * %s\n' % xml_escape(docstring
))
190 self
.h('#define %s (%s ())\n\n' % (name
, impl
))
192 array_name
= struct
.getAttribute('array-name')
194 array_name
= (self
.PREFIX_
+ 'ARRAY_TYPE_' + array_name
.upper())
195 impl
= self
.prefix_
+ 'type_dbus_array_' + esc_impl_sig
196 self
.d('/**\n * %s:\n\n' % array_name
)
197 self
.d(' * Expands to a call to a function\n')
198 self
.d(' * that returns the #GType of a #GPtrArray\n')
199 self
.d(' * of #%s.\n' % name
)
202 self
.h('#define %s (%s ())\n\n' % (array_name
, impl
))
203 self
.need_struct_arrays
[impl_sig
] = esc_impl_sig
205 self
.need_structs
[impl_sig
] = esc_impl_sig
208 mappings
= self
.dom
.getElementsByTagNameNS(NS_TP
, 'mapping')
209 structs
= self
.dom
.getElementsByTagNameNS(NS_TP
, 'struct')
211 for mapping
in mappings
:
212 self
.do_mapping_header(mapping
)
214 for sig
in self
.need_mappings
:
215 self
.h('GType %stype_dbus_hash_%s (void);\n\n' %
216 (self
.prefix_
, self
.need_mappings
[sig
]))
217 self
.c('GType\n%stype_dbus_hash_%s (void)\n{\n' %
218 (self
.prefix_
, self
.need_mappings
[sig
]))
219 self
.c(' static GType t = 0;\n\n')
220 self
.c(' if (G_UNLIKELY (t == 0))\n')
221 # FIXME: translate sig into two GTypes
222 items
= tuple(Signature(sig
))
223 gtypes
= types_to_gtypes(items
)
224 self
.c(' t = dbus_g_type_get_map ("GHashTable", '
225 '%s, %s);\n' % (gtypes
[0], gtypes
[1]))
226 self
.c(' return t;\n')
229 for struct
in structs
:
230 self
.do_struct_header(struct
)
232 for sig
in self
.need_structs
:
233 self
.h('GType %stype_dbus_struct_%s (void);\n\n' %
234 (self
.prefix_
, self
.need_structs
[sig
]))
235 self
.c('GType\n%stype_dbus_struct_%s (void)\n{\n' %
236 (self
.prefix_
, self
.need_structs
[sig
]))
237 self
.c(' static GType t = 0;\n\n')
238 self
.c(' if (G_UNLIKELY (t == 0))\n')
239 self
.c(' t = dbus_g_type_get_struct ("GValueArray",\n')
240 items
= tuple(Signature(sig
))
241 gtypes
= types_to_gtypes(items
)
243 self
.c(' %s,\n' % gtype
)
244 self
.c(' G_TYPE_INVALID);\n')
245 self
.c(' return t;\n')
248 for sig
in self
.need_struct_arrays
:
249 self
.h('GType %stype_dbus_array_%s (void);\n\n' %
250 (self
.prefix_
, self
.need_struct_arrays
[sig
]))
251 self
.c('GType\n%stype_dbus_array_%s (void)\n{\n' %
252 (self
.prefix_
, self
.need_struct_arrays
[sig
]))
253 self
.c(' static GType t = 0;\n\n')
254 self
.c(' if (G_UNLIKELY (t == 0))\n')
255 self
.c(' t = dbus_g_type_get_collection ("GPtrArray", '
256 '%stype_dbus_struct_%s ());\n' %
257 (self
.prefix_
, self
.need_struct_arrays
[sig
]))
258 self
.c(' return t;\n')
261 for sig
in self
.need_other_arrays
:
262 self
.h('GType %stype_dbus_array_of_%s (void);\n\n' %
263 (self
.prefix_
, self
.need_other_arrays
[sig
]))
264 self
.c('GType\n%stype_dbus_array_of_%s (void)\n{\n' %
265 (self
.prefix_
, self
.need_other_arrays
[sig
]))
266 self
.c(' static GType t = 0;\n\n')
267 self
.c(' if (G_UNLIKELY (t == 0))\n')
269 if sig
[:2] == 'a{' and sig
[-1:] == '}':
271 self
.c(' t = dbus_g_type_get_collection ('
273 '%stype_dbus_hash_%s ());\n' %
274 (self
.prefix_
, escape_as_identifier(sig
[2:-1])))
275 elif sig
[:2] == 'a(' and sig
[-1:] == ')':
276 # array of arrays of struct
277 self
.c(' t = dbus_g_type_get_collection ('
279 '%stype_dbus_array_%s ());\n' %
280 (self
.prefix_
, escape_as_identifier(sig
[2:-1])))
282 # array of arrays of non-struct
283 self
.c(' t = dbus_g_type_get_collection ('
285 '%stype_dbus_array_of_%s ());\n' %
286 (self
.prefix_
, escape_as_identifier(sig
[1:])))
288 raise AssertionError("array of '%s' not supported" % sig
)
290 self
.c(' return t;\n')
293 if __name__
== '__main__':
296 dom
= xml
.dom
.minidom
.parse(argv
[0])
298 GTypesGenerator(dom
, argv
[1], argv
[2])()