| 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 |