File indexing completed on 2024-03-24 05:04:52
0001 #!/usr/bin/python 0002 0003 # Generate GLib GInterfaces from the Telepathy specification. 0004 # The master copy of this program is in the telepathy-glib repository - 0005 # please make any changes there. 0006 # 0007 # Copyright (C) 2006, 2007 Collabora Limited 0008 # 0009 # This library is free software; you can redistribute it and/or 0010 # modify it under the terms of the GNU Lesser General Public 0011 # License as published by the Free Software Foundation; either 0012 # version 2.1 of the License, or (at your option) any later version. 0013 # 0014 # This library is distributed in the hope that it will be useful, 0015 # but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0017 # Lesser General Public License for more details. 0018 # 0019 # You should have received a copy of the GNU Lesser General Public 0020 # License along with this library; if not, write to the Free Software 0021 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0022 0023 import sys 0024 import xml.dom.minidom 0025 0026 from libtpcodegen import file_set_contents, u 0027 from libglibcodegen import escape_as_identifier, \ 0028 get_docstring, \ 0029 NS_TP, \ 0030 Signature, \ 0031 type_to_gtype, \ 0032 xml_escape 0033 0034 0035 def types_to_gtypes(types): 0036 return [type_to_gtype(t)[1] for t in types] 0037 0038 0039 class GTypesGenerator(object): 0040 def __init__(self, dom, output, mixed_case_prefix): 0041 self.dom = dom 0042 self.Prefix = mixed_case_prefix 0043 self.PREFIX_ = self.Prefix.upper() + '_' 0044 self.prefix_ = self.Prefix.lower() + '_' 0045 0046 self.header = [] 0047 self.body = [] 0048 self.docs = [] 0049 self.output = output 0050 0051 for f in (self.header, self.body, self.docs): 0052 f.append('/* Auto-generated, do not edit.\n *\n' 0053 ' * This file may be distributed under the same terms\n' 0054 ' * as the specification from which it was generated.\n' 0055 ' */\n\n') 0056 0057 # keys are e.g. 'sv', values are the key escaped 0058 self.need_mappings = {} 0059 # keys are the contents of the struct (e.g. 'sssu'), values are the 0060 # key escaped 0061 self.need_structs = {} 0062 # keys are the contents of the struct (e.g. 'sssu'), values are the 0063 # key escaped 0064 self.need_struct_arrays = {} 0065 0066 # keys are the contents of the array (unlike need_struct_arrays!), 0067 # values are the key escaped 0068 self.need_other_arrays = {} 0069 0070 def h(self, code): 0071 self.header.append(code) 0072 0073 def c(self, code): 0074 self.body.append(code) 0075 0076 def d(self, code): 0077 self.docs.append(code) 0078 0079 def do_mapping_header(self, mapping): 0080 members = mapping.getElementsByTagNameNS(NS_TP, 'member') 0081 assert len(members) == 2 0082 0083 impl_sig = ''.join([elt.getAttribute('type') 0084 for elt in members]) 0085 0086 esc_impl_sig = escape_as_identifier(impl_sig) 0087 0088 name = (self.PREFIX_ + 'HASH_TYPE_' + 0089 mapping.getAttribute('name').upper()) 0090 impl = self.prefix_ + 'type_dbus_hash_' + esc_impl_sig 0091 0092 docstring = get_docstring(mapping) or '(Undocumented)' 0093 0094 self.d('/**\n * %s:\n *\n' % name.strip()) 0095 self.d(' * %s\n' % xml_escape(docstring)) 0096 self.d(' *\n') 0097 self.d(' * This macro expands to a call to a function\n') 0098 self.d(' * that returns the #GType of a #GHashTable\n') 0099 self.d(' * appropriate for representing a D-Bus\n') 0100 self.d(' * dictionary of signature\n') 0101 self.d(' * <literal>a{%s}</literal>.\n' % impl_sig) 0102 self.d(' *\n') 0103 0104 key, value = members 0105 0106 self.d(' * Keys (D-Bus type <literal>%s</literal>,\n' 0107 % key.getAttribute('type')) 0108 tp_type = key.getAttributeNS(NS_TP, 'type') 0109 if tp_type: 0110 self.d(' * type <literal>%s</literal>,\n' % tp_type) 0111 self.d(' * named <literal>%s</literal>):\n' 0112 % key.getAttribute('name')) 0113 docstring = get_docstring(key) or '(Undocumented)' 0114 self.d(' * %s\n' % xml_escape(docstring)) 0115 self.d(' *\n') 0116 0117 self.d(' * Values (D-Bus type <literal>%s</literal>,\n' 0118 % value.getAttribute('type')) 0119 tp_type = value.getAttributeNS(NS_TP, 'type') 0120 if tp_type: 0121 self.d(' * type <literal>%s</literal>,\n' % tp_type) 0122 self.d(' * named <literal>%s</literal>):\n' 0123 % value.getAttribute('name')) 0124 docstring = get_docstring(value) or '(Undocumented)' 0125 self.d(' * %s\n' % xml_escape(docstring)) 0126 self.d(' *\n') 0127 0128 self.d(' */\n') 0129 0130 self.h('#define %s (%s ())\n\n' % (name, impl)) 0131 self.need_mappings[impl_sig] = esc_impl_sig 0132 0133 array_name = mapping.getAttribute('array-name') 0134 if array_name: 0135 gtype_name = self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper() 0136 contents_sig = 'a{' + impl_sig + '}' 0137 esc_contents_sig = escape_as_identifier(contents_sig) 0138 impl = self.prefix_ + 'type_dbus_array_of_' + esc_contents_sig 0139 self.d('/**\n * %s:\n\n' % gtype_name) 0140 self.d(' * Expands to a call to a function\n') 0141 self.d(' * that returns the #GType of a #GPtrArray\n') 0142 self.d(' * of #%s.\n' % name) 0143 self.d(' */\n\n') 0144 0145 self.h('#define %s (%s ())\n\n' % (gtype_name, impl)) 0146 self.need_other_arrays[contents_sig] = esc_contents_sig 0147 0148 def do_struct_header(self, struct): 0149 members = struct.getElementsByTagNameNS(NS_TP, 'member') 0150 impl_sig = ''.join([elt.getAttribute('type') for elt in members]) 0151 esc_impl_sig = escape_as_identifier(impl_sig) 0152 0153 name = (self.PREFIX_ + 'STRUCT_TYPE_' + 0154 struct.getAttribute('name').upper()) 0155 impl = self.prefix_ + 'type_dbus_struct_' + esc_impl_sig 0156 docstring = struct.getElementsByTagNameNS(NS_TP, 'docstring') 0157 if docstring: 0158 docstring = docstring[0].toprettyxml() 0159 if docstring.startswith('<tp:docstring>'): 0160 docstring = docstring[14:] 0161 if docstring.endswith('</tp:docstring>\n'): 0162 docstring = docstring[:-16] 0163 if docstring.strip() in ('<tp:docstring/>', ''): 0164 docstring = '(Undocumented)' 0165 else: 0166 docstring = '(Undocumented)' 0167 self.d('/**\n * %s:\n\n' % name) 0168 self.d(' * %s\n' % xml_escape(docstring)) 0169 self.d(' *\n') 0170 self.d(' * This macro expands to a call to a function\n') 0171 self.d(' * that returns the #GType of a #GValueArray\n') 0172 self.d(' * appropriate for representing a D-Bus struct\n') 0173 self.d(' * with signature <literal>(%s)</literal>.\n' 0174 % impl_sig) 0175 self.d(' *\n') 0176 0177 for i, member in enumerate(members): 0178 self.d(' * Member %d (D-Bus type ' 0179 '<literal>%s</literal>,\n' 0180 % (i, member.getAttribute('type'))) 0181 tp_type = member.getAttributeNS(NS_TP, 'type') 0182 if tp_type: 0183 self.d(' * type <literal>%s</literal>,\n' % tp_type) 0184 self.d(' * named <literal>%s</literal>):\n' 0185 % member.getAttribute('name')) 0186 docstring = get_docstring(member) or '(Undocumented)' 0187 self.d(' * %s\n' % xml_escape(docstring)) 0188 self.d(' *\n') 0189 0190 self.d(' */\n\n') 0191 0192 self.h('#define %s (%s ())\n\n' % (name, impl)) 0193 0194 array_name = struct.getAttribute('array-name') 0195 if array_name != '': 0196 array_name = (self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper()) 0197 impl = self.prefix_ + 'type_dbus_array_' + esc_impl_sig 0198 self.d('/**\n * %s:\n\n' % array_name) 0199 self.d(' * Expands to a call to a function\n') 0200 self.d(' * that returns the #GType of a #GPtrArray\n') 0201 self.d(' * of #%s.\n' % name) 0202 self.d(' */\n\n') 0203 0204 self.h('#define %s (%s ())\n\n' % (array_name, impl)) 0205 self.need_struct_arrays[impl_sig] = esc_impl_sig 0206 0207 self.need_structs[impl_sig] = esc_impl_sig 0208 0209 def __call__(self): 0210 mappings = self.dom.getElementsByTagNameNS(NS_TP, 'mapping') 0211 structs = self.dom.getElementsByTagNameNS(NS_TP, 'struct') 0212 0213 for mapping in mappings: 0214 self.do_mapping_header(mapping) 0215 0216 for sig in self.need_mappings: 0217 self.h('GType %stype_dbus_hash_%s (void);\n\n' % 0218 (self.prefix_, self.need_mappings[sig])) 0219 self.c('GType\n%stype_dbus_hash_%s (void)\n{\n' % 0220 (self.prefix_, self.need_mappings[sig])) 0221 self.c(' static GType t = 0;\n\n') 0222 self.c(' if (G_UNLIKELY (t == 0))\n') 0223 # FIXME: translate sig into two GTypes 0224 items = tuple(Signature(sig)) 0225 gtypes = types_to_gtypes(items) 0226 self.c(' t = dbus_g_type_get_map ("GHashTable", ' 0227 '%s, %s);\n' % (gtypes[0], gtypes[1])) 0228 self.c(' return t;\n') 0229 self.c('}\n\n') 0230 0231 for struct in structs: 0232 self.do_struct_header(struct) 0233 0234 for sig in self.need_structs: 0235 self.h('GType %stype_dbus_struct_%s (void);\n\n' % 0236 (self.prefix_, self.need_structs[sig])) 0237 self.c('GType\n%stype_dbus_struct_%s (void)\n{\n' % 0238 (self.prefix_, self.need_structs[sig])) 0239 self.c(' static GType t = 0;\n\n') 0240 self.c(' if (G_UNLIKELY (t == 0))\n') 0241 self.c(' t = dbus_g_type_get_struct ("GValueArray",\n') 0242 items = tuple(Signature(sig)) 0243 gtypes = types_to_gtypes(items) 0244 for gtype in gtypes: 0245 self.c(' %s,\n' % gtype) 0246 self.c(' G_TYPE_INVALID);\n') 0247 self.c(' return t;\n') 0248 self.c('}\n\n') 0249 0250 for sig in self.need_struct_arrays: 0251 self.h('GType %stype_dbus_array_%s (void);\n\n' % 0252 (self.prefix_, self.need_struct_arrays[sig])) 0253 self.c('GType\n%stype_dbus_array_%s (void)\n{\n' % 0254 (self.prefix_, self.need_struct_arrays[sig])) 0255 self.c(' static GType t = 0;\n\n') 0256 self.c(' if (G_UNLIKELY (t == 0))\n') 0257 self.c(' t = dbus_g_type_get_collection ("GPtrArray", ' 0258 '%stype_dbus_struct_%s ());\n' % 0259 (self.prefix_, self.need_struct_arrays[sig])) 0260 self.c(' return t;\n') 0261 self.c('}\n\n') 0262 0263 for sig in self.need_other_arrays: 0264 self.h('GType %stype_dbus_array_of_%s (void);\n\n' % 0265 (self.prefix_, self.need_other_arrays[sig])) 0266 self.c('GType\n%stype_dbus_array_of_%s (void)\n{\n' % 0267 (self.prefix_, self.need_other_arrays[sig])) 0268 self.c(' static GType t = 0;\n\n') 0269 self.c(' if (G_UNLIKELY (t == 0))\n') 0270 0271 if sig[:2] == 'a{' and sig[-1:] == '}': 0272 # array of mappings 0273 self.c(' t = dbus_g_type_get_collection (' 0274 '"GPtrArray", ' 0275 '%stype_dbus_hash_%s ());\n' % 0276 (self.prefix_, escape_as_identifier(sig[2:-1]))) 0277 elif sig[:2] == 'a(' and sig[-1:] == ')': 0278 # array of arrays of struct 0279 self.c(' t = dbus_g_type_get_collection (' 0280 '"GPtrArray", ' 0281 '%stype_dbus_array_%s ());\n' % 0282 (self.prefix_, escape_as_identifier(sig[2:-1]))) 0283 elif sig[:1] == 'a': 0284 # array of arrays of non-struct 0285 self.c(' t = dbus_g_type_get_collection (' 0286 '"GPtrArray", ' 0287 '%stype_dbus_array_of_%s ());\n' % 0288 (self.prefix_, escape_as_identifier(sig[1:]))) 0289 else: 0290 raise AssertionError("array of '%s' not supported" % sig) 0291 0292 self.c(' return t;\n') 0293 self.c('}\n\n') 0294 0295 file_set_contents(self.output + '.h', u('').join(self.header).encode('utf-8')) 0296 file_set_contents(self.output + '-body.h', u('').join(self.body).encode('utf-8')) 0297 file_set_contents(self.output + '-gtk-doc.h', u('').join(self.docs).encode('utf-8')) 0298 0299 if __name__ == '__main__': 0300 argv = sys.argv[1:] 0301 0302 dom = xml.dom.minidom.parse(argv[0]) 0303 0304 GTypesGenerator(dom, argv[1], argv[2])()