GenerateCSSPropsGenerated.py 3.7 KB

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