Chromium Code Reviews| 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()) |