#!/usr/bin/env python # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. import sys import os import buildconfig import mozpack.path as mozpath # The xpidl parser is not incorporated in the in-tree virtualenv. xpidl_dir = mozpath.join(buildconfig.topsrcdir, 'xpcom', 'idl-parser', 'xpidl') xpidl_cachedir = mozpath.join(buildconfig.topobjdir, 'xpcom', 'idl-parser', 'xpidl') sys.path.extend([xpidl_dir, xpidl_cachedir]) import xpidl # Instantiate the parser. p = xpidl.IDLParser() def findIDL(includePath, interfaceFileName): for d in includePath: path = mozpath.join(d, interfaceFileName) if os.path.exists(path): return path raise BaseException("No IDL file found for interface %s " "in include path %r" % (interfaceFileName, includePath)) def loadEventIDL(parser, includePath, eventname): eventidl = ("nsIAccessible%s.idl" % eventname) idlFile = findIDL(includePath, eventidl) idl = p.parse(open(idlFile).read(), idlFile) idl.resolve(includePath, p) return idl, idlFile class Configuration: def __init__(self, filename): config = {} execfile(filename, config) self.simple_events = config.get('simple_events', []) def firstCap(str): return str[0].upper() + str[1:] def writeAttributeParams(a): return ("%s a%s" % (a.realtype.nativeType('in'), firstCap(a.name))) def print_header_file(fd, conf, incdirs): idl_paths = set() fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n") fd.write("#ifndef _mozilla_a11y_generated_AccEvents_h_\n" "#define _mozilla_a11y_generated_AccEvents_h_\n\n") fd.write("#include \"nscore.h\"\n") fd.write("#include \"nsCOMPtr.h\"\n") fd.write("#include \"nsCycleCollectionParticipant.h\"\n") fd.write("#include \"nsString.h\"\n") for e in conf.simple_events: fd.write("#include \"nsIAccessible%s.h\"\n" % e) for e in conf.simple_events: idl, idl_path = loadEventIDL(p, incdirs, e) idl_paths.add(idl_path) for iface in filter(lambda p: p.kind == "interface", idl.productions): classname = ("xpcAcc%s" % e) baseinterfaces = interfaces(iface) fd.write("\nclass %s final : public %s\n" % (classname, iface.name)) fd.write("{\n") fd.write("public:\n") attributes = allAttributes(iface) args = map(writeAttributeParams, attributes) fd.write(" %s(%s) :\n" % (classname, ", ".join(args))) initializers = [] for a in attributes: initializers.append("m%s(a%s)" % (firstCap(a.name), firstCap(a.name))) fd.write(" %s\n {}\n\n" % ", ".join(initializers)) fd.write(" NS_DECL_CYCLE_COLLECTING_ISUPPORTS\n") fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS(%s)\n" % (classname)) for iface in filter(lambda i: i.name != "nsISupports", baseinterfaces): fd.write(" NS_DECL_%s\n" % iface.name.upper()) fd.write("\nprivate:\n") fd.write(" ~%s() {}\n\n" % classname) for a in attributes: fd.write(" %s\n" % attributeVariableTypeAndName(a)) fd.write("};\n\n") fd.write("#endif\n") return idl_paths def interfaceAttributeTypes(idl): ifaces = filter(lambda p: p.kind == "interface", idl.productions) attributes = [] for i in ifaces: ifaceAttributes = allAttributes(i) attributes.extend(ifaceAttributes) ifaceAttrs = filter(lambda a: a.realtype.nativeType("in").endswith("*"), attributes) return map(lambda a: a.realtype.nativeType("in").strip(" *"), ifaceAttrs) def print_cpp(idl, fd, conf, eventname): for p in idl.productions: if p.kind == 'interface': write_cpp(eventname, p, fd) def print_cpp_file(fd, conf, incdirs): idl_paths = set() fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n") fd.write('#include "xpcAccEvents.h"\n') includes = [] for e in conf.simple_events: if not e in includes: includes.append(("nsIAccessible%s" % e)) types = [] for e in conf.simple_events: idl, idl_path = loadEventIDL(p, incdirs, e) idl_paths.add(idl_path) types.extend(interfaceAttributeTypes(idl)) for c in types: fd.write("#include \"%s.h\"\n" % c) fd.write("\n") for e in conf.simple_events: idl, idl_path = loadEventIDL(p, incdirs, e) idl_paths.add(idl_path) print_cpp(idl, fd, conf, e) return idl_paths def attributeVariableTypeAndName(a): if a.realtype.nativeType('in').endswith('*'): l = ["nsCOMPtr<%s> m%s;" % (a.realtype.nativeType('in').strip('* '), firstCap(a.name))] elif a.realtype.nativeType('in').count("nsAString"): l = ["nsString m%s;" % firstCap(a.name)] elif a.realtype.nativeType('in').count("nsACString"): l = ["nsCString m%s;" % firstCap(a.name)] else: l = ["%sm%s;" % (a.realtype.nativeType('in'), firstCap(a.name))] return ", ".join(l) def writeAttributeGetter(fd, classname, a): fd.write("NS_IMETHODIMP\n") fd.write("%s::Get%s(" % (classname, firstCap(a.name))) if a.realtype.nativeType('in').endswith('*'): fd.write("%s** a%s" % (a.realtype.nativeType('in').strip('* '), firstCap(a.name))) elif a.realtype.nativeType('in').count("nsAString"): fd.write("nsAString& a%s" % firstCap(a.name)) elif a.realtype.nativeType('in').count("nsACString"): fd.write("nsACString& a%s" % firstCap(a.name)) else: fd.write("%s*a%s" % (a.realtype.nativeType('in'), firstCap(a.name))) fd.write(")\n"); fd.write("{\n"); if a.realtype.nativeType('in').endswith('*'): fd.write(" NS_IF_ADDREF(*a%s = m%s);\n" % (firstCap(a.name), firstCap(a.name))) elif a.realtype.nativeType('in').count("nsAString"): fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) elif a.realtype.nativeType('in').count("nsACString"): fd.write(" a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) else: fd.write(" *a%s = m%s;\n" % (firstCap(a.name), firstCap(a.name))) fd.write(" return NS_OK;\n"); fd.write("}\n\n"); def interfaces(iface): interfaces = [] while iface.base: interfaces.append(iface) iface = iface.idl.getName(iface.base, iface.location) interfaces.append(iface) interfaces.reverse() return interfaces def allAttributes(iface): attributes = [] for i in interfaces(iface): attrs = filter(lambda m: isinstance(m, xpidl.Attribute), i.members) attributes.extend(attrs) return attributes def write_cpp(eventname, iface, fd): classname = "xpcAcc%s" % eventname attributes = allAttributes(iface) ccattributes = filter(lambda m: m.realtype.nativeType('in').endswith('*'), attributes) fd.write("NS_IMPL_CYCLE_COLLECTION(%s" % classname) for c in ccattributes: fd.write(", m%s" % firstCap(c.name)) fd.write(")\n\n"); fd.write("NS_IMPL_CYCLE_COLLECTING_ADDREF(%s)\n" % classname) fd.write("NS_IMPL_CYCLE_COLLECTING_RELEASE(%s)\n\n" % classname) fd.write("NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(%s)\n" % classname) for baseiface in interfaces(iface): fd.write(" NS_INTERFACE_MAP_ENTRY(%s)\n" % baseiface.name) fd.write("NS_INTERFACE_MAP_END\n\n") for a in attributes: writeAttributeGetter(fd, classname, a) def get_conf(conf_file): conf = Configuration(conf_file) inc_dir = [ mozpath.join(buildconfig.topsrcdir, 'accessible', 'interfaces'), mozpath.join(buildconfig.topsrcdir, 'xpcom', 'base'), ] return conf, inc_dir def gen_files(fd, conf_file, xpidllex, xpidlyacc): deps = set() conf, inc_dir = get_conf(conf_file) deps.update(print_header_file(fd, conf, inc_dir)) with open(os.path.join(os.path.dirname(fd.name), 'xpcAccEvents.cpp'), 'w') as cpp_fd: deps.update(print_cpp_file(cpp_fd, conf, inc_dir)) return deps