# 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 argparse import os import re import sys import mozpack.path as mozpath from buildconfig import topobjdir, topsrcdir from mozbuild.backend.configenvironment import PartialConfigEnvironment def process_define_file(output, input): """Creates the given config header. A config header is generated by taking the corresponding source file and replacing some *#define/#undef* occurences: - "#undef NAME" is turned into "#define NAME VALUE" - "#define NAME" is unchanged - "#define NAME ORIGINAL_VALUE" is turned into "#define NAME VALUE" - "#undef UNKNOWN_NAME" is turned into "/* #undef UNKNOWN_NAME */" - Whitespaces are preserved. As a special rule, "#undef ALLDEFINES" is turned into "#define NAME VALUE" for all the defined variables. """ path = os.path.abspath(input) config = PartialConfigEnvironment(topobjdir) if mozpath.basedir( path, [mozpath.join(topsrcdir, "js/src")] ) and not config.substs.get("JS_STANDALONE"): config = PartialConfigEnvironment(mozpath.join(topobjdir, "js", "src")) with open(path, "r") as input: r = re.compile( "^\s*#\s*(?P[a-z]+)(?:\s+(?P\S+)(?:\s+(?P\S+))?)?", re.U ) for l in input: m = r.match(l) if m: cmd = m.group("cmd") name = m.group("name") value = m.group("value") if name: if name == "ALLDEFINES": if cmd == "define": raise Exception( "`#define ALLDEFINES` is not allowed in a " "CONFIGURE_DEFINE_FILE" ) def define_for_name(name, val): """WebRTC files like to define WINVER and _WIN32_WINNT via the command line, which raises a mass of macro redefinition warnings. Just handle those macros specially here.""" define = "#define {name} {val}".format(name=name, val=val) if name in ("_WIN32_IE", "_WIN32_WINNT", "WIN32", "WINVER"): return "#if !defined({name})\n{define}\n#endif".format( name=name, define=define ) return define defines = "\n".join( sorted( define_for_name(name, val) for name, val in config.defines["ALLDEFINES"].items() ) ) l = l[: m.start("cmd") - 1] + defines + l[m.end("name") :] elif cmd == "define": if value and name in config.defines: l = ( l[: m.start("value")] + str(config.defines[name]) + l[m.end("value") :] ) elif cmd == "undef": if name in config.defines: l = ( l[: m.start("cmd")] + "define" + l[m.end("cmd") : m.end("name")] + " " + str(config.defines[name]) + l[m.end("name") :] ) else: l = "/* " + l[: m.end("name")] + " */" + l[m.end("name") :] output.write(l) deps = {path} deps.update(config.get_dependencies()) return deps def main(argv): parser = argparse.ArgumentParser(description="Process define files.") parser.add_argument("input", help="Input define file.") args = parser.parse_args(argv) return process_define_file(sys.stdout, args.input) if __name__ == "__main__": sys.exit(main(sys.argv[1:]))