OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2014 The Chromium Authors. All rights reserved. | 3 # Copyright 2014 The Chromium Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 import collections | 7 import collections |
8 import re | 8 import re |
9 import optparse | 9 import optparse |
10 import os | 10 import os |
11 from string import Template | 11 from string import Template |
12 import sys | 12 import sys |
13 | 13 |
14 from util import build_utils | 14 from util import build_utils |
15 | 15 |
| 16 # List of C++ types that are compatible with the Java code generated by this |
| 17 # script. |
| 18 ENUM_FIXED_TYPE_WHITELIST = ['char', 'unsigned char', |
| 19 'short', 'unsigned short', |
| 20 'int', 'int8_t', 'int16_t', 'int32_t', 'uint8_t', 'uint16_t'] |
| 21 |
16 class EnumDefinition(object): | 22 class EnumDefinition(object): |
17 def __init__(self, original_enum_name=None, class_name_override=None, | 23 def __init__(self, original_enum_name=None, class_name_override=None, |
18 enum_package=None, entries=None): | 24 enum_package=None, entries=None, fixed_type=None): |
19 self.original_enum_name = original_enum_name | 25 self.original_enum_name = original_enum_name |
20 self.class_name_override = class_name_override | 26 self.class_name_override = class_name_override |
21 self.enum_package = enum_package | 27 self.enum_package = enum_package |
22 self.entries = collections.OrderedDict(entries or []) | 28 self.entries = collections.OrderedDict(entries or []) |
23 self.prefix_to_strip = None | 29 self.prefix_to_strip = None |
| 30 self.fixed_type = fixed_type |
24 | 31 |
25 def AppendEntry(self, key, value): | 32 def AppendEntry(self, key, value): |
26 if key in self.entries: | 33 if key in self.entries: |
27 raise Exception('Multiple definitions of key %s found.' % key) | 34 raise Exception('Multiple definitions of key %s found.' % key) |
28 self.entries[key] = value | 35 self.entries[key] = value |
29 | 36 |
30 @property | 37 @property |
31 def class_name(self): | 38 def class_name(self): |
32 return self.class_name_override or self.original_enum_name | 39 return self.class_name_override or self.original_enum_name |
33 | 40 |
34 def Finalize(self): | 41 def Finalize(self): |
35 self._Validate() | 42 self._Validate() |
36 self._AssignEntryIndices() | 43 self._AssignEntryIndices() |
37 self._StripPrefix() | 44 self._StripPrefix() |
38 | 45 |
39 def _Validate(self): | 46 def _Validate(self): |
40 assert self.class_name | 47 assert self.class_name |
41 assert self.enum_package | 48 assert self.enum_package |
42 assert self.entries | 49 assert self.entries |
| 50 if self.fixed_type and self.fixed_type not in ENUM_FIXED_TYPE_WHITELIST: |
| 51 raise Exception('Fixed type %s for enum %s not whitelisted.' % |
| 52 (self.fixed_type, self.class_name)) |
43 | 53 |
44 def _AssignEntryIndices(self): | 54 def _AssignEntryIndices(self): |
45 # Enums, if given no value, are given the value of the previous enum + 1. | 55 # Enums, if given no value, are given the value of the previous enum + 1. |
46 if not all(self.entries.values()): | 56 if not all(self.entries.values()): |
47 prev_enum_value = -1 | 57 prev_enum_value = -1 |
48 for key, value in self.entries.iteritems(): | 58 for key, value in self.entries.iteritems(): |
49 if not value: | 59 if not value: |
50 self.entries[key] = prev_enum_value + 1 | 60 self.entries[key] = prev_enum_value + 1 |
51 elif value in self.entries: | 61 elif value in self.entries: |
52 self.entries[key] = self.entries[value] | 62 self.entries[key] = self.entries[value] |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 DirectiveSet.class_name_override_key, '') | 113 DirectiveSet.class_name_override_key, '') |
104 definition.enum_package = self._directives.get( | 114 definition.enum_package = self._directives.get( |
105 DirectiveSet.enum_package_key) | 115 DirectiveSet.enum_package_key) |
106 definition.prefix_to_strip = self._directives.get( | 116 definition.prefix_to_strip = self._directives.get( |
107 DirectiveSet.prefix_to_strip_key) | 117 DirectiveSet.prefix_to_strip_key) |
108 | 118 |
109 | 119 |
110 class HeaderParser(object): | 120 class HeaderParser(object): |
111 single_line_comment_re = re.compile(r'\s*//') | 121 single_line_comment_re = re.compile(r'\s*//') |
112 multi_line_comment_start_re = re.compile(r'\s*/\*') | 122 multi_line_comment_start_re = re.compile(r'\s*/\*') |
113 enum_start_re = re.compile(r'^\s*enum\s+(\w+)\s+{\s*$') | |
114 enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?') | 123 enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?') |
115 enum_end_re = re.compile(r'^\s*}\s*;\.*$') | 124 enum_end_re = re.compile(r'^\s*}\s*;\.*$') |
116 generator_directive_re = re.compile( | 125 generator_directive_re = re.compile( |
117 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$') | 126 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$') |
118 | 127 |
| 128 optional_class_or_struct_re = r'(class|struct)?' |
| 129 enum_name_re = r'(\w+)' |
| 130 optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?' |
| 131 enum_start_re = re.compile(r'^\s*enum\s+' + optional_class_or_struct_re + |
| 132 '\s*' + enum_name_re + '\s*' + optional_fixed_type_re + '\s*{\s*$') |
| 133 |
119 def __init__(self, lines): | 134 def __init__(self, lines): |
120 self._lines = lines | 135 self._lines = lines |
121 self._enum_definitions = [] | 136 self._enum_definitions = [] |
122 self._in_enum = False | 137 self._in_enum = False |
123 self._current_definition = None | 138 self._current_definition = None |
124 self._generator_directives = DirectiveSet() | 139 self._generator_directives = DirectiveSet() |
125 | 140 |
126 def ParseDefinitions(self): | 141 def ParseDefinitions(self): |
127 for line in self._lines: | 142 for line in self._lines: |
128 self._ParseLine(line) | 143 self._ParseLine(line) |
(...skipping 26 matching lines...) Expand all Loading... |
155 self._generator_directives.UpdateDefinition(self._current_definition) | 170 self._generator_directives.UpdateDefinition(self._current_definition) |
156 self._generator_directives = DirectiveSet() | 171 self._generator_directives = DirectiveSet() |
157 | 172 |
158 def _ParseRegularLine(self, line): | 173 def _ParseRegularLine(self, line): |
159 enum_start = HeaderParser.enum_start_re.match(line) | 174 enum_start = HeaderParser.enum_start_re.match(line) |
160 generator_directive = HeaderParser.generator_directive_re.match(line) | 175 generator_directive = HeaderParser.generator_directive_re.match(line) |
161 if enum_start: | 176 if enum_start: |
162 if self._generator_directives.empty: | 177 if self._generator_directives.empty: |
163 return | 178 return |
164 self._current_definition = EnumDefinition( | 179 self._current_definition = EnumDefinition( |
165 original_enum_name=enum_start.groups()[0]) | 180 original_enum_name=enum_start.groups()[1], |
| 181 fixed_type=enum_start.groups()[3]) |
166 self._in_enum = True | 182 self._in_enum = True |
167 elif generator_directive: | 183 elif generator_directive: |
168 directive_name = generator_directive.groups()[0] | 184 directive_name = generator_directive.groups()[0] |
169 directive_value = generator_directive.groups()[1] | 185 directive_value = generator_directive.groups()[1] |
170 self._generator_directives.Update(directive_name, directive_value) | 186 self._generator_directives.Update(directive_name, directive_value) |
171 | 187 |
172 | 188 |
173 def GetScriptName(): | 189 def GetScriptName(): |
174 script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) | 190 script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) |
175 build_index = script_components.index('build') | 191 build_index = script_components.index('build') |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 | 278 |
263 output_paths = DoGenerate(options, args) | 279 output_paths = DoGenerate(options, args) |
264 | 280 |
265 if options.assert_files_list: | 281 if options.assert_files_list: |
266 AssertFilesList(output_paths, options.assert_files_list) | 282 AssertFilesList(output_paths, options.assert_files_list) |
267 | 283 |
268 return " ".join(output_paths) | 284 return " ".join(output_paths) |
269 | 285 |
270 if __name__ == '__main__': | 286 if __name__ == '__main__': |
271 DoMain(sys.argv[1:]) | 287 DoMain(sys.argv[1:]) |
OLD | NEW |