OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2012 the V8 project authors. All rights reserved. | 3 # Copyright 2012 the V8 project authors. All rights reserved. |
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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
62 file = open(filename, "rt") | 62 file = open(filename, "rt") |
63 try: | 63 try: |
64 lines = file.read() | 64 lines = file.read() |
65 finally: | 65 finally: |
66 file.close() | 66 file.close() |
67 return lines | 67 return lines |
68 | 68 |
69 | 69 |
70 EVAL_PATTERN = re.compile(r'\beval\s*\(') | 70 EVAL_PATTERN = re.compile(r'\beval\s*\(') |
71 WITH_PATTERN = re.compile(r'\bwith\s*\(') | 71 WITH_PATTERN = re.compile(r'\bwith\s*\(') |
| 72 INVALID_ERROR_MESSAGE_PATTERN = re.compile(r'Make\w*Error\((k\w+),') |
72 | 73 |
73 def Validate(lines): | 74 def Validate(lines): |
74 # Because of simplified context setup, eval and with is not | 75 # Because of simplified context setup, eval and with is not |
75 # allowed in the natives files. | 76 # allowed in the natives files. |
76 if EVAL_PATTERN.search(lines): | 77 if EVAL_PATTERN.search(lines): |
77 raise Error("Eval disallowed in natives.") | 78 raise Error("Eval disallowed in natives.") |
78 if WITH_PATTERN.search(lines): | 79 if WITH_PATTERN.search(lines): |
79 raise Error("With statements disallowed in natives.") | 80 raise Error("With statements disallowed in natives.") |
80 | 81 invalid_error = INVALID_ERROR_MESSAGE_PATTERN.search(lines) |
| 82 if invalid_error: |
| 83 raise Error("Unknown error message template '%s'" % invalid_error.group(1)) |
81 # Pass lines through unchanged. | 84 # Pass lines through unchanged. |
82 return lines | 85 return lines |
83 | 86 |
84 | 87 |
85 def ExpandConstants(lines, constants): | 88 def ExpandConstants(lines, constants): |
86 for key, value in constants: | 89 for key, value in constants: |
87 lines = key.sub(str(value), lines) | 90 lines = key.sub(str(value), lines) |
88 return lines | 91 return lines |
89 | 92 |
90 | 93 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 if python_match: | 184 if python_match: |
182 name = python_match.group(1) | 185 name = python_match.group(1) |
183 args = [match.strip() for match in python_match.group(2).split(',')] | 186 args = [match.strip() for match in python_match.group(2).split(',')] |
184 body = python_match.group(3).strip() | 187 body = python_match.group(3).strip() |
185 fun = eval("lambda " + ",".join(args) + ': ' + body) | 188 fun = eval("lambda " + ",".join(args) + ': ' + body) |
186 macros.append((re.compile("\\b%s\\(" % name), PythonMacro(args, fun))) | 189 macros.append((re.compile("\\b%s\\(" % name), PythonMacro(args, fun))) |
187 else: | 190 else: |
188 raise Error("Illegal line: " + line) | 191 raise Error("Illegal line: " + line) |
189 return (constants, macros) | 192 return (constants, macros) |
190 | 193 |
| 194 |
| 195 TEMPLATE_PATTERN = re.compile(r'^\s+T\(([a-zA-Z]+), ".+"\)') |
| 196 |
| 197 def ReadMessageTemplates(lines): |
| 198 templates = [] |
| 199 index = 0 |
| 200 for line in lines.split('\n'): |
| 201 template_match = TEMPLATE_PATTERN.match(line) |
| 202 if template_match: |
| 203 name = "k%s" % template_match.group(1) |
| 204 value = index |
| 205 index = index + 1 |
| 206 templates.append((re.compile("\\b%s\\b" % name), value)) |
| 207 return templates |
| 208 |
191 INLINE_MACRO_PATTERN = re.compile(r'macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*\n') | 209 INLINE_MACRO_PATTERN = re.compile(r'macro\s+([a-zA-Z0-9_]+)\s*\(([^)]*)\)\s*\n') |
192 INLINE_MACRO_END_PATTERN = re.compile(r'endmacro\s*\n') | 210 INLINE_MACRO_END_PATTERN = re.compile(r'endmacro\s*\n') |
193 | 211 |
194 def ExpandInlineMacros(lines): | 212 def ExpandInlineMacros(lines): |
195 pos = 0 | 213 pos = 0 |
196 while True: | 214 while True: |
197 macro_match = INLINE_MACRO_PATTERN.search(lines, pos) | 215 macro_match = INLINE_MACRO_PATTERN.search(lines, pos) |
198 if macro_match is None: | 216 if macro_match is None: |
199 # no more macros | 217 # no more macros |
200 return lines | 218 return lines |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 GET_SCRIPT_SOURCE_CASE = """\ | 322 GET_SCRIPT_SOURCE_CASE = """\ |
305 if (index == %(i)i) return Vector<const char>(sources + %(offset)i, %(source
_length)i); | 323 if (index == %(i)i) return Vector<const char>(sources + %(offset)i, %(source
_length)i); |
306 """ | 324 """ |
307 | 325 |
308 | 326 |
309 GET_SCRIPT_NAME_CASE = """\ | 327 GET_SCRIPT_NAME_CASE = """\ |
310 if (index == %(i)i) return Vector<const char>("%(name)s", %(length)i); | 328 if (index == %(i)i) return Vector<const char>("%(name)s", %(length)i); |
311 """ | 329 """ |
312 | 330 |
313 | 331 |
314 def BuildFilterChain(macro_filename): | 332 def BuildFilterChain(macro_filename, message_template_file): |
315 """Build the chain of filter functions to be applied to the sources. | 333 """Build the chain of filter functions to be applied to the sources. |
316 | 334 |
317 Args: | 335 Args: |
318 macro_filename: Name of the macro file, if any. | 336 macro_filename: Name of the macro file, if any. |
319 | 337 |
320 Returns: | 338 Returns: |
321 A function (string -> string) that reads a source file and processes it. | 339 A function (string -> string) that reads a source file and processes it. |
322 """ | 340 """ |
323 filter_chain = [ReadFile] | 341 filter_chain = [ReadFile] |
324 | 342 |
325 if macro_filename: | 343 if macro_filename: |
326 (consts, macros) = ReadMacros(ReadFile(macro_filename)) | 344 (consts, macros) = ReadMacros(ReadFile(macro_filename)) |
327 filter_chain.append(lambda l: ExpandConstants(l, consts)) | 345 filter_chain.append(lambda l: ExpandConstants(l, consts)) |
328 filter_chain.append(lambda l: ExpandMacros(l, macros)) | 346 filter_chain.append(lambda l: ExpandMacros(l, macros)) |
329 | 347 |
| 348 if message_template_file: |
| 349 message_templates = ReadMessageTemplates(ReadFile(message_template_file)) |
| 350 filter_chain.append(lambda l: ExpandConstants(l, message_templates)) |
| 351 |
330 filter_chain.extend([ | 352 filter_chain.extend([ |
331 RemoveCommentsAndTrailingWhitespace, | 353 RemoveCommentsAndTrailingWhitespace, |
332 ExpandInlineMacros, | 354 ExpandInlineMacros, |
333 ExpandInlineConstants, | 355 ExpandInlineConstants, |
334 Validate, | 356 Validate, |
335 jsmin.JavaScriptMinifier().JSMinify | 357 jsmin.JavaScriptMinifier().JSMinify |
336 ]) | 358 ]) |
337 | 359 |
338 def chain(f1, f2): | 360 def chain(f1, f2): |
339 return lambda x: f2(f1(x)) | 361 return lambda x: f2(f1(x)) |
340 | 362 |
341 return reduce(chain, filter_chain) | 363 return reduce(chain, filter_chain) |
342 | 364 |
343 | 365 |
344 class Sources: | 366 class Sources: |
345 def __init__(self): | 367 def __init__(self): |
346 self.names = [] | 368 self.names = [] |
347 self.modules = [] | 369 self.modules = [] |
348 self.is_debugger_id = [] | 370 self.is_debugger_id = [] |
349 | 371 |
350 | 372 |
351 def IsDebuggerFile(filename): | 373 def IsDebuggerFile(filename): |
352 return filename.endswith("-debugger.js") | 374 return filename.endswith("-debugger.js") |
353 | 375 |
354 def IsMacroFile(filename): | 376 def IsMacroFile(filename): |
355 return filename.endswith("macros.py") | 377 return filename.endswith("macros.py") |
356 | 378 |
| 379 def IsMessageTemplateFile(filename): |
| 380 return filename.endswith("messages.h") |
| 381 |
357 | 382 |
358 def PrepareSources(source_files): | 383 def PrepareSources(source_files): |
359 """Read, prepare and assemble the list of source files. | 384 """Read, prepare and assemble the list of source files. |
360 | 385 |
361 Args: | 386 Args: |
362 sources: List of Javascript-ish source files. A file named macros.py | 387 sources: List of Javascript-ish source files. A file named macros.py |
363 will be treated as a list of macros. | 388 will be treated as a list of macros. |
364 | 389 |
365 Returns: | 390 Returns: |
366 An instance of Sources. | 391 An instance of Sources. |
367 """ | 392 """ |
368 macro_file = None | 393 macro_file = None |
369 macro_files = filter(IsMacroFile, source_files) | 394 macro_files = filter(IsMacroFile, source_files) |
370 assert len(macro_files) in [0, 1] | 395 assert len(macro_files) in [0, 1] |
371 if macro_files: | 396 if macro_files: |
372 source_files.remove(macro_files[0]) | 397 source_files.remove(macro_files[0]) |
373 macro_file = macro_files[0] | 398 macro_file = macro_files[0] |
374 | 399 |
375 filters = BuildFilterChain(macro_file) | 400 message_template_file = None |
| 401 message_template_files = filter(IsMessageTemplateFile, source_files) |
| 402 assert len(message_template_files) in [0, 1] |
| 403 if message_template_files: |
| 404 source_files.remove(message_template_files[0]) |
| 405 message_template_file = message_template_files[0] |
| 406 |
| 407 filters = BuildFilterChain(macro_file, message_template_file) |
376 | 408 |
377 # Sort 'debugger' sources first. | 409 # Sort 'debugger' sources first. |
378 source_files = sorted(source_files, | 410 source_files = sorted(source_files, |
379 lambda l,r: IsDebuggerFile(r) - IsDebuggerFile(l)) | 411 lambda l,r: IsDebuggerFile(r) - IsDebuggerFile(l)) |
380 | 412 |
381 result = Sources() | 413 result = Sources() |
382 for source in source_files: | 414 for source in source_files: |
383 try: | 415 try: |
384 lines = filters(source) | 416 lines = filters(source) |
385 except Error as e: | 417 except Error as e: |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
525 out.cc: C code to be generated. | 557 out.cc: C code to be generated. |
526 type: type parameter for NativesCollection template. | 558 type: type parameter for NativesCollection template. |
527 sources.js: JS internal sources or macros.py.""") | 559 sources.js: JS internal sources or macros.py.""") |
528 (options, args) = parser.parse_args() | 560 (options, args) = parser.parse_args() |
529 | 561 |
530 JS2C(args[2:], args[0], args[1], options.raw, options.startup_blob) | 562 JS2C(args[2:], args[0], args[1], options.raw, options.startup_blob) |
531 | 563 |
532 | 564 |
533 if __name__ == "__main__": | 565 if __name__ == "__main__": |
534 main() | 566 main() |
OLD | NEW |