| 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 322 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  333 """ |  333 """ | 
|  334  |  334  | 
|  335  |  335  | 
|  336 def BuildFilterChain(macro_filename, message_template_file): |  336 def BuildFilterChain(macro_filename, message_template_file): | 
|  337   """Build the chain of filter functions to be applied to the sources. |  337   """Build the chain of filter functions to be applied to the sources. | 
|  338  |  338  | 
|  339   Args: |  339   Args: | 
|  340     macro_filename: Name of the macro file, if any. |  340     macro_filename: Name of the macro file, if any. | 
|  341  |  341  | 
|  342   Returns: |  342   Returns: | 
|  343     A function (string -> string) that reads a source file and processes it. |  343     A function (string -> string) that processes a source file. | 
|  344   """ |  344   """ | 
|  345   filter_chain = [ReadFile] |  345   filter_chain = [] | 
|  346  |  346  | 
|  347   if macro_filename: |  347   if macro_filename: | 
|  348     (consts, macros) = ReadMacros(ReadFile(macro_filename)) |  348     (consts, macros) = ReadMacros(ReadFile(macro_filename)) | 
|  349     filter_chain.append(lambda l: ExpandConstants(l, consts)) |  349     filter_chain.append(lambda l: ExpandConstants(l, consts)) | 
|  350     filter_chain.append(lambda l: ExpandMacros(l, macros)) |  350     filter_chain.append(lambda l: ExpandMacros(l, macros)) | 
|  351  |  351  | 
|  352   if message_template_file: |  352   if message_template_file: | 
|  353     message_templates = ReadMessageTemplates(ReadFile(message_template_file)) |  353     message_templates = ReadMessageTemplates(ReadFile(message_template_file)) | 
|  354     filter_chain.append(lambda l: ExpandConstants(l, message_templates)) |  354     filter_chain.append(lambda l: ExpandConstants(l, message_templates)) | 
|  355  |  355  | 
|  356   filter_chain.extend([ |  356   filter_chain.extend([ | 
|  357     RemoveCommentsAndTrailingWhitespace, |  357     RemoveCommentsAndTrailingWhitespace, | 
|  358     ExpandInlineMacros, |  358     ExpandInlineMacros, | 
|  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(): |  369 def BuildExtraFilterChain(): | 
|  370   return lambda x: RemoveCommentsAndTrailingWhitespace(Validate(ReadFile(x))) |  370   return lambda x: RemoveCommentsAndTrailingWhitespace(Validate(x)) | 
|  371  |  371  | 
|  372 class Sources: |  372 class Sources: | 
|  373   def __init__(self): |  373   def __init__(self): | 
|  374     self.names = [] |  374     self.names = [] | 
|  375     self.modules = [] |  375     self.modules = [] | 
|  376     self.is_debugger_id = [] |  376     self.is_debugger_id = [] | 
|  377  |  377  | 
|  378  |  378  | 
|  379 def IsDebuggerFile(filename): |  379 def IsDebuggerFile(filename): | 
|  380   return filename.endswith("-debugger.js") |  380   return filename.endswith("-debugger.js") | 
|  381  |  381  | 
|  382 def IsMacroFile(filename): |  382 def IsMacroFile(filename): | 
|  383   return filename.endswith("macros.py") |  383   return filename.endswith("macros.py") | 
|  384  |  384  | 
|  385 def IsMessageTemplateFile(filename): |  385 def IsMessageTemplateFile(filename): | 
|  386   return filename.endswith("messages.h") |  386   return filename.endswith("messages.h") | 
|  387  |  387  | 
|  388  |  388  | 
|  389 def PrepareSources(source_files, extra_files, emit_js): |  389 def PrepareSources(source_files, native_type, emit_js): | 
|  390   """Read, prepare and assemble the list of source files. |  390   """Read, prepare and assemble the list of source files. | 
|  391  |  391  | 
|  392   Args: |  392   Args: | 
|  393     source_files: 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 | 
|  394         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 |  395     native_type: String corresponding to a NativeType enum value, allowing us | 
|  396         externally from V8. Will not be minified or macro-ified. |  396         to treat different types of sources differently. | 
|  397     emit_js: True if we should skip the byte conversion and just leave the |  397     emit_js: True if we should skip the byte conversion and just leave the | 
|  398         sources as JS strings. |  398         sources as JS strings. | 
|  399  |  399  | 
|  400   Returns: |  400   Returns: | 
|  401     An instance of Sources. |  401     An instance of Sources. | 
|  402   """ |  402   """ | 
|  403   macro_file = None |  403   macro_file = None | 
|  404   macro_files = filter(IsMacroFile, source_files) |  404   macro_files = filter(IsMacroFile, source_files) | 
|  405   assert len(macro_files) in [0, 1] |  405   assert len(macro_files) in [0, 1] | 
|  406   if macro_files: |  406   if macro_files: | 
|  407     source_files.remove(macro_files[0]) |  407     source_files.remove(macro_files[0]) | 
|  408     macro_file = macro_files[0] |  408     macro_file = macro_files[0] | 
|  409  |  409  | 
|  410   message_template_file = None |  410   message_template_file = None | 
|  411   message_template_files = filter(IsMessageTemplateFile, source_files) |  411   message_template_files = filter(IsMessageTemplateFile, source_files) | 
|  412   assert len(message_template_files) in [0, 1] |  412   assert len(message_template_files) in [0, 1] | 
|  413   if message_template_files: |  413   if message_template_files: | 
|  414     source_files.remove(message_template_files[0]) |  414     source_files.remove(message_template_files[0]) | 
|  415     message_template_file = message_template_files[0] |  415     message_template_file = message_template_files[0] | 
|  416  |  416  | 
|  417   filters = BuildFilterChain(macro_file, message_template_file) |  417   filters = None | 
|  418   extra_filters = BuildExtraFilterChain() |  418   if native_type == "EXTRA": | 
 |  419     filters = BuildExtraFilterChain() | 
 |  420   else: | 
 |  421     filters = BuildFilterChain(macro_file, message_template_file) | 
|  419  |  422  | 
|  420   # Sort 'debugger' sources first. |  423   # Sort 'debugger' sources first. | 
|  421   source_files = sorted(source_files, |  424   source_files = sorted(source_files, | 
|  422                         lambda l,r: IsDebuggerFile(r) - IsDebuggerFile(l)) |  425                         lambda l,r: IsDebuggerFile(r) - IsDebuggerFile(l)) | 
|  423  |  426  | 
 |  427   source_files_and_contents = [(f, ReadFile(f)) for f in source_files] | 
 |  428  | 
 |  429   # Have a single not-quite-empty source file if there are none present; | 
 |  430   # otherwise you get errors trying to compile an empty C++ array. | 
 |  431   if not source_files_and_contents: | 
 |  432     source_files_and_contents = [("dummy.js", " ")] | 
 |  433  | 
|  424   result = Sources() |  434   result = Sources() | 
|  425  |  435  | 
|  426   for source in source_files: |  436   for (source, contents) in source_files_and_contents: | 
|  427     try: |  437     try: | 
|  428       lines = filters(source) |  438       lines = filters(contents) | 
|  429     except Error as e: |  439     except Error as e: | 
|  430       raise Error("In file %s:\n%s" % (source, str(e))) |  440       raise Error("In file %s:\n%s" % (source, str(e))) | 
|  431  |  441  | 
|  432     result.modules.append(lines) |  442     result.modules.append(lines) | 
|  433  |  443  | 
|  434     is_debugger = IsDebuggerFile(source) |  444     is_debugger = IsDebuggerFile(source) | 
|  435     result.is_debugger_id.append(is_debugger) |  445     result.is_debugger_id.append(is_debugger) | 
|  436  |  446  | 
|  437     name = os.path.basename(source)[:-3] |  447     name = os.path.basename(source)[:-3] | 
|  438     result.names.append(name if not is_debugger else name[:-9]) |  448     result.names.append(name if not is_debugger else name[:-9]) | 
|  439  |  449  | 
|  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" % (extra, str(e))) |  | 
|  445  |  | 
|  446     result.modules.append(lines) |  | 
|  447     name = os.path.basename(extra)[:-3] |  | 
|  448     result.names.append(name) |  | 
|  449  |  | 
|  450   return result |  450   return result | 
|  451  |  451  | 
|  452  |  452  | 
|  453 def BuildMetadata(sources, source_bytes, native_type): |  453 def BuildMetadata(sources, source_bytes, native_type): | 
|  454   """Build the meta data required to generate a libaries file. |  454   """Build the meta data required to generate a libaries file. | 
|  455  |  455  | 
|  456   Args: |  456   Args: | 
|  457     sources: A Sources instance with the prepared sources. |  457     sources: A Sources instance with the prepared sources. | 
|  458     source_bytes: A list of source bytes. |  458     source_bytes: A list of source bytes. | 
|  459         (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... | 
|  543     PutStr(output, sources.modules[i]); |  543     PutStr(output, sources.modules[i]); | 
|  544  |  544  | 
|  545   PutInt(output, len(sources.names) - debug_sources) |  545   PutInt(output, len(sources.names) - debug_sources) | 
|  546   for i in xrange(debug_sources, len(sources.names)): |  546   for i in xrange(debug_sources, len(sources.names)): | 
|  547     PutStr(output, sources.names[i]); |  547     PutStr(output, sources.names[i]); | 
|  548     PutStr(output, sources.modules[i]); |  548     PutStr(output, sources.modules[i]); | 
|  549  |  549  | 
|  550   output.close() |  550   output.close() | 
|  551  |  551  | 
|  552  |  552  | 
|  553 def JS2C(sources, extra_sources, target, native_type, raw_file, startup_blob, em
     itJS): |  553 def JS2C(sources, target, native_type, raw_file, startup_blob, emit_js): | 
|  554   prepared_sources = PrepareSources(sources, extra_sources, emitJS) |  554   prepared_sources = PrepareSources(sources, native_type, emit_js) | 
|  555   sources_output = "".join(prepared_sources.modules) |  555   sources_output = "".join(prepared_sources.modules) | 
|  556   metadata = BuildMetadata(prepared_sources, sources_output, native_type) |  556   metadata = BuildMetadata(prepared_sources, sources_output, native_type) | 
|  557  |  557  | 
|  558   # Optionally emit raw file. |  558   # Optionally emit raw file. | 
|  559   if raw_file: |  559   if raw_file: | 
|  560     output = open(raw_file, "w") |  560     output = open(raw_file, "w") | 
|  561     output.write(sources_output) |  561     output.write(sources_output) | 
|  562     output.close() |  562     output.close() | 
|  563  |  563  | 
|  564   if startup_blob: |  564   if startup_blob: | 
|  565     WriteStartupBlob(prepared_sources, startup_blob) |  565     WriteStartupBlob(prepared_sources, startup_blob) | 
|  566  |  566  | 
|  567   # Emit resulting source file. |  567   # Emit resulting source file. | 
|  568   output = open(target, "w") |  568   output = open(target, "w") | 
|  569   if emitJS: |  569   if emit_js: | 
|  570     output.write(sources_output) |  570     output.write(sources_output) | 
|  571   else: |  571   else: | 
|  572     output.write(HEADER_TEMPLATE % metadata) |  572     output.write(HEADER_TEMPLATE % metadata) | 
|  573   output.close() |  573   output.close() | 
|  574  |  574  | 
|  575  |  575  | 
|  576 def main(): |  576 def main(): | 
|  577   parser = argparse.ArgumentParser() |  577   parser = argparse.ArgumentParser() | 
|  578   parser.add_argument("out.cc", |  578   parser.add_argument("out.cc", | 
|  579                       help="output filename") |  579                       help="output filename") | 
|  580   parser.add_argument("type", |  580   parser.add_argument("type", | 
|  581                       help="type parameter for NativesCollection template") |  581                       help="type parameter for NativesCollection template " + | 
 |  582                            "(see NativeType enum)") | 
|  582   parser.add_argument("sources.js", |  583   parser.add_argument("sources.js", | 
|  583                       help="JS internal sources or macros.py.", |  584                       help="JS internal sources or macros.py.", | 
|  584                       nargs="+") |  585                       nargs="*") | 
|  585   parser.add_argument("--raw", |  586   parser.add_argument("--raw", | 
|  586                       help="file to write the processed sources array to.") |  587                       help="file to write the processed sources array to.") | 
|  587   parser.add_argument("--startup_blob", |  588   parser.add_argument("--startup_blob", | 
|  588                       help="file to write the startup blob to.") |  589                       help="file to write the startup blob to.") | 
|  589   parser.add_argument("--extra", |  | 
|  590                       help="extra JS sources.", |  | 
|  591                       nargs="*") |  | 
|  592   parser.add_argument("--js", |  590   parser.add_argument("--js", | 
|  593                       help="writes a JS file output instead of a C file", |  591                       help="writes a JS file output instead of a C file", | 
|  594                       action="store_true") |  592                       action="store_true") | 
|  595  |  593  | 
|  596   args = vars(parser.parse_args()) |  594   args = vars(parser.parse_args()) | 
|  597   JS2C(args["sources.js"], args["extra"] or [], args["out.cc"], args["type"], ar
     gs["raw"], args["startup_blob"], |  595   JS2C(args["sources.js"], args["out.cc"], args["type"], args["raw"], args["star
     tup_blob"], args["js"]) | 
|  598        args["js"]) |  | 
|  599  |  596  | 
|  600  |  597  | 
|  601 if __name__ == "__main__": |  598 if __name__ == "__main__": | 
|  602   main() |  599   main() | 
| OLD | NEW |