1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/accessible/src/xpcom/AccEventGen.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,240 @@ 1.4 +#!/usr/bin/env python 1.5 +# 1.6 +# This Source Code Form is subject to the terms of the Mozilla Public 1.7 +# License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 +# file, You can obtain one at http://mozilla.org/MPL/2.0/. 1.9 + 1.10 +import sys, os, xpidl, makeutils 1.11 + 1.12 +def findIDL(includePath, interfaceFileName): 1.13 + for d in includePath: 1.14 + # Not os.path.join: we need a forward slash even on Windows because 1.15 + # this filename ends up in makedepend output. 1.16 + path = d + '/' + interfaceFileName 1.17 + if os.path.exists(path): 1.18 + return path 1.19 + raise BaseException("No IDL file found for interface %s " 1.20 + "in include path %r" 1.21 + % (interfaceFileName, includePath)) 1.22 + 1.23 +def loadEventIDL(parser, includePath, eventname): 1.24 + eventidl = ("nsIAccessible%s.idl" % eventname) 1.25 + idlFile = findIDL(includePath, eventidl) 1.26 + if not idlFile in makeutils.dependencies: 1.27 + makeutils.dependencies.append(idlFile) 1.28 + idl = p.parse(open(idlFile).read(), idlFile) 1.29 + idl.resolve(includePath, p) 1.30 + return idl 1.31 + 1.32 +class Configuration: 1.33 + def __init__(self, filename): 1.34 + config = {} 1.35 + execfile(filename, config) 1.36 + self.simple_events = config.get('simple_events', []) 1.37 + 1.38 +def readConfigFile(filename): 1.39 + return Configuration(filename) 1.40 + 1.41 +def firstCap(str): 1.42 + return str[0].upper() + str[1:] 1.43 + 1.44 +def writeAttributeParams(a): 1.45 + return ("%s a%s" % (a.realtype.nativeType('in'), firstCap(a.name))) 1.46 + 1.47 +def print_header_file(fd, conf): 1.48 + fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n") 1.49 + fd.write("#ifndef _mozilla_a11y_generated_AccEvents_h_\n" 1.50 + "#define _mozilla_a11y_generated_AccEvents_h_\n\n") 1.51 + fd.write("#include \"nscore.h\"\n") 1.52 + fd.write("#include \"nsCOMPtr.h\"\n") 1.53 + fd.write("#include \"nsCycleCollectionParticipant.h\"\n") 1.54 + fd.write("#include \"nsString.h\"\n") 1.55 + for e in conf.simple_events: 1.56 + fd.write("#include \"nsIAccessible%s.h\"\n" % e) 1.57 + for e in conf.simple_events: 1.58 + idl = loadEventIDL(p, options.incdirs, e) 1.59 + for iface in filter(lambda p: p.kind == "interface", idl.productions): 1.60 + classname = ("xpcAcc%s" % e) 1.61 + baseinterfaces = interfaces(iface) 1.62 + 1.63 + fd.write("\nclass %s MOZ_FINAL : public %s\n" % (classname, iface.name)) 1.64 + fd.write("{\n") 1.65 + fd.write("public:\n") 1.66 + 1.67 + attributes = allAttributes(iface) 1.68 + args = map(writeAttributeParams, attributes) 1.69 + fd.write(" %s(%s) :\n" % (classname, ", ".join(args))) 1.70 + 1.71 + initializers = [] 1.72 + for a in attributes: 1.73 + initializers.append("m%s(a%s)" % (firstCap(a.name), firstCap(a.name))) 1.74 + fd.write(" %s\n {}\n" % ", ".join(initializers)) 1.75 + fd.write(" ~%s() {}\n\n" % classname) 1.76 + fd.write(" NS_DECL_CYCLE_COLLECTING_ISUPPORTS\n") 1.77 + fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS(%s)\n" % (classname)) 1.78 + 1.79 + for iface in filter(lambda i: i.name != "nsISupports", baseinterfaces): 1.80 + fd.write(" NS_DECL_%s\n" % iface.name.upper()) 1.81 + 1.82 + fd.write("private:\n") 1.83 + for a in attributes: 1.84 + fd.write(" %s\n" % attributeVariableTypeAndName(a)) 1.85 + fd.write("};\n\n") 1.86 + 1.87 + fd.write("#endif\n") 1.88 + 1.89 +def interfaceAttributeTypes(idl): 1.90 + ifaces = filter(lambda p: p.kind == "interface", idl.productions) 1.91 + attributes = [] 1.92 + for i in ifaces: 1.93 + ifaceAttributes = allAttributes(i) 1.94 + attributes.extend(ifaceAttributes) 1.95 + ifaceAttrs = filter(lambda a: a.realtype.nativeType("in").endswith("*"), attributes) 1.96 + return map(lambda a: a.realtype.nativeType("in").strip(" *"), ifaceAttrs) 1.97 + 1.98 +def print_cpp(idl, fd, conf, eventname): 1.99 + for p in idl.productions: 1.100 + if p.kind == 'interface': 1.101 + write_cpp(eventname, p, fd) 1.102 + 1.103 +def print_cpp_file(fd, conf): 1.104 + fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n") 1.105 + fd.write('#include "xpcAccEvents.h"\n') 1.106 + 1.107 + includes = [] 1.108 + for e in conf.simple_events: 1.109 + if not e in includes: 1.110 + includes.append(("nsIAccessible%s" % e)) 1.111 + 1.112 + types = [] 1.113 + for e in conf.simple_events: 1.114 + idl = loadEventIDL(p, options.incdirs, e) 1.115 + types.extend(interfaceAttributeTypes(idl)) 1.116 + 1.117 + for c in types: 1.118 + fd.write("#include \"%s.h\"\n" % c) 1.119 + 1.120 + fd.write("\n") 1.121 + for e in conf.simple_events: 1.122 + print_cpp(loadEventIDL(p, options.incdirs, e), fd, conf, e) 1.123 + 1.124 +def attributeVariableTypeAndName(a): 1.125 + if a.realtype.nativeType('in').endswith('*'): 1.126 + l = ["nsCOMPtr<%s> m%s;" % (a.realtype.nativeType('in').strip('* '), 1.127 + firstCap(a.name))] 1.128 + elif a.realtype.nativeType('in').count("nsAString"): 1.129 + l = ["nsString m%s;" % firstCap(a.name)] 1.130 + elif a.realtype.nativeType('in').count("nsACString"): 1.131 + l = ["nsCString m%s;" % firstCap(a.name)] 1.132 + else: 1.133 + l = ["%sm%s;" % (a.realtype.nativeType('in'), 1.134 + firstCap(a.name))] 1.135 + return ", ".join(l) 1.136 + 1.137 +def writeAttributeGetter(fd, classname, a): 1.138 + fd.write("NS_IMETHODIMP\n") 1.139 + fd.write("%s::Get%s(" % (classname, firstCap(a.name))) 1.140 + if a.realtype.nativeType('in').endswith('*'): 1.141 + fd.write("%s** a%s" % (a.realtype.nativeType('in').strip('* '), firstCap(a.name))) 1.142 + elif a.realtype.nativeType('in').count("nsAString"): 1.143 + fd.write("nsAString& a%s" % firstCap(a.name)) 1.144 + elif a.realtype.nativeType('in').count("nsACString"): 1.145 + fd.write("nsACString& a%s" % firstCap(a.name)) 1.146 + else: 1.147 + fd.write("%s*a%s" % (a.realtype.nativeType('in'), firstCap(a.name))) 1.148 + fd.write(")\n"); 1.149 + fd.write("{\n"); 1.150 + if a.realtype.nativeType('in').endswith('*'): 1.151 + fd.write(" NS_IF_ADDREF(*a%s = m%s);\n" % (firstCap(a.name), firstCap(a.name))) 1.152 + elif a.realtype.nativeType('in').count("nsAString"): 1.153 + fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) 1.154 + elif a.realtype.nativeType('in').count("nsACString"): 1.155 + fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) 1.156 + else: 1.157 + fd.write(" *a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) 1.158 + fd.write(" return NS_OK;\n"); 1.159 + fd.write("}\n\n"); 1.160 + 1.161 +def interfaces(iface): 1.162 + interfaces = [] 1.163 + while iface.base: 1.164 + interfaces.append(iface) 1.165 + iface = iface.idl.getName(iface.base, iface.location) 1.166 + interfaces.append(iface) 1.167 + interfaces.reverse() 1.168 + return interfaces 1.169 + 1.170 +def allAttributes(iface): 1.171 + attributes = [] 1.172 + for i in interfaces(iface): 1.173 + attrs = filter(lambda m: isinstance(m, xpidl.Attribute), i.members) 1.174 + attributes.extend(attrs) 1.175 + 1.176 + return attributes 1.177 + 1.178 +def write_cpp(eventname, iface, fd): 1.179 + classname = "xpcAcc%s" % eventname 1.180 + attributes = allAttributes(iface) 1.181 + ccattributes = filter(lambda m: m.realtype.nativeType('in').endswith('*'), attributes) 1.182 + fd.write("NS_IMPL_CYCLE_COLLECTION(%s" % classname) 1.183 + for c in ccattributes: 1.184 + fd.write(", m%s" % firstCap(c.name)) 1.185 + fd.write(")\n\n"); 1.186 + 1.187 + fd.write("NS_IMPL_CYCLE_COLLECTING_ADDREF(%s)\n" % classname) 1.188 + fd.write("NS_IMPL_CYCLE_COLLECTING_RELEASE(%s)\n\n" % classname) 1.189 + 1.190 + fd.write("NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(%s)\n" % classname) 1.191 + for baseiface in interfaces(iface): 1.192 + fd.write(" NS_INTERFACE_MAP_ENTRY(%s)\n" % baseiface.name) 1.193 + fd.write("NS_INTERFACE_MAP_END\n\n") 1.194 + 1.195 + for a in attributes: 1.196 + writeAttributeGetter(fd, classname, a) 1.197 + 1.198 + 1.199 +def main(): 1.200 + from optparse import OptionParser 1.201 + o = OptionParser(usage="usage: %prog [options] configfile") 1.202 + o.add_option('-I', action='append', dest='incdirs', default=['.'], 1.203 + help="Directory to search for imported files") 1.204 + o.add_option('-o', "--stub-output", 1.205 + type='string', dest='stub_output', default=None, 1.206 + help="C++ source output file", metavar="FILE") 1.207 + o.add_option('--header-output', type='string', default=None, 1.208 + help="Quick stub header output file", metavar="FILE") 1.209 + o.add_option('--makedepend-output', type='string', default=None, 1.210 + help="gnumake dependencies output file", metavar="FILE") 1.211 + o.add_option('--cachedir', dest='cachedir', default=None, 1.212 + help="Directory in which to cache lex/parse tables.") 1.213 + global options 1.214 + (options, filenames) = o.parse_args() 1.215 + if len(filenames) != 1: 1.216 + o.error("Exactly one config filename is needed.") 1.217 + filename = filenames[0] 1.218 + 1.219 + if options.cachedir is not None: 1.220 + if not os.path.isdir(options.cachedir): 1.221 + os.mkdir(options.cachedir) 1.222 + sys.path.append(options.cachedir) 1.223 + 1.224 + # Instantiate the parser. 1.225 + global p 1.226 + p = xpidl.IDLParser(outputdir=options.cachedir) 1.227 + 1.228 + conf = readConfigFile(filename) 1.229 + 1.230 + if options.stub_output is not None: 1.231 + makeutils.targets.append(options.stub_output) 1.232 + outfd = open(options.stub_output, 'w') 1.233 + print_cpp_file(outfd, conf) 1.234 + outfd.close() 1.235 + if options.makedepend_output is not None: 1.236 + makeutils.writeMakeDependOutput(options.makedepend_output) 1.237 + if options.header_output is not None: 1.238 + outfd = open(options.header_output, 'w') 1.239 + print_header_file(outfd, conf) 1.240 + outfd.close() 1.241 + 1.242 +if __name__ == '__main__': 1.243 + main()