File indexing completed on 2024-05-05 17:01:41
0001 #!/usr/bin/python 0002 # 0003 # Copyright (C) 2008 Collabora Limited <http://www.collabora.co.uk> 0004 # Copyright (C) 2008 Nokia Corporation 0005 # 0006 # This library is free software; you can redistribute it and/or 0007 # modify it under the terms of the GNU Lesser General Public 0008 # License as published by the Free Software Foundation; either 0009 # version 2.1 of the License, or (at your option) any later version. 0010 # 0011 # This library is distributed in the hope that it will be useful, 0012 # but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 # Lesser General Public License for more details. 0015 # 0016 # You should have received a copy of the GNU Lesser General Public 0017 # License along with this library; if not, write to the Free Software 0018 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 0019 0020 from sys import argv, stdout, stderr 0021 import codecs 0022 import xml.dom.minidom 0023 from getopt import gnu_getopt 0024 0025 from libtpcodegen import NS_TP, get_descendant_text, get_by_path 0026 from libqtcodegen import format_docstring, RefRegistry 0027 0028 class Generator(object): 0029 def __init__(self, opts): 0030 try: 0031 self.namespace = opts['--namespace'] 0032 self.must_define = opts.get('--must-define', None) 0033 dom = xml.dom.minidom.parse(opts['--specxml']) 0034 except KeyError, k: 0035 assert False, 'Missing required parameter %s' % k.args[0] 0036 0037 self.define_prefix = None 0038 if '--define-prefix' in opts: 0039 self.define_prefix = opts['--define-prefix'] 0040 0041 self.old_prefix = None 0042 if '--str-constant-prefix' in opts: 0043 self.old_prefix = opts['--str-constant-prefix'] 0044 0045 self.spec = get_by_path(dom, "spec")[0] 0046 self.out = codecs.getwriter('utf-8')(stdout) 0047 self.refs = RefRegistry(self.spec) 0048 0049 def h(self, code): 0050 self.out.write(code) 0051 0052 def __call__(self): 0053 # Header 0054 self.h('/* Generated from ') 0055 self.h(get_descendant_text(get_by_path(self.spec, 'title'))) 0056 version = get_by_path(self.spec, "version") 0057 0058 if version: 0059 self.h(', version ' + get_descendant_text(version)) 0060 0061 self.h(""" 0062 */ 0063 """) 0064 0065 if self.must_define: 0066 self.h(""" 0067 #ifndef %s 0068 #error %s 0069 #endif 0070 """ % (self.must_define, self.must_define)) 0071 0072 self.h(""" 0073 #include <QFlags> 0074 0075 /** 0076 * \\addtogroup typesconstants Types and constants 0077 * 0078 * Enumerated, flag, structure, list and mapping types and utility constants. 0079 */ 0080 0081 /** 0082 * \\defgroup flagtypeconsts Flag type constants 0083 * \\ingroup typesconstants 0084 * 0085 * Types generated from the specification representing bit flag constants and 0086 * combinations of them (bitfields). 0087 */ 0088 0089 /** 0090 * \\defgroup enumtypeconsts Enumerated type constants 0091 * \\ingroup typesconstants 0092 * 0093 * Types generated from the specification representing enumerated types ie. 0094 * types the values of which are mutually exclusive integral constants. 0095 */ 0096 0097 /** 0098 * \\defgroup ifacestrconsts Interface string constants 0099 * \\ingroup typesconstants 0100 * 0101 * D-Bus interface names of the interfaces in the specification. 0102 */ 0103 0104 /** 0105 * \\defgroup errorstrconsts Error string constants 0106 * \\ingroup typesconstants 0107 * 0108 * Names of the D-Bus errors in the specification. 0109 */ 0110 """) 0111 0112 # Begin namespace 0113 self.h(""" 0114 namespace %s 0115 { 0116 """ % self.namespace) 0117 0118 # Flags 0119 for flags in self.spec.getElementsByTagNameNS(NS_TP, 'flags'): 0120 self.do_flags(flags) 0121 0122 # Enums 0123 for enum in self.spec.getElementsByTagNameNS(NS_TP, 'enum'): 0124 self.do_enum(enum) 0125 0126 # End namespace 0127 self.h("""\ 0128 } 0129 0130 """) 0131 0132 # Interface names 0133 for iface in self.spec.getElementsByTagName('interface'): 0134 if self.old_prefix: 0135 self.h("""\ 0136 /** 0137 * \\ingroup ifacestrconsts 0138 * 0139 * The interface name "%(name)s". 0140 */ 0141 #define %(DEFINE)s "%(name)s" 0142 0143 """ % {'name' : iface.getAttribute('name'), 0144 'DEFINE' : self.old_prefix + 'INTERFACE_' + get_by_path(iface, '../@name').upper().replace('/', '')}) 0145 0146 if self.define_prefix: 0147 self.h("""\ 0148 /** 0149 * \\ingroup ifacestrconsts 0150 * 0151 * The interface name "%(name)s" as a QLatin1String, usable in QString requiring contexts even when 0152 * building with Q_NO_CAST_FROM_ASCII defined. 0153 */ 0154 #define %(DEFINE)s (QLatin1String("%(name)s")) 0155 0156 """ % {'name' : iface.getAttribute('name'), 0157 'DEFINE' : self.define_prefix + 'IFACE_' + get_by_path(iface, '../@name').upper().replace('/', '')}) 0158 0159 # Error names 0160 for error in get_by_path(self.spec, 'errors/error'): 0161 name = error.getAttribute('name') 0162 fullname = get_by_path(error, '../@namespace') + '.' + name.replace(' ', '') 0163 0164 if self.old_prefix: 0165 define = self.old_prefix + 'ERROR_' + name.replace(' ', '_').replace('.', '_').upper() 0166 self.h("""\ 0167 /** 0168 * \\ingroup errorstrconsts 0169 * 0170 * The error name "%(fullname)s". 0171 %(docstring)s\ 0172 */ 0173 #define %(DEFINE)s "%(fullname)s" 0174 0175 """ % {'fullname' : fullname, 0176 'docstring': format_docstring(error, self.refs), 0177 'DEFINE' : define}) 0178 0179 if self.define_prefix: 0180 define = self.define_prefix + 'ERROR_' + name.replace(' ', '_').replace('.', '_').upper() 0181 self.h("""\ 0182 /** 0183 * \\ingroup errorstrconsts 0184 * 0185 * The error name "%(fullname)s" as a QLatin1String, usable in QString requiring contexts even when 0186 * building with Q_NO_CAST_FROM_ASCII defined. 0187 %(docstring)s\ 0188 */ 0189 #define %(DEFINE)s QLatin1String("%(fullname)s") 0190 0191 """ % {'fullname' : fullname, 0192 'docstring': format_docstring(error, self.refs), 0193 'DEFINE' : define}) 0194 0195 def do_flags(self, flags): 0196 singular = flags.getAttribute('singular') or \ 0197 flags.getAttribute('value-prefix') 0198 0199 using_name = False 0200 if not singular: 0201 using_name = True 0202 singular = flags.getAttribute('name') 0203 0204 if singular.endswith('lags'): 0205 singular = singular[:-1] 0206 0207 if using_name and singular.endswith('s'): 0208 singular = singular[:-1] 0209 0210 singular = singular.replace('_', '') 0211 plural = (flags.getAttribute('plural') or flags.getAttribute('name') or singular + 's').replace('_', '') 0212 self.h("""\ 0213 /** 0214 * \\ingroup flagtypeconsts 0215 * 0216 * Flag type generated from the specification. 0217 */ 0218 enum %(singular)s 0219 { 0220 """ % {'singular' : singular}) 0221 0222 flagvalues = get_by_path(flags, 'flag') 0223 0224 for flag in flagvalues: 0225 self.do_val(flag, singular, flag == flagvalues[-1]) 0226 0227 self.h("""\ 0228 %s = 0xffffffffU 0229 """ % ("_" + singular + "Padding")) 0230 0231 self.h("""\ 0232 }; 0233 0234 /** 0235 * \\typedef QFlags<%(singular)s> %(plural)s 0236 * \\ingroup flagtypeconsts 0237 * 0238 * Type representing combinations of #%(singular)s values. 0239 %(docstring)s\ 0240 */ 0241 typedef QFlags<%(singular)s> %(plural)s; 0242 Q_DECLARE_OPERATORS_FOR_FLAGS(%(plural)s) 0243 0244 """ % {'singular' : singular, 'plural' : plural, 'docstring' : format_docstring(flags, self.refs)}) 0245 0246 def do_enum(self, enum): 0247 singular = enum.getAttribute('singular') or \ 0248 enum.getAttribute('name') 0249 value_prefix = enum.getAttribute('singular') or \ 0250 enum.getAttribute('value-prefix') or \ 0251 enum.getAttribute('name') 0252 0253 if singular.endswith('lags'): 0254 singular = singular[:-1] 0255 0256 plural = enum.getAttribute('plural') or singular + 's' 0257 singular = singular.replace('_', '') 0258 value_prefix = value_prefix.replace('_', '') 0259 vals = get_by_path(enum, 'enumvalue') 0260 0261 self.h("""\ 0262 /** 0263 * \\enum %(singular)s 0264 * \\ingroup enumtypeconsts 0265 * 0266 * Enumerated type generated from the specification. 0267 %(docstring)s\ 0268 */ 0269 enum %(singular)s 0270 { 0271 """ % {'singular' : singular, 'docstring' : format_docstring(enum, self.refs)}) 0272 0273 for val in vals: 0274 self.do_val(val, value_prefix, val == vals[-1]) 0275 0276 self.h("""\ 0277 %s = 0xffffffffU 0278 }; 0279 0280 """ % ("_" + singular + "Padding")) 0281 0282 self.h("""\ 0283 /** 0284 * \\ingroup enumtypeconsts 0285 * 0286 * 1 higher than the highest valid value of %(singular)s. 0287 */ 0288 const int NUM_%(upper-plural)s = (%(last-val)s+1); 0289 0290 """ % {'singular' : singular, 0291 'upper-plural' : plural.upper(), 0292 'last-val' : vals[-1].getAttribute('value')}) 0293 0294 def do_val(self, val, prefix, last): 0295 name = (val.getAttribute('suffix') or val.getAttribute('name')).replace('_', '') 0296 self.h("""\ 0297 %s\ 0298 %s = %s, 0299 0300 """ % (format_docstring(val, self.refs, indent=' * ', brackets=(' /**', ' */')), prefix + name, val.getAttribute('value'))) 0301 0302 if __name__ == '__main__': 0303 options, argv = gnu_getopt(argv[1:], '', 0304 ['namespace=', 0305 'str-constant-prefix=', 0306 'define-prefix=', 0307 'must-define=', 0308 'specxml=']) 0309 0310 Generator(dict(options))()