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 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
359 ExpandInlineConstants, | 359 ExpandInlineConstants, |
360 Validate, | 360 Validate, |
361 jsmin.JavaScriptMinifier().JSMinify | 361 jsmin.JavaScriptMinifier().JSMinify |
362 ]) | 362 ]) |
363 | 363 |
364 def chain(f1, f2): | 364 def chain(f1, f2): |
365 return lambda x: f2(f1(x)) | 365 return lambda x: f2(f1(x)) |
366 | 366 |
367 return reduce(chain, filter_chain) | 367 return reduce(chain, filter_chain) |
368 | 368 |
| 369 def BuildExtraFilterChain(): |
| 370 return lambda x: RemoveCommentsAndTrailingWhitespace(Validate(ReadFile(x))) |
369 | 371 |
370 class Sources: | 372 class Sources: |
371 def __init__(self): | 373 def __init__(self): |
372 self.names = [] | 374 self.names = [] |
373 self.modules = [] | 375 self.modules = [] |
374 self.is_debugger_id = [] | 376 self.is_debugger_id = [] |
375 | 377 |
376 | 378 |
377 def IsDebuggerFile(filename): | 379 def IsDebuggerFile(filename): |
378 return filename.endswith("-debugger.js") | 380 return filename.endswith("-debugger.js") |
379 | 381 |
380 def IsMacroFile(filename): | 382 def IsMacroFile(filename): |
381 return filename.endswith("macros.py") | 383 return filename.endswith("macros.py") |
382 | 384 |
383 def IsMessageTemplateFile(filename): | 385 def IsMessageTemplateFile(filename): |
384 return filename.endswith("messages.h") | 386 return filename.endswith("messages.h") |
385 | 387 |
386 | 388 |
387 def PrepareSources(source_files): | 389 def PrepareSources(source_files, extra_files, emit_js): |
388 """Read, prepare and assemble the list of source files. | 390 """Read, prepare and assemble the list of source files. |
389 | 391 |
390 Args: | 392 Args: |
391 sources: List of Javascript-ish source files. A file named macros.py | 393 source_files: List of JavaScript-ish source files. A file named macros.py |
392 will be treated as a list of macros. | 394 will be treated as a list of macros. |
| 395 extra_files: List of JavaScript-ish extra source files, passed in |
| 396 externally from V8. Will not be minified or macro-ified. |
| 397 emit_js: True if we should skip the byte conversion and just leave the |
| 398 sources as JS strings. |
393 | 399 |
394 Returns: | 400 Returns: |
395 An instance of Sources. | 401 An instance of Sources. |
396 """ | 402 """ |
397 macro_file = None | 403 macro_file = None |
398 macro_files = filter(IsMacroFile, source_files) | 404 macro_files = filter(IsMacroFile, source_files) |
399 assert len(macro_files) in [0, 1] | 405 assert len(macro_files) in [0, 1] |
400 if macro_files: | 406 if macro_files: |
401 source_files.remove(macro_files[0]) | 407 source_files.remove(macro_files[0]) |
402 macro_file = macro_files[0] | 408 macro_file = macro_files[0] |
403 | 409 |
404 message_template_file = None | 410 message_template_file = None |
405 message_template_files = filter(IsMessageTemplateFile, source_files) | 411 message_template_files = filter(IsMessageTemplateFile, source_files) |
406 assert len(message_template_files) in [0, 1] | 412 assert len(message_template_files) in [0, 1] |
407 if message_template_files: | 413 if message_template_files: |
408 source_files.remove(message_template_files[0]) | 414 source_files.remove(message_template_files[0]) |
409 message_template_file = message_template_files[0] | 415 message_template_file = message_template_files[0] |
410 | 416 |
411 filters = BuildFilterChain(macro_file, message_template_file) | 417 filters = BuildFilterChain(macro_file, message_template_file) |
| 418 extra_filters = BuildExtraFilterChain() |
412 | 419 |
413 # Sort 'debugger' sources first. | 420 # Sort 'debugger' sources first. |
414 source_files = sorted(source_files, | 421 source_files = sorted(source_files, |
415 lambda l,r: IsDebuggerFile(r) - IsDebuggerFile(l)) | 422 lambda l,r: IsDebuggerFile(r) - IsDebuggerFile(l)) |
416 | 423 |
417 result = Sources() | 424 result = Sources() |
| 425 |
418 for source in source_files: | 426 for source in source_files: |
419 try: | 427 try: |
420 lines = filters(source) | 428 lines = filters(source) |
421 except Error as e: | 429 except Error as e: |
422 raise Error("In file %s:\n%s" % (source, str(e))) | 430 raise Error("In file %s:\n%s" % (source, str(e))) |
423 | 431 |
424 result.modules.append(lines); | 432 result.modules.append(lines) |
425 | 433 |
426 is_debugger = IsDebuggerFile(source) | 434 is_debugger = IsDebuggerFile(source) |
427 result.is_debugger_id.append(is_debugger); | 435 result.is_debugger_id.append(is_debugger) |
428 | 436 |
429 name = os.path.basename(source)[:-3] | 437 name = os.path.basename(source)[:-3] |
430 result.names.append(name if not is_debugger else name[:-9]); | 438 result.names.append(name if not is_debugger else name[:-9]) |
| 439 |
| 440 for extra in extra_files: |
| 441 try: |
| 442 lines = extra_filters(extra) |
| 443 except Error as e: |
| 444 raise Error("In file %s:\n%s" % (source, str(e))) |
| 445 |
| 446 result.modules.append(lines) |
| 447 name = os.path.basename(source)[:-3] |
| 448 result.names.append(name) |
| 449 |
431 return result | 450 return result |
432 | 451 |
433 | 452 |
434 def BuildMetadata(sources, source_bytes, native_type): | 453 def BuildMetadata(sources, source_bytes, native_type): |
435 """Build the meta data required to generate a libaries file. | 454 """Build the meta data required to generate a libaries file. |
436 | 455 |
437 Args: | 456 Args: |
438 sources: A Sources instance with the prepared sources. | 457 sources: A Sources instance with the prepared sources. |
439 source_bytes: A list of source bytes. | 458 source_bytes: A list of source bytes. |
440 (The concatenation of all sources; might be compressed.) | 459 (The concatenation of all sources; might be compressed.) |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 PutStr(output, sources.modules[i]); | 543 PutStr(output, sources.modules[i]); |
525 | 544 |
526 PutInt(output, len(sources.names) - debug_sources) | 545 PutInt(output, len(sources.names) - debug_sources) |
527 for i in xrange(debug_sources, len(sources.names)): | 546 for i in xrange(debug_sources, len(sources.names)): |
528 PutStr(output, sources.names[i]); | 547 PutStr(output, sources.names[i]); |
529 PutStr(output, sources.modules[i]); | 548 PutStr(output, sources.modules[i]); |
530 | 549 |
531 output.close() | 550 output.close() |
532 | 551 |
533 | 552 |
534 def JS2C(source, extraSource, target, native_type, raw_file, startup_blob): | 553 def JS2C(sources, extra_sources, target, native_type, raw_file, startup_blob, em
itJS): |
535 # For now we treat source and extraSource the same, but we keep them separate | 554 prepared_sources = PrepareSources(sources, extra_sources, emitJS) |
536 # in the input so that we can start treating them differently in the future. | 555 sources_output = "".join(prepared_sources.modules) |
537 sources = PrepareSources(source + extraSource) | 556 metadata = BuildMetadata(prepared_sources, sources_output, native_type) |
538 sources_bytes = "".join(sources.modules) | |
539 metadata = BuildMetadata(sources, sources_bytes, native_type) | |
540 | 557 |
541 # Optionally emit raw file. | 558 # Optionally emit raw file. |
542 if raw_file: | 559 if raw_file: |
543 output = open(raw_file, "w") | 560 output = open(raw_file, "w") |
544 output.write(sources_bytes) | 561 output.write(sources_output) |
545 output.close() | 562 output.close() |
546 | 563 |
547 if startup_blob: | 564 if startup_blob: |
548 WriteStartupBlob(sources, startup_blob); | 565 WriteStartupBlob(prepared_sources, startup_blob) |
549 | 566 |
550 # Emit resulting source file. | 567 # Emit resulting source file. |
551 output = open(target, "w") | 568 output = open(target, "w") |
552 output.write(HEADER_TEMPLATE % metadata) | 569 if emitJS: |
| 570 output.write(sources_output) |
| 571 else: |
| 572 output.write(HEADER_TEMPLATE % metadata) |
553 output.close() | 573 output.close() |
554 | 574 |
555 | 575 |
556 def main(): | 576 def main(): |
557 parser = argparse.ArgumentParser() | 577 parser = argparse.ArgumentParser() |
558 parser.add_argument("out.cc", | 578 parser.add_argument("out.cc", |
559 help="C code to be generated") | 579 help="output filename") |
560 parser.add_argument("type", | 580 parser.add_argument("type", |
561 help="type parameter for NativesCollection template") | 581 help="type parameter for NativesCollection template") |
562 parser.add_argument("sources.js", | 582 parser.add_argument("sources.js", |
563 help="JS internal sources or macros.py.", | 583 help="JS internal sources or macros.py.", |
564 nargs="+") | 584 nargs="+") |
565 parser.add_argument("--raw", | 585 parser.add_argument("--raw", |
566 help="file to write the processed sources array to.") | 586 help="file to write the processed sources array to.") |
567 parser.add_argument("--startup_blob", | 587 parser.add_argument("--startup_blob", |
568 help="file to write the startup blob to.") | 588 help="file to write the startup blob to.") |
569 parser.add_argument("--extra", | 589 parser.add_argument("--extra", |
570 help="extra JS sources.", | 590 help="extra JS sources.", |
571 nargs="*") | 591 nargs="*") |
| 592 parser.add_argument("--js", |
| 593 help="writes a JS file output instead of a C file", |
| 594 action="store_true") |
572 | 595 |
573 args = vars(parser.parse_args()) | 596 args = vars(parser.parse_args()) |
574 JS2C(args["sources.js"], args["extra"] or [], args["out.cc"], args["type"], ar
gs["raw"], args["startup_blob"]) | 597 JS2C(args["sources.js"], args["extra"] or [], args["out.cc"], args["type"], ar
gs["raw"], args["startup_blob"], |
| 598 args["js"]) |
575 | 599 |
576 | 600 |
577 if __name__ == "__main__": | 601 if __name__ == "__main__": |
578 main() | 602 main() |
OLD | NEW |