mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-26 03:35:33 +00:00
be8b24333a
This information is read in order to handle correctly selecting the native type and header files for WebIDL types.
236 lines
8.4 KiB
Python
Executable File
236 lines
8.4 KiB
Python
Executable File
#!/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
|
|
|
|
# Load the webidl configuration file.
|
|
glbl = {}
|
|
execfile(mozpath.join(buildconfig.topsrcdir,
|
|
'dom', 'bindings', 'Bindings.conf'),
|
|
glbl)
|
|
webidlconfig = glbl['DOMInterfaces']
|
|
|
|
# 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, webidlconfig)
|
|
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
|