michael@0: #!/usr/bin/env python michael@0: # michael@0: # This Source Code Form is subject to the terms of the Mozilla Public michael@0: # License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: # file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: michael@0: import sys, os, xpidl, makeutils michael@0: michael@0: def findIDL(includePath, interfaceFileName): michael@0: for d in includePath: michael@0: # Not os.path.join: we need a forward slash even on Windows because michael@0: # this filename ends up in makedepend output. michael@0: path = d + '/' + interfaceFileName michael@0: if os.path.exists(path): michael@0: return path michael@0: raise BaseException("No IDL file found for interface %s " michael@0: "in include path %r" michael@0: % (interfaceFileName, includePath)) michael@0: michael@0: def loadEventIDL(parser, includePath, eventname): michael@0: eventidl = ("nsIAccessible%s.idl" % eventname) michael@0: idlFile = findIDL(includePath, eventidl) michael@0: if not idlFile in makeutils.dependencies: michael@0: makeutils.dependencies.append(idlFile) michael@0: idl = p.parse(open(idlFile).read(), idlFile) michael@0: idl.resolve(includePath, p) michael@0: return idl michael@0: michael@0: class Configuration: michael@0: def __init__(self, filename): michael@0: config = {} michael@0: execfile(filename, config) michael@0: self.simple_events = config.get('simple_events', []) michael@0: michael@0: def readConfigFile(filename): michael@0: return Configuration(filename) michael@0: michael@0: def firstCap(str): michael@0: return str[0].upper() + str[1:] michael@0: michael@0: def writeAttributeParams(a): michael@0: return ("%s a%s" % (a.realtype.nativeType('in'), firstCap(a.name))) michael@0: michael@0: def print_header_file(fd, conf): michael@0: fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n") michael@0: fd.write("#ifndef _mozilla_a11y_generated_AccEvents_h_\n" michael@0: "#define _mozilla_a11y_generated_AccEvents_h_\n\n") michael@0: fd.write("#include \"nscore.h\"\n") michael@0: fd.write("#include \"nsCOMPtr.h\"\n") michael@0: fd.write("#include \"nsCycleCollectionParticipant.h\"\n") michael@0: fd.write("#include \"nsString.h\"\n") michael@0: for e in conf.simple_events: michael@0: fd.write("#include \"nsIAccessible%s.h\"\n" % e) michael@0: for e in conf.simple_events: michael@0: idl = loadEventIDL(p, options.incdirs, e) michael@0: for iface in filter(lambda p: p.kind == "interface", idl.productions): michael@0: classname = ("xpcAcc%s" % e) michael@0: baseinterfaces = interfaces(iface) michael@0: michael@0: fd.write("\nclass %s MOZ_FINAL : public %s\n" % (classname, iface.name)) michael@0: fd.write("{\n") michael@0: fd.write("public:\n") michael@0: michael@0: attributes = allAttributes(iface) michael@0: args = map(writeAttributeParams, attributes) michael@0: fd.write(" %s(%s) :\n" % (classname, ", ".join(args))) michael@0: michael@0: initializers = [] michael@0: for a in attributes: michael@0: initializers.append("m%s(a%s)" % (firstCap(a.name), firstCap(a.name))) michael@0: fd.write(" %s\n {}\n" % ", ".join(initializers)) michael@0: fd.write(" ~%s() {}\n\n" % classname) michael@0: fd.write(" NS_DECL_CYCLE_COLLECTING_ISUPPORTS\n") michael@0: fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS(%s)\n" % (classname)) michael@0: michael@0: for iface in filter(lambda i: i.name != "nsISupports", baseinterfaces): michael@0: fd.write(" NS_DECL_%s\n" % iface.name.upper()) michael@0: michael@0: fd.write("private:\n") michael@0: for a in attributes: michael@0: fd.write(" %s\n" % attributeVariableTypeAndName(a)) michael@0: fd.write("};\n\n") michael@0: michael@0: fd.write("#endif\n") michael@0: michael@0: def interfaceAttributeTypes(idl): michael@0: ifaces = filter(lambda p: p.kind == "interface", idl.productions) michael@0: attributes = [] michael@0: for i in ifaces: michael@0: ifaceAttributes = allAttributes(i) michael@0: attributes.extend(ifaceAttributes) michael@0: ifaceAttrs = filter(lambda a: a.realtype.nativeType("in").endswith("*"), attributes) michael@0: return map(lambda a: a.realtype.nativeType("in").strip(" *"), ifaceAttrs) michael@0: michael@0: def print_cpp(idl, fd, conf, eventname): michael@0: for p in idl.productions: michael@0: if p.kind == 'interface': michael@0: write_cpp(eventname, p, fd) michael@0: michael@0: def print_cpp_file(fd, conf): michael@0: fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n") michael@0: fd.write('#include "xpcAccEvents.h"\n') michael@0: michael@0: includes = [] michael@0: for e in conf.simple_events: michael@0: if not e in includes: michael@0: includes.append(("nsIAccessible%s" % e)) michael@0: michael@0: types = [] michael@0: for e in conf.simple_events: michael@0: idl = loadEventIDL(p, options.incdirs, e) michael@0: types.extend(interfaceAttributeTypes(idl)) michael@0: michael@0: for c in types: michael@0: fd.write("#include \"%s.h\"\n" % c) michael@0: michael@0: fd.write("\n") michael@0: for e in conf.simple_events: michael@0: print_cpp(loadEventIDL(p, options.incdirs, e), fd, conf, e) michael@0: michael@0: def attributeVariableTypeAndName(a): michael@0: if a.realtype.nativeType('in').endswith('*'): michael@0: l = ["nsCOMPtr<%s> m%s;" % (a.realtype.nativeType('in').strip('* '), michael@0: firstCap(a.name))] michael@0: elif a.realtype.nativeType('in').count("nsAString"): michael@0: l = ["nsString m%s;" % firstCap(a.name)] michael@0: elif a.realtype.nativeType('in').count("nsACString"): michael@0: l = ["nsCString m%s;" % firstCap(a.name)] michael@0: else: michael@0: l = ["%sm%s;" % (a.realtype.nativeType('in'), michael@0: firstCap(a.name))] michael@0: return ", ".join(l) michael@0: michael@0: def writeAttributeGetter(fd, classname, a): michael@0: fd.write("NS_IMETHODIMP\n") michael@0: fd.write("%s::Get%s(" % (classname, firstCap(a.name))) michael@0: if a.realtype.nativeType('in').endswith('*'): michael@0: fd.write("%s** a%s" % (a.realtype.nativeType('in').strip('* '), firstCap(a.name))) michael@0: elif a.realtype.nativeType('in').count("nsAString"): michael@0: fd.write("nsAString& a%s" % firstCap(a.name)) michael@0: elif a.realtype.nativeType('in').count("nsACString"): michael@0: fd.write("nsACString& a%s" % firstCap(a.name)) michael@0: else: michael@0: fd.write("%s*a%s" % (a.realtype.nativeType('in'), firstCap(a.name))) michael@0: fd.write(")\n"); michael@0: fd.write("{\n"); michael@0: if a.realtype.nativeType('in').endswith('*'): michael@0: fd.write(" NS_IF_ADDREF(*a%s = m%s);\n" % (firstCap(a.name), firstCap(a.name))) michael@0: elif a.realtype.nativeType('in').count("nsAString"): michael@0: fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) michael@0: elif a.realtype.nativeType('in').count("nsACString"): michael@0: fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) michael@0: else: michael@0: fd.write(" *a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) michael@0: fd.write(" return NS_OK;\n"); michael@0: fd.write("}\n\n"); michael@0: michael@0: def interfaces(iface): michael@0: interfaces = [] michael@0: while iface.base: michael@0: interfaces.append(iface) michael@0: iface = iface.idl.getName(iface.base, iface.location) michael@0: interfaces.append(iface) michael@0: interfaces.reverse() michael@0: return interfaces michael@0: michael@0: def allAttributes(iface): michael@0: attributes = [] michael@0: for i in interfaces(iface): michael@0: attrs = filter(lambda m: isinstance(m, xpidl.Attribute), i.members) michael@0: attributes.extend(attrs) michael@0: michael@0: return attributes michael@0: michael@0: def write_cpp(eventname, iface, fd): michael@0: classname = "xpcAcc%s" % eventname michael@0: attributes = allAttributes(iface) michael@0: ccattributes = filter(lambda m: m.realtype.nativeType('in').endswith('*'), attributes) michael@0: fd.write("NS_IMPL_CYCLE_COLLECTION(%s" % classname) michael@0: for c in ccattributes: michael@0: fd.write(", m%s" % firstCap(c.name)) michael@0: fd.write(")\n\n"); michael@0: michael@0: fd.write("NS_IMPL_CYCLE_COLLECTING_ADDREF(%s)\n" % classname) michael@0: fd.write("NS_IMPL_CYCLE_COLLECTING_RELEASE(%s)\n\n" % classname) michael@0: michael@0: fd.write("NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(%s)\n" % classname) michael@0: for baseiface in interfaces(iface): michael@0: fd.write(" NS_INTERFACE_MAP_ENTRY(%s)\n" % baseiface.name) michael@0: fd.write("NS_INTERFACE_MAP_END\n\n") michael@0: michael@0: for a in attributes: michael@0: writeAttributeGetter(fd, classname, a) michael@0: michael@0: michael@0: def main(): michael@0: from optparse import OptionParser michael@0: o = OptionParser(usage="usage: %prog [options] configfile") michael@0: o.add_option('-I', action='append', dest='incdirs', default=['.'], michael@0: help="Directory to search for imported files") michael@0: o.add_option('-o', "--stub-output", michael@0: type='string', dest='stub_output', default=None, michael@0: help="C++ source output file", metavar="FILE") michael@0: o.add_option('--header-output', type='string', default=None, michael@0: help="Quick stub header output file", metavar="FILE") michael@0: o.add_option('--makedepend-output', type='string', default=None, michael@0: help="gnumake dependencies output file", metavar="FILE") michael@0: o.add_option('--cachedir', dest='cachedir', default=None, michael@0: help="Directory in which to cache lex/parse tables.") michael@0: global options michael@0: (options, filenames) = o.parse_args() michael@0: if len(filenames) != 1: michael@0: o.error("Exactly one config filename is needed.") michael@0: filename = filenames[0] michael@0: michael@0: if options.cachedir is not None: michael@0: if not os.path.isdir(options.cachedir): michael@0: os.mkdir(options.cachedir) michael@0: sys.path.append(options.cachedir) michael@0: michael@0: # Instantiate the parser. michael@0: global p michael@0: p = xpidl.IDLParser(outputdir=options.cachedir) michael@0: michael@0: conf = readConfigFile(filename) michael@0: michael@0: if options.stub_output is not None: michael@0: makeutils.targets.append(options.stub_output) michael@0: outfd = open(options.stub_output, 'w') michael@0: print_cpp_file(outfd, conf) michael@0: outfd.close() michael@0: if options.makedepend_output is not None: michael@0: makeutils.writeMakeDependOutput(options.makedepend_output) michael@0: if options.header_output is not None: michael@0: outfd = open(options.header_output, 'w') michael@0: print_header_file(outfd, conf) michael@0: outfd.close() michael@0: michael@0: if __name__ == '__main__': michael@0: main()