File indexing completed on 2024-04-28 16:13:13
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 libglibcodegen import escape_as_identifier, \ 0027 get_docstring, \ 0028 NS_TP, \ 0029 Signature, \ 0030 type_to_gtype, \ 0031 xml_escape 0032 0033 0034 def types_to_gtypes(types): 0035 return [type_to_gtype(t)[1] for t in types] 0036 0037 0038 class GTypesGenerator(object): 0039 def __init__(self, dom, output, mixed_case_prefix): 0040 self.dom = dom 0041 self.Prefix = mixed_case_prefix 0042 self.PREFIX_ = self.Prefix.upper() + '_' 0043 self.prefix_ = self.Prefix.lower() + '_' 0044 0045 self.header = open(output + '.h', 'w') 0046 self.body = open(output + '-body.h', 'w') 0047 0048 for f in (self.header, self.body): 0049 f.write('/* Auto-generated, do not edit.\n *\n' 0050 ' * This file may be distributed under the same terms\n' 0051 ' * as the specification from which it was generated.\n' 0052 ' */\n\n') 0053 0054 # keys are e.g. 'sv', values are the key escaped 0055 self.need_mappings = {} 0056 # keys are the contents of the struct (e.g. 'sssu'), values are the 0057 # key escaped 0058 self.need_structs = {} 0059 # keys are the contents of the struct (e.g. 'sssu'), values are the 0060 # key escaped 0061 self.need_struct_arrays = {} 0062 0063 # keys are the contents of the array (unlike need_struct_arrays!), 0064 # values are the key escaped 0065 self.need_other_arrays = {} 0066 0067 def h(self, code): 0068 self.header.write(code.encode("utf-8")) 0069 0070 def c(self, code): 0071 self.body.write(code.encode("utf-8")) 0072 0073 def do_mapping_header(self, mapping): 0074 members = mapping.getElementsByTagNameNS(NS_TP, 'member') 0075 assert len(members) == 2 0076 0077 impl_sig = ''.join([elt.getAttribute('type') 0078 for elt in members]) 0079 0080 esc_impl_sig = escape_as_identifier(impl_sig) 0081 0082 name = (self.PREFIX_ + 'HASH_TYPE_' + 0083 mapping.getAttribute('name').upper()) 0084 impl = self.prefix_ + 'type_dbus_hash_' + esc_impl_sig 0085 0086 docstring = get_docstring(mapping) or '(Undocumented)' 0087 0088 self.h('/**\n * %s:\n *\n' % name) 0089 self.h(' * %s\n' % xml_escape(docstring)) 0090 self.h(' *\n') 0091 self.h(' * This macro expands to a call to a function\n') 0092 self.h(' * that returns the #GType of a #GHashTable\n') 0093 self.h(' * appropriate for representing a D-Bus\n') 0094 self.h(' * dictionary of signature\n') 0095 self.h(' * <literal>a{%s}</literal>.\n' % impl_sig) 0096 self.h(' *\n') 0097 0098 key, value = members 0099 0100 self.h(' * Keys (D-Bus type <literal>%s</literal>,\n' 0101 % key.getAttribute('type')) 0102 tp_type = key.getAttributeNS(NS_TP, 'type') 0103 if tp_type: 0104 self.h(' * type <literal>%s</literal>,\n' % tp_type) 0105 self.h(' * named <literal>%s</literal>):\n' 0106 % key.getAttribute('name')) 0107 docstring = get_docstring(key) or '(Undocumented)' 0108 self.h(' * %s\n' % xml_escape(docstring)) 0109 self.h(' *\n') 0110 0111 self.h(' * Values (D-Bus type <literal>%s</literal>,\n' 0112 % value.getAttribute('type')) 0113 tp_type = value.getAttributeNS(NS_TP, 'type') 0114 if tp_type: 0115 self.h(' * type <literal>%s</literal>,\n' % tp_type) 0116 self.h(' * named <literal>%s</literal>):\n' 0117 % value.getAttribute('name')) 0118 docstring = get_docstring(value) or '(Undocumented)' 0119 self.h(' * %s\n' % xml_escape(docstring)) 0120 self.h(' *\n') 0121 0122 self.h(' */\n') 0123 0124 self.h('#define %s (%s ())\n\n' % (name, impl)) 0125 self.need_mappings[impl_sig] = esc_impl_sig 0126 0127 array_name = mapping.getAttribute('array-name') 0128 if array_name: 0129 gtype_name = self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper() 0130 contents_sig = 'a{' + impl_sig + '}' 0131 esc_contents_sig = escape_as_identifier(contents_sig) 0132 impl = self.prefix_ + 'type_dbus_array_of_' + esc_contents_sig 0133 self.h('/**\n * %s:\n\n' % gtype_name) 0134 self.h(' * Expands to a call to a function\n') 0135 self.h(' * that returns the #GType of a #GPtrArray\n') 0136 self.h(' * of #%s.\n' % name) 0137 self.h(' */\n') 0138 self.h('#define %s (%s ())\n\n' % (gtype_name, impl)) 0139 self.need_other_arrays[contents_sig] = esc_contents_sig 0140 0141 def do_struct_header(self, struct): 0142 members = struct.getElementsByTagNameNS(NS_TP, 'member') 0143 impl_sig = ''.join([elt.getAttribute('type') for elt in members]) 0144 esc_impl_sig = escape_as_identifier(impl_sig) 0145 0146 name = (self.PREFIX_ + 'STRUCT_TYPE_' + 0147 struct.getAttribute('name').upper()) 0148 impl = self.prefix_ + 'type_dbus_struct_' + esc_impl_sig 0149 docstring = struct.getElementsByTagNameNS(NS_TP, 'docstring') 0150 if docstring: 0151 docstring = docstring[0].toprettyxml() 0152 if docstring.startswith('<tp:docstring>'): 0153 docstring = docstring[14:] 0154 if docstring.endswith('</tp:docstring>\n'): 0155 docstring = docstring[:-16] 0156 if docstring.strip() in ('<tp:docstring/>', ''): 0157 docstring = '(Undocumented)' 0158 else: 0159 docstring = '(Undocumented)' 0160 self.h('/**\n * %s:\n\n' % name) 0161 self.h(' * %s\n' % xml_escape(docstring)) 0162 self.h(' *\n') 0163 self.h(' * This macro expands to a call to a function\n') 0164 self.h(' * that returns the #GType of a #GValueArray\n') 0165 self.h(' * appropriate for representing a D-Bus struct\n') 0166 self.h(' * with signature <literal>(%s)</literal>.\n' 0167 % impl_sig) 0168 self.h(' *\n') 0169 0170 for i, member in enumerate(members): 0171 self.h(' * Member %d (D-Bus type ' 0172 '<literal>%s</literal>,\n' 0173 % (i, member.getAttribute('type'))) 0174 tp_type = member.getAttributeNS(NS_TP, 'type') 0175 if tp_type: 0176 self.h(' * type <literal>%s</literal>,\n' % tp_type) 0177 self.h(' * named <literal>%s</literal>):\n' 0178 % member.getAttribute('name')) 0179 docstring = get_docstring(member) or '(Undocumented)' 0180 self.h(' * %s\n' % xml_escape(docstring)) 0181 self.h(' *\n') 0182 0183 self.h(' */\n') 0184 self.h('#define %s (%s ())\n\n' % (name, impl)) 0185 0186 array_name = struct.getAttribute('array-name') 0187 if array_name != '': 0188 array_name = (self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper()) 0189 impl = self.prefix_ + 'type_dbus_array_' + esc_impl_sig 0190 self.h('/**\n * %s:\n\n' % array_name) 0191 self.h(' * Expands to a call to a function\n') 0192 self.h(' * that returns the #GType of a #GPtrArray\n') 0193 self.h(' * of #%s.\n' % name) 0194 self.h(' */\n') 0195 self.h('#define %s (%s ())\n\n' % (array_name, impl)) 0196 self.need_struct_arrays[impl_sig] = esc_impl_sig 0197 0198 self.need_structs[impl_sig] = esc_impl_sig 0199 0200 def __call__(self): 0201 mappings = self.dom.getElementsByTagNameNS(NS_TP, 'mapping') 0202 structs = self.dom.getElementsByTagNameNS(NS_TP, 'struct') 0203 0204 for mapping in mappings: 0205 self.do_mapping_header(mapping) 0206 0207 for sig in self.need_mappings: 0208 self.h('GType %stype_dbus_hash_%s (void);\n\n' % 0209 (self.prefix_, self.need_mappings[sig])) 0210 self.c('GType\n%stype_dbus_hash_%s (void)\n{\n' % 0211 (self.prefix_, self.need_mappings[sig])) 0212 self.c(' static GType t = 0;\n\n') 0213 self.c(' if (G_UNLIKELY (t == 0))\n') 0214 # FIXME: translate sig into two GTypes 0215 items = tuple(Signature(sig)) 0216 gtypes = types_to_gtypes(items) 0217 self.c(' t = dbus_g_type_get_map ("GHashTable", ' 0218 '%s, %s);\n' % (gtypes[0], gtypes[1])) 0219 self.c(' return t;\n') 0220 self.c('}\n\n') 0221 0222 for struct in structs: 0223 self.do_struct_header(struct) 0224 0225 for sig in self.need_structs: 0226 self.h('GType %stype_dbus_struct_%s (void);\n\n' % 0227 (self.prefix_, self.need_structs[sig])) 0228 self.c('GType\n%stype_dbus_struct_%s (void)\n{\n' % 0229 (self.prefix_, self.need_structs[sig])) 0230 self.c(' static GType t = 0;\n\n') 0231 self.c(' if (G_UNLIKELY (t == 0))\n') 0232 self.c(' t = dbus_g_type_get_struct ("GValueArray",\n') 0233 items = tuple(Signature(sig)) 0234 gtypes = types_to_gtypes(items) 0235 for gtype in gtypes: 0236 self.c(' %s,\n' % gtype) 0237 self.c(' G_TYPE_INVALID);\n') 0238 self.c(' return t;\n') 0239 self.c('}\n\n') 0240 0241 for sig in self.need_struct_arrays: 0242 self.h('GType %stype_dbus_array_%s (void);\n\n' % 0243 (self.prefix_, self.need_struct_arrays[sig])) 0244 self.c('GType\n%stype_dbus_array_%s (void)\n{\n' % 0245 (self.prefix_, self.need_struct_arrays[sig])) 0246 self.c(' static GType t = 0;\n\n') 0247 self.c(' if (G_UNLIKELY (t == 0))\n') 0248 self.c(' t = dbus_g_type_get_collection ("GPtrArray", ' 0249 '%stype_dbus_struct_%s ());\n' % 0250 (self.prefix_, self.need_struct_arrays[sig])) 0251 self.c(' return t;\n') 0252 self.c('}\n\n') 0253 0254 for sig in self.need_other_arrays: 0255 self.h('GType %stype_dbus_array_of_%s (void);\n\n' % 0256 (self.prefix_, self.need_other_arrays[sig])) 0257 self.c('GType\n%stype_dbus_array_of_%s (void)\n{\n' % 0258 (self.prefix_, self.need_other_arrays[sig])) 0259 self.c(' static GType t = 0;\n\n') 0260 self.c(' if (G_UNLIKELY (t == 0))\n') 0261 0262 if sig[:2] == 'a{' and sig[-1:] == '}': 0263 # array of mappings 0264 self.c(' t = dbus_g_type_get_collection (' 0265 '"GPtrArray", ' 0266 '%stype_dbus_hash_%s ());\n' % 0267 (self.prefix_, escape_as_identifier(sig[2:-1]))) 0268 elif sig[:2] == 'a(' and sig[-1:] == ')': 0269 # array of arrays of struct 0270 self.c(' t = dbus_g_type_get_collection (' 0271 '"GPtrArray", ' 0272 '%stype_dbus_array_%s ());\n' % 0273 (self.prefix_, escape_as_identifier(sig[2:-1]))) 0274 elif sig[:1] == 'a': 0275 # array of arrays of non-struct 0276 self.c(' t = dbus_g_type_get_collection (' 0277 '"GPtrArray", ' 0278 '%stype_dbus_array_of_%s ());\n' % 0279 (self.prefix_, escape_as_identifier(sig[1:]))) 0280 else: 0281 raise AssertionError("array of '%s' not supported" % sig) 0282 0283 self.c(' return t;\n') 0284 self.c('}\n\n') 0285 0286 if __name__ == '__main__': 0287 argv = sys.argv[1:] 0288 0289 dom = xml.dom.minidom.parse(argv[0]) 0290 0291 GTypesGenerator(dom, argv[1], argv[2])()