michael@0: #!/usr/bin/env python michael@0: # header.py - Generate C++ header files from IDL. 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 strip_end(text, suffix): michael@0: if not text.endswith(suffix): michael@0: return text michael@0: return text[:-len(suffix)] 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: eventFileNameToIdl = {}; michael@0: michael@0: def loadIDL(parser, includePath, filename): michael@0: global eventFileNameToIdl michael@0: if filename in eventFileNameToIdl: michael@0: return eventFileNameToIdl[filename] michael@0: michael@0: idlFile = findIDL(includePath, filename) 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: eventFileNameToIdl[filename] = idl michael@0: return idl michael@0: michael@0: def loadEventIDL(parser, includePath, eventname): michael@0: eventidl = ("nsIDOM%s.idl" % eventname) michael@0: return loadIDL(parser, includePath, eventidl) 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: self.special_includes = config.get('special_includes', []) michael@0: self.exclude_automatic_type_include = config.get('exclude_automatic_type_include', []) michael@0: self.xpidl_to_native = config.get('xpidl_to_native', []) 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 getBaseName(iface): michael@0: return ("%s" % iface.base[6:]) michael@0: michael@0: def print_header_file(fd, conf): michael@0: fd.write("#ifndef _gen_mozilla_idl_generated_events_h_\n" michael@0: "#define _gen_mozilla_idl_generated_events_h_\n\n") michael@0: fd.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n") michael@0: fd.write("#include \"nscore.h\"\n") michael@0: fd.write("class nsIDOMEvent;\n") michael@0: fd.write("class nsPresContext;\n") michael@0: fd.write("namespace mozilla {\n"); michael@0: fd.write("class WidgetEvent;\n") michael@0: fd.write("namespace dom {\n"); michael@0: fd.write("class EventTarget;\n") michael@0: fd.write("}\n"); michael@0: fd.write("}\n\n"); michael@0: for e in conf.simple_events: michael@0: fd.write("nsresult\n") michael@0: fd.write("NS_NewDOM%s(nsIDOMEvent** aInstance, " % e) michael@0: fd.write("mozilla::dom::EventTarget* aOwner, ") michael@0: fd.write("nsPresContext* aPresContext, mozilla::WidgetEvent* aEvent);\n") michael@0: michael@0: fd.write("\n#endif\n") michael@0: michael@0: def print_classes_file(fd, conf): michael@0: fd.write("#ifndef _gen_mozilla_idl_generated_event_declarations_h_\n") michael@0: fd.write("#define _gen_mozilla_idl_generated_event_declarations_h_\n\n") michael@0: michael@0: fd.write("#include \"mozilla/dom/Event.h\"\n"); michael@0: includes = [] michael@0: for s in conf.special_includes: michael@0: if not s in includes: michael@0: includes.append(strip_end(s, ".h")) michael@0: michael@0: for e in conf.simple_events: michael@0: if not e in includes: michael@0: includes.append(("nsIDOM%s" % e)) michael@0: michael@0: attrnames = [] michael@0: for e in conf.simple_events: michael@0: idl = loadEventIDL(p, options.incdirs, e) michael@0: collect_names_and_non_primitive_attribute_types(idl, attrnames, includes) michael@0: michael@0: for c in includes: michael@0: if not c in conf.exclude_automatic_type_include: michael@0: fd.write("#include \"%s.h\"\n" % c) michael@0: michael@0: for e in conf.simple_events: michael@0: fd.write('#include "mozilla/dom/%sBinding.h"\n' % e); michael@0: michael@0: fd.write("namespace mozilla {\n") michael@0: fd.write("namespace dom {\n") michael@0: for e in conf.simple_events: michael@0: idl = loadEventIDL(p, options.incdirs, e) michael@0: for pr in idl.productions: michael@0: if pr.kind == 'interface': michael@0: print_class_declaration(e, pr, fd, conf) michael@0: fd.write("} // namespace dom\n") michael@0: fd.write("} // namespace mozilla\n\n") michael@0: fd.write("#endif\n"); michael@0: michael@0: def print_class_declaration(eventname, iface, fd, conf): michael@0: classname = ("%s" % eventname) michael@0: basename = getBaseName(iface) michael@0: attributes = [] michael@0: ccattributes = [] michael@0: for member in iface.members: michael@0: if isinstance(member, xpidl.Attribute): michael@0: attributes.append(member) michael@0: if (member.realtype.nativeType('in').endswith('*')): michael@0: ccattributes.append(member); michael@0: michael@0: baseinterfaces = [] michael@0: baseiface = iface.idl.getName(iface.base, iface.location) michael@0: while baseiface.name != "nsIDOMEvent": michael@0: baseinterfaces.append(baseiface) michael@0: baseiface = baseiface.idl.getName(baseiface.base, baseiface.location) michael@0: baseinterfaces.reverse() michael@0: michael@0: allattributes = [] michael@0: for baseiface in baseinterfaces: michael@0: for member in baseiface.members: michael@0: if isinstance(member, xpidl.Attribute): michael@0: allattributes.append(member) michael@0: allattributes.extend(attributes); michael@0: michael@0: fd.write("\nclass %s MOZ_FINAL : public %s, public %s\n" % (classname, basename, iface.name)) michael@0: fd.write("{\n") michael@0: fd.write("public:\n") michael@0: fd.write(" %s(mozilla::dom::EventTarget* aOwner, " % classname) michael@0: fd.write("nsPresContext* aPresContext = nullptr, mozilla::WidgetEvent* aEvent = nullptr);\n"); michael@0: fd.write(" virtual ~%s();\n\n" % classname) michael@0: fd.write(" NS_DECL_ISUPPORTS_INHERITED\n") michael@0: fd.write(" NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(%s, %s)\n" % (classname, basename)) michael@0: fd.write(" NS_FORWARD_TO_EVENT\n") michael@0: michael@0: for baseiface in baseinterfaces: michael@0: baseimpl = ("%s" % baseiface.name[6:]) michael@0: fd.write(" NS_FORWARD_%s(%s::)\n" % (baseiface.name.upper(), baseimpl)) michael@0: michael@0: fd.write(" NS_DECL_%s\n" % iface.name.upper()) michael@0: michael@0: hasVariant = False michael@0: for a in allattributes: michael@0: if a.type == "nsIVariant": michael@0: hasVariant = True michael@0: break; michael@0: fd.write(" static already_AddRefed<%s> Constructor(const GlobalObject& aGlobal, " % eventname) michael@0: if hasVariant: michael@0: fd.write("JSContext* aCx, ") michael@0: fd.write("const nsAString& aType, ") michael@0: fd.write("const %sInit& aParam, " % eventname) michael@0: fd.write("ErrorResult& aRv);\n\n") michael@0: michael@0: fd.write(" virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE\n") michael@0: fd.write(" {\n") michael@0: fd.write(" return mozilla::dom::%sBinding::Wrap(aCx, this);\n" % eventname) michael@0: fd.write(" }\n\n") michael@0: michael@0: for a in attributes: michael@0: """xpidl methods take care of string member variables!""" michael@0: firstCapName = firstCap(a.name) michael@0: cleanNativeType = a.realtype.nativeType('in').strip('* ') michael@0: if a.realtype.nativeType('in').count("nsAString"): michael@0: continue michael@0: elif a.realtype.nativeType('in').count("nsIVariant"): michael@0: fd.write(" void Get%s(JSContext* aCx, JS::MutableHandle aRetval, ErrorResult& aRv);\n\n" % firstCapName); michael@0: elif a.realtype.nativeType('in').endswith('*'): michael@0: fd.write(" already_AddRefed<%s> Get%s()\n" % (xpidl_to_native(cleanNativeType, conf), firstCapName)) michael@0: fd.write(" {\n"); michael@0: fd.write(" nsCOMPtr<%s> %s = do_QueryInterface(m%s);\n" % (xpidl_to_canonical(cleanNativeType, conf), a.name, firstCapName)) michael@0: fd.write(" return %s.forget().downcast<%s>();\n" % (a.name, xpidl_to_native(cleanNativeType, conf))) michael@0: fd.write(" }\n\n"); michael@0: else: michael@0: fd.write(" %s %s()\n" % (cleanNativeType, firstCapName)) michael@0: fd.write(" {\n"); michael@0: fd.write(" return m%s;\n" % firstCapName) michael@0: fd.write(" }\n\n"); michael@0: michael@0: fd.write(" void ") michael@0: fd.write("Init%s(" % eventname) michael@0: if hasVariant: michael@0: fd.write("JSContext* aCx, ") michael@0: fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable") michael@0: for a in allattributes: michael@0: writeNativeAttributeParams(fd, a, conf) michael@0: fd.write(", ErrorResult& aRv);\n\n") michael@0: michael@0: fd.write("protected:\n") michael@0: for a in attributes: michael@0: fd.write(" %s\n" % attributeVariableTypeAndName(a)) michael@0: fd.write("};\n") michael@0: michael@0: def collect_names_and_non_primitive_attribute_types(idl, attrnames, forwards): michael@0: for p in idl.productions: michael@0: if p.kind == 'interface' or p.kind == 'dictionary': michael@0: interfaces = [] michael@0: base = p.base michael@0: baseiface = p michael@0: while base is not None: michael@0: baseiface = baseiface.idl.getName(baseiface.base, baseiface.location) michael@0: interfaces.append(baseiface) michael@0: base = baseiface.base michael@0: michael@0: interfaces.reverse() michael@0: interfaces.append(p) michael@0: michael@0: for iface in interfaces: michael@0: collect_names_and_non_primitive_attribute_types_from_interface(iface, attrnames, forwards) michael@0: michael@0: def collect_names_and_non_primitive_attribute_types_from_interface(iface, attrnames, forwards): michael@0: for member in iface.members: michael@0: if isinstance(member, xpidl.Attribute): michael@0: if not member.name in attrnames: michael@0: attrnames.append(member.name) michael@0: if member.realtype.nativeType('in').endswith('*'): michael@0: t = member.realtype.nativeType('in').strip('* ') michael@0: if not t in forwards: michael@0: forwards.append(t) 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, conf) 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 "GeneratedEventClasses.h"\n') michael@0: fd.write('#include "xpcprivate.h"\n'); michael@0: fd.write('#include "mozilla/dom/Event.h"\n'); michael@0: fd.write('#include "mozilla/dom/EventTarget.h"\n'); michael@0: michael@0: for e in conf.simple_events: michael@0: idl = loadEventIDL(p, options.incdirs, e) michael@0: print_cpp(idl, fd, conf, e) michael@0: michael@0: def init_value(attribute): michael@0: realtype = attribute.realtype.nativeType('in') michael@0: realtype = realtype.strip(' ') michael@0: if realtype.endswith('*'): michael@0: return "nullptr" michael@0: if realtype == "bool": michael@0: return "false" michael@0: if realtype.count("nsAString"): michael@0: return "" michael@0: if realtype.count("nsACString"): michael@0: return "" michael@0: if realtype.count("JS::Value"): michael@0: raise BaseException("JS::Value not supported in simple events!") michael@0: return "0" 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 = %s();\n" % (firstCap(a.name), firstCap(a.name))) michael@0: fd.write(" return NS_OK;\n"); michael@0: fd.write("}\n\n"); michael@0: if a.realtype.nativeType('in').count("nsIVariant"): michael@0: fd.write("void\n") michael@0: fd.write("%s::Get%s(JSContext* aCx, JS::MutableHandle aRetval, ErrorResult& aRv)\n" % (classname, firstCap(a.name))) michael@0: fd.write("{\n") michael@0: fd.write(" nsresult rv = NS_ERROR_UNEXPECTED;\n") michael@0: fd.write(" if (!m%s) {\n" % firstCap(a.name)) michael@0: fd.write(" aRetval.setNull();\n") michael@0: fd.write(" } else if (!XPCVariant::VariantDataToJS(m%s, &rv, aRetval)) {\n" % (firstCap(a.name))) michael@0: fd.write(" aRv.Throw(NS_ERROR_FAILURE);\n") michael@0: fd.write(" }\n") michael@0: fd.write("}\n\n") michael@0: michael@0: def writeAttributeParams(fd, a): 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(", const nsAString& a%s" % firstCap(a.name)) michael@0: elif a.realtype.nativeType('in').count("nsACString"): michael@0: fd.write(", const 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: michael@0: def writeNativeAttributeParams(fd, a, conf): michael@0: if a.type == "nsIVariant": michael@0: fd.write(", JS::Value a%s" % firstCap(a.name)); michael@0: elif a.realtype.nativeType('in').endswith('*'): michael@0: fd.write(", %s* a%s" % (xpidl_to_native(a.realtype.nativeType('in').strip('* '), conf), firstCap(a.name))) michael@0: elif a.realtype.nativeType('in').count("nsAString"): michael@0: fd.write(", const nsAString& a%s" % firstCap(a.name)) michael@0: elif a.realtype.nativeType('in').count("nsACString"): michael@0: fd.write(", const 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: michael@0: def write_cpp(eventname, iface, fd, conf): michael@0: classname = ("%s" % eventname) michael@0: basename = getBaseName(iface) michael@0: attributes = [] michael@0: ccattributes = [] michael@0: for member in iface.members: michael@0: if isinstance(member, xpidl.Attribute): michael@0: attributes.append(member) michael@0: if (member.realtype.nativeType('in').endswith('*')): michael@0: ccattributes.append(member); michael@0: michael@0: baseinterfaces = [] michael@0: baseiface = iface.idl.getName(iface.base, iface.location) michael@0: while baseiface.name != "nsIDOMEvent": michael@0: baseinterfaces.append(baseiface) michael@0: baseiface = baseiface.idl.getName(baseiface.base, baseiface.location) michael@0: baseinterfaces.reverse() michael@0: michael@0: baseattributes = [] michael@0: for baseiface in baseinterfaces: michael@0: for member in baseiface.members: michael@0: if isinstance(member, xpidl.Attribute): michael@0: baseattributes.append(member) michael@0: michael@0: allattributes = [] michael@0: allattributes.extend(baseattributes); michael@0: allattributes.extend(attributes); michael@0: michael@0: fd.write("namespace mozilla {\n") michael@0: fd.write("namespace dom {\n\n") michael@0: michael@0: fd.write("%s::%s(mozilla::dom::EventTarget* aOwner, " % (classname, classname)) michael@0: fd.write("nsPresContext* aPresContext, mozilla::WidgetEvent* aEvent)\n"); michael@0: fd.write(": %s(aOwner, aPresContext, aEvent)" % basename) michael@0: for a in attributes: michael@0: fd.write(",\n m%s(%s)" % (firstCap(a.name), init_value(a))) michael@0: fd.write("\n{\n") michael@0: fd.write("}\n\n") michael@0: michael@0: fd.write("%s::~%s() {}\n\n" % (classname, classname)) michael@0: michael@0: fd.write("NS_IMPL_CYCLE_COLLECTION_CLASS(%s)\n" % (classname)) michael@0: fd.write("NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(%s, %s)\n" % (classname, basename)) michael@0: for c in ccattributes: michael@0: fd.write(" NS_IMPL_CYCLE_COLLECTION_UNLINK(m%s)\n" % firstCap(c.name)) michael@0: fd.write("NS_IMPL_CYCLE_COLLECTION_UNLINK_END\n\n"); michael@0: fd.write("NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(%s, %s)\n" % (classname, basename)) michael@0: for c in ccattributes: michael@0: fd.write(" NS_IMPL_CYCLE_COLLECTION_TRAVERSE(m%s)\n" % firstCap(c.name)) michael@0: fd.write("NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END\n\n"); michael@0: michael@0: fd.write("NS_IMPL_ADDREF_INHERITED(%s, %s)\n" % (classname, basename)) michael@0: fd.write("NS_IMPL_RELEASE_INHERITED(%s, %s)\n\n" % (classname, basename)) michael@0: michael@0: fd.write("NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(%s)\n" % classname) michael@0: fd.write(" NS_INTERFACE_MAP_ENTRY(nsIDOM%s)\n" % eventname) michael@0: fd.write("NS_INTERFACE_MAP_END_INHERITING(%s)\n\n" % basename) michael@0: michael@0: hasVariant = False michael@0: for a in allattributes: michael@0: if a.type == "nsIVariant": michael@0: hasVariant = True michael@0: break; michael@0: michael@0: fd.write("already_AddRefed<%s>\n" % eventname) michael@0: fd.write("%s::Constructor(const GlobalObject& aGlobal, " % eventname) michael@0: if hasVariant: michael@0: fd.write("JSContext* aCx, "); michael@0: fd.write("const nsAString& aType, ") michael@0: fd.write("const %sInit& aParam, " % eventname) michael@0: fd.write("ErrorResult& aRv)\n") michael@0: fd.write("{\n") michael@0: fd.write(" nsCOMPtr t = do_QueryInterface(aGlobal.GetAsSupports());\n") michael@0: fd.write(" nsRefPtr<%s> e = new %s(t, nullptr, nullptr);\n" % (eventname, eventname)) michael@0: fd.write(" bool trusted = e->Init(t);\n") michael@0: fd.write(" e->Init%s(" % eventname) michael@0: if hasVariant: michael@0: fd.write("aCx, "); michael@0: fd.write("aType, aParam.mBubbles, aParam.mCancelable") michael@0: for a in allattributes: michael@0: fd.write(", aParam.m%s" % firstCap(a.name)) michael@0: fd.write(", aRv);\n") michael@0: fd.write(" e->SetTrusted(trusted);\n") michael@0: fd.write(" return e.forget();\n") michael@0: fd.write("}\n\n") michael@0: michael@0: fd.write("NS_IMETHODIMP\n") michael@0: fd.write("%s::Init%s(" % (classname, eventname)) michael@0: fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable") michael@0: for a in allattributes: michael@0: writeAttributeParams(fd, a) michael@0: fd.write(")\n{\n") michael@0: fd.write(" nsresult rv = %s::Init%s(aType, aCanBubble, aCancelable" % (basename, ("%s" % iface.base[6:]))) michael@0: for a in baseattributes: michael@0: fd.write(", a%s" % firstCap(a.name)) michael@0: fd.write(");\n"); michael@0: fd.write(" NS_ENSURE_SUCCESS(rv, rv);\n") michael@0: for a in attributes: michael@0: if a.realtype.nativeType("in").count("nsAString"): michael@0: fd.write(" if (!m%s.Assign(a%s, fallible_t())) {\n" % (firstCap(a.name), firstCap(a.name))) michael@0: fd.write(" return NS_ERROR_OUT_OF_MEMORY;\n") michael@0: fd.write(" }\n") michael@0: else: michael@0: fd.write(" m%s = a%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: fd.write("void\n") michael@0: fd.write("%s::Init%s(" % (classname, eventname)) michael@0: if hasVariant: michael@0: fd.write("JSContext* aCx, ") michael@0: fd.write("const nsAString& aType, bool aCanBubble, bool aCancelable") michael@0: for a in allattributes: michael@0: writeNativeAttributeParams(fd, a, conf) michael@0: fd.write(", ErrorResult& aRv") michael@0: fd.write(")\n") michael@0: fd.write("{\n"); michael@0: for a in allattributes: michael@0: if a.type == "nsIVariant": michael@0: fd.write(" nsCOMPtr %s = dont_AddRef(XPCVariant::newVariant(aCx, a%s));\n" % (a.name, firstCap(a.name))) michael@0: fd.write(" if (!%s) {\n" % a.name) michael@0: fd.write(" aRv.Throw(NS_ERROR_FAILURE);\n") michael@0: fd.write(" return;\n") michael@0: fd.write(" }\n") michael@0: elif a.realtype.nativeType('in').endswith('*'): michael@0: xpidl_t = a.realtype.nativeType('in').strip('* ') michael@0: native_t = xpidl_to_native(xpidl_t, conf) michael@0: if xpidl_t != native_t: michael@0: fd.write(" nsCOMPtr<%s> %s = do_QueryInterface(static_cast<%s*>(a%s));\n" % (xpidl_t, a.name, xpidl_to_canonical(xpidl_t, conf), firstCap(a.name))) michael@0: fd.write(" aRv = Init%s(" % classname); michael@0: fd.write("aType, aCanBubble, aCancelable") michael@0: for a in allattributes: michael@0: if a.realtype.nativeType('in').endswith('*'): michael@0: xpidl_t = a.realtype.nativeType('in').strip('* ') michael@0: native_t = xpidl_to_native(xpidl_t, conf) michael@0: if xpidl_t != native_t or a.type == "nsIVariant": michael@0: fd.write(", %s" % a.name) michael@0: continue michael@0: fd.write(", a%s" % firstCap(a.name)) michael@0: fd.write(");\n}\n\n"); michael@0: michael@0: for a in attributes: michael@0: writeAttributeGetter(fd, classname, a) michael@0: michael@0: fd.write("} // namespace dom\n") michael@0: fd.write("} // namespace mozilla\n\n") michael@0: michael@0: fd.write("nsresult\n") michael@0: fd.write("NS_NewDOM%s(nsIDOMEvent** aInstance, " % eventname) michael@0: fd.write("mozilla::dom::EventTarget* aOwner, nsPresContext* aPresContext = nullptr, mozilla::WidgetEvent* aEvent = nullptr)\n") michael@0: fd.write("{\n") michael@0: fd.write(" mozilla::dom::%s* it = new mozilla::dom::%s(aOwner, aPresContext, aEvent);\n" % (classname, classname)) michael@0: fd.write(" NS_ADDREF(it);\n") michael@0: fd.write(" *aInstance = static_cast(it);\n") michael@0: fd.write(" return NS_OK;\n"); michael@0: fd.write("}\n\n") michael@0: michael@0: def toWebIDLType(attribute, inType=False, onlyInterface=False): michael@0: if attribute.type == "nsIVariant": michael@0: return "any"; michael@0: if attribute.type == "nsISupports": michael@0: return "%s%s" % (attribute.type, "" if onlyInterface else "?") michael@0: if attribute.type.count("nsIDOM"): michael@0: return "%s%s" % (attribute.type[6:], "" if onlyInterface else "?") michael@0: if attribute.type.count("nsI"): michael@0: return "%s%s" % (attribute.type[3:], "" if onlyInterface else "?") michael@0: if attribute.realtype.nativeType('in').endswith('*') or attribute.realtype.nativeType('in').count("nsAString"): michael@0: return "%s%s" % (attribute.type, "" if onlyInterface else "?") michael@0: return attribute.type michael@0: michael@0: def write_webidl(eventname, iface, fd, conf, idl): michael@0: basename = ("%s" % iface.base[6:]) michael@0: attributes = [] michael@0: ccattributes = [] michael@0: consts = [] michael@0: hasInit = False michael@0: initMethod = "init%s" % eventname; michael@0: for member in iface.members: michael@0: if isinstance(member, xpidl.Attribute): michael@0: attributes.append(member) michael@0: if (member.realtype.nativeType('in').endswith('*')): michael@0: ccattributes.append(member); michael@0: elif isinstance(member, xpidl.Method) and member.name == initMethod: michael@0: if not member.noscript and not member.notxpcom: michael@0: hasInit = True michael@0: elif isinstance(member, xpidl.ConstMember): michael@0: consts.append(member); michael@0: else: michael@0: raise BaseException("Unsupported idl member %s::%s" % (eventname, member.name)) michael@0: michael@0: baseinterfaces = [] michael@0: baseiface = iface.idl.getName(iface.base, iface.location) michael@0: while baseiface.name != "nsIDOMEvent": michael@0: baseinterfaces.append(baseiface) michael@0: baseiface = baseiface.idl.getName(baseiface.base, baseiface.location) michael@0: baseinterfaces.reverse() michael@0: michael@0: allattributes = [] michael@0: for baseiface in baseinterfaces: michael@0: for member in baseiface.members: michael@0: if isinstance(member, xpidl.Attribute): michael@0: allattributes.append(member) michael@0: allattributes.extend(attributes) michael@0: michael@0: fd.write( michael@0: """/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 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 file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: */ michael@0: """) michael@0: michael@0: neededInterfaces = [] michael@0: for a in attributes: michael@0: if a.realtype.nativeType('in').endswith('*'): michael@0: nativeType = a.realtype.nativeType('in').strip('* ') michael@0: mappingForWebIDL = False michael@0: for xp in conf.xpidl_to_native: michael@0: if xp[0] == nativeType: michael@0: mappingForWebIDL = True michael@0: break; michael@0: if not mappingForWebIDL: michael@0: webidlType = toWebIDLType(a, False, True) michael@0: if (not webidlType in neededInterfaces and webidlType != "any"): michael@0: neededInterfaces.append(webidlType); michael@0: michael@0: for i in neededInterfaces: michael@0: fd.write("interface %s;\n" % i) michael@0: michael@0: fd.write("\n"); michael@0: fd.write("[Constructor(DOMString type, optional %sInit eventInitDict), HeaderFile=\"GeneratedEventClasses.h\"]\n" % eventname); michael@0: fd.write("interface %s : %s\n" % (eventname, basename)) michael@0: fd.write("{\n") michael@0: michael@0: for c in consts: michael@0: fd.write(" const %s %s = %s;\n" % (c.type, c.name, c.getValue())) michael@0: if len(consts): michael@0: fd.write("\n") michael@0: michael@0: for a in attributes: michael@0: if a.realtype.nativeType('in').count("nsIVariant"): michael@0: fd.write(" [Throws]\n") michael@0: fd.write(" readonly attribute %s %s;\n" % (toWebIDLType(a), a.name)) michael@0: elif a.realtype.nativeType('in').endswith('*') or a.realtype.nativeType('in').count("nsAString"): michael@0: fd.write(" readonly attribute %s %s;\n" % (toWebIDLType(a), a.name)) michael@0: else: michael@0: fd.write(" readonly attribute %s %s;\n" % (a.type, a.name)) michael@0: if hasInit: michael@0: fd.write("\n [Throws]\n") michael@0: m = " void %s(" % initMethod michael@0: fd.write(m) michael@0: indent = "".join(" " for i in range(len(m))) michael@0: indent = ",\n%s" % indent michael@0: fd.write("DOMString type") michael@0: fd.write(indent); michael@0: fd.write("boolean canBubble") michael@0: fd.write(indent); michael@0: fd.write("boolean cancelable") michael@0: for a in baseattributes + attributes: michael@0: fd.write(indent); michael@0: fd.write("%s %s" % (toWebIDLType(a, True), a.name)) michael@0: fd.write(");\n"); michael@0: fd.write("};\n\n") michael@0: michael@0: dname = "%sInit" % eventname michael@0: for p in idl.productions: michael@0: if p.kind == "dictionary" and p.name == dname: michael@0: fd.write("dictionary %s : %sInit\n" % (dname, basename)) michael@0: fd.write("{\n") michael@0: # We want to keep the same ordering what interface has. michael@0: for ifaceattribute in attributes: michael@0: for member in p.members: michael@0: if member.name == ifaceattribute.name: michael@0: a = member michael@0: if a.realtype.nativeType('in').endswith('*'): michael@0: fd.write(" %s %s = null;\n" % (toWebIDLType(a, True), a.name)) michael@0: elif a.realtype.nativeType('in').count("nsAString"): michael@0: if a.defvalue is None: michael@0: if a.nullable: michael@0: fd.write(" %s? %s = null;\n" % (a.type, a.name)) michael@0: else: michael@0: fd.write(" %s %s = \"\";\n" % (a.type, a.name)) michael@0: else: michael@0: if a.nullable: michael@0: fd.write(" %s? %s = \"%s\";\n" % (a.type, a.name, a.defvalue)) michael@0: else: michael@0: fd.write(" %s %s = \"%s\";\n" % (a.type, a.name, a.defvalue)) michael@0: else: michael@0: if a.defvalue is None: michael@0: if a.type == "boolean": michael@0: fd.write(" %s %s = false;\n" % (a.type, a.name)) michael@0: else: michael@0: fd.write(" %s %s = 0;\n" % (a.type, a.name)) michael@0: # Infinity is not supported by all the types, but michael@0: # WebIDL parser will then complain about the wrong values. michael@0: elif a.defvalue == "Infinity": michael@0: fd.write(" unrestricted %s %s = Infinity;\n" % (a.type, a.name)) michael@0: elif a.defvalue == "-Infinity": michael@0: fd.write(" unrestricted %s %s = -Infinity;\n" % (a.type, a.name)) michael@0: else: michael@0: fd.write(" %s %s = %s;\n" % (a.type, a.name, a.defvalue)) michael@0: continue michael@0: fd.write("};\n") michael@0: return michael@0: michael@0: # There is no dictionary defined in the .idl file. Generate one based on michael@0: # the interface. michael@0: fd.write("dictionary %s : %sInit\n" % (dname, basename)) michael@0: fd.write("{\n") michael@0: for a in attributes: michael@0: if a.realtype.nativeType('in').endswith('*'): michael@0: fd.write(" %s %s = null;\n" % (toWebIDLType(a, True), a.name)) michael@0: elif a.realtype.nativeType('in').count("nsAString"): michael@0: fd.write(" %s? %s = \"\";\n" % (a.type, a.name)) michael@0: elif a.type == "boolean": michael@0: fd.write(" %s %s = false;\n" % (a.type, a.name)) michael@0: else: michael@0: fd.write(" %s %s = 0;\n" % (a.type, a.name)) michael@0: fd.write("};\n") michael@0: michael@0: def print_webidl_file(idl, fd, conf, eventname): michael@0: for p in idl.productions: michael@0: if p.kind == 'interface': michael@0: write_webidl(eventname, p, fd, conf, idl) michael@0: michael@0: def xpidl_to_native(xpidl, conf): michael@0: for x in conf.xpidl_to_native: michael@0: if x[0] == xpidl: michael@0: return x[1] michael@0: return xpidl michael@0: michael@0: def xpidl_to_canonical(xpidl, conf): michael@0: for x in conf.xpidl_to_native: michael@0: if x[0] == xpidl: michael@0: return x[2] michael@0: return xpidl michael@0: michael@0: def native_to_xpidl(native, conf): michael@0: for x in conf.xpidl_to_native: michael@0: if x[1] == native: michael@0: return x[0] michael@0: return native michael@0: michael@0: def print_webidl_files(webidlDir, conf): michael@0: for e in conf.simple_events: michael@0: idl = loadEventIDL(p, options.incdirs, e) michael@0: webidl = "%s/%s.webidl" % (webidlDir, e) michael@0: if not os.path.exists(webidl): michael@0: fd = open(webidl, 'w') michael@0: print_webidl_file(idl, fd, conf, e) michael@0: fd.close(); michael@0: michael@0: if __name__ == '__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="Quick stub 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: o.add_option('--class-declarations', type='string', default=None, michael@0: help="Class declarations", metavar="FILE") michael@0: o.add_option('--webidltarget', dest='webidltarget', default=None, michael@0: help="Directory in which to store generated WebIDL files.") 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: p = xpidl.IDLParser(outputdir=options.cachedir) michael@0: michael@0: conf = readConfigFile(filename) michael@0: 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: if options.class_declarations is not None: michael@0: outfd = open(options.class_declarations, 'w') michael@0: print_classes_file(outfd, conf) michael@0: outfd.close() 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: michael@0: if options.webidltarget is not None: michael@0: print_webidl_files(options.webidltarget, conf) michael@0: