Index: build/android/gyp/enum_preprocess.py |
diff --git a/build/android/gyp/enum_preprocess.py b/build/android/gyp/enum_preprocess.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..7f293e1ef202fe8a2e7adfbfb505454663d11d29 |
--- /dev/null |
+++ b/build/android/gyp/enum_preprocess.py |
@@ -0,0 +1,143 @@ |
+#!/usr/bin/env python |
+# |
+# Copyright 2013 The Chromium Authors. All rights reserved. |
Yaron
2014/08/20 05:52:02
2014
mkosiba (inactive)
2014/09/02 16:00:57
Done.
|
+# Use of this source code is governed by a BSD-style license that can be |
Yaron
2014/08/20 05:52:02
Please add tests.
mkosiba (inactive)
2014/09/02 16:00:57
Done.
|
+# found in the LICENSE file. |
+ |
+import collections |
+import re |
+import optparse |
+import os |
+from string import Template |
+import sys |
+ |
+from util import build_utils |
+ |
+def GetScriptName(): |
+ script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) |
+ build_index = script_components.index('build') |
+ return os.sep.join(script_components[build_index:]) |
+ |
+def DoGenerate(options, path): |
+ enum_entries = DoParseHeaderFile(path) |
+ build_utils.MakeDirectory(os.path.dirname(options.output)) |
+ DoWriteOutput(options, enum_entries) |
+ |
+def DoParseHeaderFile(path): |
+ with open(path) as f: |
+ lines = f.readlines() |
+ |
+ single_line_comment_re = re.compile(r'\s*//') |
+ multi_line_comment_start_re = re.compile(r'\s*/\*') |
+ enum_start_re = re.compile(r'^\s*enum\s+(\w+)\s+{\s*$') |
+ enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,]+))?,\s*$') |
+ enum_end_re = re.compile(r'^\s*}\s*;\s*$') |
+ |
+ in_enum = False |
+ enum_name = None |
+ enum_entries = collections.OrderedDict() |
+ |
+ for line in lines: |
+ if not in_enum: |
+ enum_start = enum_start_re.match(line) |
+ if enum_start: |
+ if enum_name: |
+ raise Exception('Only one enum per header file is supported.') |
Yaron
2014/08/20 05:52:02
Are there really no examples of this?
mkosiba (inactive)
2014/09/02 16:00:57
Done.
|
+ enum_name = enum_start.groups()[0] |
+ in_enum = True |
+ else: |
+ |
+ if single_line_comment_re.match(line): |
+ continue |
+ if multi_line_comment_start_re.match(line): |
+ raise Exception('Multi-line comments are not supported.') |
+ enum_end = enum_end_re.match(line) |
+ enum_entry = enum_line_re.match(line) |
+ if enum_end: |
+ in_enum = False |
+ if enum_entry: |
+ enum_key = enum_entry.groups()[0] |
+ enum_value = enum_entry.groups()[2] |
+ if enum_key in enum_entries: |
+ raise Exception('Multiple definitions of key %s found.' % enum_key) |
+ enum_entries[enum_key] = enum_value |
+ |
+ all_entries_assigned = all(enum_entries.values()) |
+ any_entries_assigned = any(enum_entries.values()) |
+ if any_entries_assigned and not all_entries_assigned: |
+ raise Exception('You either need to assign a value to all or none of the ' |
+ 'enum values.') |
+ |
+ if not any_entries_assigned: |
+ index = 0 |
+ for key in enum_entries.iterkeys(): |
+ enum_entries[key] = index |
+ index = index + 1 |
+ |
+ return enum_entries |
+ |
+ |
+def DoWriteOutput(options, enum_entries): |
+ template = Template(""" |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+// This file is autogenerated by |
+// ${SCRIPT_NAME} |
+// For |
+// ${PACKAGE}.${CLASS_NAME} |
+ |
+package ${PACKAGE}; |
+ |
+public class ${CLASS_NAME} { |
+${ENUM_ENTRIES} |
+} |
+""") |
+ |
+ enum_template = Template(" public final int ${NAME} = ${VALUE},") |
+ enum_entries_string = [] |
+ for enum_name, enum_value in enum_entries.iteritems(): |
+ values = { |
+ 'NAME': enum_name, |
+ 'VALUE': enum_value, |
+ } |
+ enum_entries_string.append(enum_template.substitute(values)) |
+ enum_entries_string = "\n".join(enum_entries_string) |
+ |
+ values = { |
+ 'SCRIPT_NAME': GetScriptName(), |
+ 'PACKAGE': options.package.replace('/', '.'), |
+ 'CLASS_NAME': options.class_name, |
+ 'ENUM_ENTRIES': enum_entries_string, |
+ } |
+ |
+ with open(options.output, "w") as out_file: |
+ out_file.write(template.substitute(values)) |
+ |
+ |
+def main(): |
+ parser = optparse.OptionParser() |
+ build_utils.AddDepfileOption(parser) |
+ |
+ parser.add_option('--output', help='Path for generated file.') |
+ parser.add_option('--package', help='Package name.') |
+ parser.add_option('--class_name', help='Class name.') |
+ parser.add_option('--stamp', help='Path to touch on success.') |
+ parser.add_option('--defines', help='Pre-defines macros', action='append') |
+ |
+ options, args = parser.parse_args() |
+ |
+ DoGenerate(options, args[0]) |
+ |
+ if options.depfile: |
+ build_utils.WriteDepfile( |
+ options.depfile, |
+ build_utils.GetPythonDependencies()) |
+ |
+ if options.stamp: |
Yaron
2014/08/20 05:52:02
We have a definite output file. Why is a stamp nec
mkosiba (inactive)
2014/09/02 16:00:57
Done.
|
+ build_utils.Touch(options.stamp) |
+ |
+ |
+if __name__ == '__main__': |
+ sys.exit(main()) |