1# This Source Code Form is subject to the terms of the Mozilla Public 2# License, v. 2.0. If a copy of the MPL was not distributed with this file, 3# You can obtain one at http://mozilla.org/MPL/2.0/. 4 5import sys 6import string 7import argparse 8import subprocess 9import buildconfig 10from mozbuild import shellutil 11 12def get_properties(preprocessorHeader): 13 cpp = list(buildconfig.substs['CPP']) 14 cpp += shellutil.split(buildconfig.substs['ACDEFINES']) 15 cpp.append(preprocessorHeader) 16 preprocessed = subprocess.check_output(cpp) 17 properties = [{"name":p[0], "prop":p[1], "id":p[2], 18 "flags":p[3], "pref":p[4], "proptype":p[5]} 19 for (i, p) in enumerate(eval(preprocessed))] 20 21 # Sort the list so that longhand and logical properties are intermingled 22 # first, shorthand properties follow, then aliases appear last. This matches 23 # the order of the nsCSSPropertyID enum. 24 25 def property_compare(x, y): 26 property_order = {"longhand": 0, "logical": 0, "shorthand": 1, "alias": 2} 27 return property_order[x["proptype"]] - property_order[y["proptype"]] 28 29 properties = sorted(properties, cmp=property_compare) 30 31 for i, p in enumerate(properties): 32 p["index"] = i 33 34 # Record each property's IDL name. 35 for p in properties: 36 if "CSS_PROPERTY_INTERNAL" in p["flags"]: 37 p["idlname"] = None 38 else: 39 idl_name = p["prop"] 40 if not idl_name.startswith("Moz"): 41 idl_name = idl_name[0].lower() + idl_name[1:] 42 p["idlname"] = idl_name 43 44 return properties 45 46def generate_idl_names(properties): 47 names = [] 48 for p in properties: 49 if p["proptype"] is "alias": 50 continue 51 if p["idlname"] is None: 52 names.append(" nullptr, // %s" % p["name"]) 53 else: 54 names.append(' "%s",' % p["idlname"]) 55 return "\n".join(names) 56 57def generate_assertions(properties): 58 def enum(p): 59 if p["proptype"] is "alias": 60 return "eCSSPropertyAlias_%s" % p["prop"] 61 else: 62 return "eCSSProperty_%s" % p["id"] 63 msg = ('static_assert(%s == %d, "GenerateCSSPropsGenerated.py did not list ' 64 'properties in nsCSSPropertyID order");') 65 return "\n".join(map(lambda p: msg % (enum(p), p["index"]), properties)) 66 67def generate_idl_name_positions(properties): 68 # Skip aliases. 69 ps = filter(lambda p: p["proptype"] is not "alias", properties) 70 71 # Sort alphabetically by IDL name. 72 ps = sorted(ps, key=lambda p: p["idlname"]) 73 74 # Annotate entries with the sorted position. 75 ps = [(p, position) for position, p in enumerate(ps)] 76 77 # Sort back to nsCSSPropertyID order. 78 ps = sorted(ps, key=lambda (p, position): p["index"]) 79 80 return ",\n".join(map(lambda (p, position): " %d" % position, ps)) 81 82def generate(output, cppTemplate, preprocessorHeader): 83 cppFile = open(cppTemplate, "r") 84 cppTemplate = cppFile.read() 85 cppFile.close() 86 87 properties = get_properties(preprocessorHeader) 88 substitutions = { 89 "idl_names": generate_idl_names(properties), 90 "assertions": generate_assertions(properties), 91 "idl_name_positions": generate_idl_name_positions(properties), 92 } 93 output.write("/* THIS IS AN AUTOGENERATED FILE. DO NOT EDIT */\n\n" + 94 string.Template(cppTemplate).substitute(substitutions) + "\n") 95 96def main(): 97 parser = argparse.ArgumentParser() 98 parser.add_argument('cppTemplate', help='CSS property file template') 99 parser.add_argument('preprocessorHeader', help='Header file to pass through the preprocessor') 100 args = parser.parse_args() 101 generate(sys.stdout, args.cppTemplate, args.preprocessorHeader) 102 103if __name__ == '__main__': 104 main() 105