# 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 string import argparse import subprocess import buildconfig from mozbuild import shellutil def get_properties(preprocessorHeader): cpp = list(buildconfig.substs['CPP']) cpp += shellutil.split(buildconfig.substs['ACDEFINES']) cpp.append(preprocessorHeader) preprocessed = subprocess.check_output(cpp) properties = [{"name":p[0], "prop":p[1], "id":p[2], "flags":p[3], "pref":p[4], "proptype":p[5]} for (i, p) in enumerate(eval(preprocessed))] # Sort the list so that longhand and logical properties are intermingled # first, shorthand properties follow, then aliases appear last. This matches # the order of the nsCSSPropertyID enum. def property_compare(x, y): property_order = {"longhand": 0, "logical": 0, "shorthand": 1, "alias": 2} return property_order[x["proptype"]] - property_order[y["proptype"]] properties = sorted(properties, cmp=property_compare) for i, p in enumerate(properties): p["index"] = i # Record each property's IDL name. for p in properties: if "CSS_PROPERTY_INTERNAL" in p["flags"]: p["idlname"] = None else: idl_name = p["prop"] if not idl_name.startswith("Moz"): idl_name = idl_name[0].lower() + idl_name[1:] p["idlname"] = idl_name return properties def generate_idl_names(properties): names = [] for p in properties: if p["proptype"] is "alias": continue if p["idlname"] is None: names.append(" nullptr, // %s" % p["name"]) else: names.append(' "%s",' % p["idlname"]) return "\n".join(names) def generate_assertions(properties): def enum(p): if p["proptype"] is "alias": return "eCSSPropertyAlias_%s" % p["prop"] else: return "eCSSProperty_%s" % p["id"] msg = ('static_assert(%s == %d, "GenerateCSSPropsGenerated.py did not list ' 'properties in nsCSSPropertyID order");') return "\n".join(map(lambda p: msg % (enum(p), p["index"]), properties)) def generate_idl_name_positions(properties): # Skip aliases. ps = filter(lambda p: p["proptype"] is not "alias", properties) # Sort alphabetically by IDL name. ps = sorted(ps, key=lambda p: p["idlname"]) # Annotate entries with the sorted position. ps = [(p, position) for position, p in enumerate(ps)] # Sort back to nsCSSPropertyID order. ps = sorted(ps, key=lambda (p, position): p["index"]) return ",\n".join(map(lambda (p, position): " %d" % position, ps)) def generate(output, cppTemplate, preprocessorHeader): cppFile = open(cppTemplate, "r") cppTemplate = cppFile.read() cppFile.close() properties = get_properties(preprocessorHeader) substitutions = { "idl_names": generate_idl_names(properties), "assertions": generate_assertions(properties), "idl_name_positions": generate_idl_name_positions(properties), } output.write("/* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT */\n\n" + string.Template(cppTemplate).substitute(substitutions) + "\n") def main(): parser = argparse.ArgumentParser() parser.add_argument('cppTemplate', help='CSS property file template') parser.add_argument('preprocessorHeader', help='Header file to pass through the preprocessor') args = parser.parse_args() generate(sys.stdout, args.cppTemplate, args.preprocessorHeader) if __name__ == '__main__': main()