| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (C) 2013 Google Inc. All rights reserved. | 2 # Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 # | 3 # |
| 4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
| 5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
| 6 # met: | 6 # met: |
| 7 # | 7 # |
| 8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
| 9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
| 10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 | 29 |
| 30 import os.path | 30 import os.path |
| 31 import sys | 31 import sys |
| 32 import shutil | |
| 33 | 32 |
| 34 from in_file import InFile | 33 from in_file import InFile |
| 34 import in_generator |
| 35 import license | 35 import license |
| 36 | 36 |
| 37 | 37 |
| 38 HEADER_TEMPLATE = """%(license)s | 38 HEADER_TEMPLATE = """%(license)s |
| 39 #ifndef %(class_name)s_h | 39 #ifndef %(class_name)s_h |
| 40 #define %(class_name)s_h | 40 #define %(class_name)s_h |
| 41 | 41 |
| 42 namespace WebCore { | 42 namespace WebCore { |
| 43 | 43 |
| 44 // A class that stores static enablers for all experimental features. | 44 // A class that stores static enablers for all experimental features. |
| (...skipping 16 matching lines...) Expand all Loading... |
| 61 #include "config.h" | 61 #include "config.h" |
| 62 #include "RuntimeEnabledFeatures.h" | 62 #include "RuntimeEnabledFeatures.h" |
| 63 | 63 |
| 64 namespace WebCore { | 64 namespace WebCore { |
| 65 | 65 |
| 66 %(storage_definitions)s | 66 %(storage_definitions)s |
| 67 | 67 |
| 68 } // namespace WebCore | 68 } // namespace WebCore |
| 69 """ | 69 """ |
| 70 | 70 |
| 71 class RuntimeFeatureWriter(object): | 71 class RuntimeFeatureWriter(in_generator.Writer): |
| 72 defaults = { |
| 73 'condition' : None, |
| 74 'depends_on' : [], |
| 75 'default': 'false', |
| 76 'custom': False, |
| 77 } |
| 78 |
| 72 def __init__(self, in_file_path): | 79 def __init__(self, in_file_path): |
| 80 super(RuntimeFeatureWriter, self).__init__(in_file_path) |
| 81 |
| 73 # Assume that the class should be called the same as the file. | 82 # Assume that the class should be called the same as the file. |
| 74 self.class_name, _ = os.path.splitext(os.path.basename(in_file_path)) | 83 self.class_name, _ = os.path.splitext(os.path.basename(in_file_path)) |
| 75 defaults = { | 84 self._all_features = self.in_file.name_dictionaries |
| 76 'condition' : None, | |
| 77 'depends_on' : [], | |
| 78 'default': 'false', | |
| 79 'custom': False, | |
| 80 } | |
| 81 self._all_features = InFile.load_from_path(in_file_path, defaults).name_
dictionaries | |
| 82 # Make sure the resulting dictionaries have all the keys we expect. | 85 # Make sure the resulting dictionaries have all the keys we expect. |
| 83 for feature in self._all_features: | 86 for feature in self._all_features: |
| 84 feature['first_lowered_name'] = self._lower_first(feature['name']) | 87 feature['first_lowered_name'] = self._lower_first(feature['name']) |
| 85 # Most features just check their isFooEnabled bool | 88 # Most features just check their isFooEnabled bool |
| 86 # but some depend on more than one bool. | 89 # but some depend on more than one bool. |
| 87 enabled_condition = "is%sEnabled" % feature['name'] | 90 enabled_condition = "is%sEnabled" % feature['name'] |
| 88 for dependant_name in feature['depends_on']: | 91 for dependant_name in feature['depends_on']: |
| 89 enabled_condition += " && is%sEnabled" % dependant_name | 92 enabled_condition += " && is%sEnabled" % dependant_name |
| 90 feature['enabled_condition'] = enabled_condition | 93 feature['enabled_condition'] = enabled_condition |
| 91 self._non_custom_features = filter(lambda feature: not feature['custom']
, self._all_features) | 94 self._non_custom_features = filter(lambda feature: not feature['custom']
, self._all_features) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 112 static bool %(first_lowered_name)sEnabled() { return false; } | 115 static bool %(first_lowered_name)sEnabled() { return false; } |
| 113 #endif | 116 #endif |
| 114 """ | 117 """ |
| 115 template = conditional if feature['condition'] else unconditional | 118 template = conditional if feature['condition'] else unconditional |
| 116 return template % feature | 119 return template % feature |
| 117 | 120 |
| 118 def _storage_declarations(self, feature): | 121 def _storage_declarations(self, feature): |
| 119 declaration = " static bool is%(name)sEnabled;" % feature | 122 declaration = " static bool is%(name)sEnabled;" % feature |
| 120 return self._wrap_with_condition(declaration, feature['condition']) | 123 return self._wrap_with_condition(declaration, feature['condition']) |
| 121 | 124 |
| 122 def _generate_header(self): | 125 def generate_header(self): |
| 123 return HEADER_TEMPLATE % { | 126 return HEADER_TEMPLATE % { |
| 124 'class_name' : self.class_name, | 127 'class_name' : self.class_name, |
| 125 'license' : license.license_for_generated_cpp(), | 128 'license' : license.license_for_generated_cpp(), |
| 126 'method_declarations' : "\n".join(map(self._method_declaration, self
._all_features)), | 129 'method_declarations' : "\n".join(map(self._method_declaration, self
._all_features)), |
| 127 'storage_declarations' : "\n".join(map(self._storage_declarations, s
elf._non_custom_features)), | 130 'storage_declarations' : "\n".join(map(self._storage_declarations, s
elf._non_custom_features)), |
| 128 } | 131 } |
| 129 | 132 |
| 130 def _storage_definition(self, feature): | 133 def _storage_definition(self, feature): |
| 131 definition = "bool RuntimeEnabledFeatures::is%(name)sEnabled = %(default
)s;" % feature | 134 definition = "bool RuntimeEnabledFeatures::is%(name)sEnabled = %(default
)s;" % feature |
| 132 return self._wrap_with_condition(definition, feature['condition']) | 135 return self._wrap_with_condition(definition, feature['condition']) |
| 133 | 136 |
| 134 def _generate_implementation(self): | 137 def generate_implementation(self): |
| 135 return IMPLEMENTATION_TEMPLATE % { | 138 return IMPLEMENTATION_TEMPLATE % { |
| 136 'class_name' : self.class_name, | 139 'class_name' : self.class_name, |
| 137 'license' : license.license_for_generated_cpp(), | 140 'license' : license.license_for_generated_cpp(), |
| 138 'storage_definitions' : "\n".join(map(self._storage_definition, self
._non_custom_features)), | 141 'storage_definitions' : "\n".join(map(self._storage_definition, self
._non_custom_features)), |
| 139 } | 142 } |
| 140 | 143 |
| 141 def _forcibly_create_text_file_at_path_with_contents(self, file_path, conten
ts): | |
| 142 # FIXME: This method can be made less force-full anytime after 6/1/2013. | |
| 143 # A gyp error was briefly checked into the tree, causing | |
| 144 # a directory to have been generated in place of one of | |
| 145 # our output files. Clean up after that error so that | |
| 146 # all users don't need to clobber their output directories. | |
| 147 shutil.rmtree(file_path, ignore_errors=True) | |
| 148 # The build system should ensure our output directory exists, but just i
n case. | |
| 149 directory = os.path.dirname(file_path) | |
| 150 if not os.path.exists(directory): | |
| 151 os.makedirs(directory) | |
| 152 | |
| 153 with open(file_path, "w") as file_to_write: | |
| 154 file_to_write.write(contents) | |
| 155 | |
| 156 def write_header(self, output_dir): | |
| 157 header_path = os.path.join(output_dir, self.class_name + ".h") | |
| 158 self._forcibly_create_text_file_at_path_with_contents(header_path, self.
_generate_header()) | |
| 159 | |
| 160 def write_implmentation(self, output_dir): | |
| 161 implmentation_path = os.path.join(output_dir, self.class_name + ".cpp") | |
| 162 self._forcibly_create_text_file_at_path_with_contents(implmentation_path
, self._generate_implementation()) | |
| 163 | |
| 164 | |
| 165 class MakeRuntimeFeatures(object): | |
| 166 def main(self, argv): | |
| 167 script_name = os.path.basename(argv[0]) | |
| 168 args = argv[1:] | |
| 169 if len(args) < 1: | |
| 170 print "USAGE: %i INPUT_FILE [OUTPUT_DIRECTORY]" % script_name | |
| 171 exit(1) | |
| 172 output_dir = args[1] if len(args) > 1 else os.getcwd() | |
| 173 | |
| 174 writer = RuntimeFeatureWriter(args[0]) | |
| 175 writer.write_header(output_dir) | |
| 176 writer.write_implmentation(output_dir) | |
| 177 | |
| 178 | 144 |
| 179 if __name__ == "__main__": | 145 if __name__ == "__main__": |
| 180 MakeRuntimeFeatures().main(sys.argv) | 146 in_generator.Maker(RuntimeFeatureWriter).main(sys.argv) |
| OLD | NEW |