Chromium Code Reviews| Index: test/cctest/interpreter/generate-bytecode-expectations.cc |
| diff --git a/test/cctest/interpreter/generate-bytecode-expectations.cc b/test/cctest/interpreter/generate-bytecode-expectations.cc |
| index 8bf9ba6dfb9ac28e459e71bf1f7480c1962bd074..e504bcd094ffb0cab3af20d65f10df1291680610 100644 |
| --- a/test/cctest/interpreter/generate-bytecode-expectations.cc |
| +++ b/test/cctest/interpreter/generate-bytecode-expectations.cc |
| @@ -28,6 +28,9 @@ class ProgramOptions { |
| print_help_(false), |
| read_raw_js_snippet_(false), |
| read_from_stdin_(false), |
| + rebaseline_(false), |
| + wrap_(true), |
| + execute_(true), |
| const_pool_type_( |
| BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {} |
| @@ -37,18 +40,30 @@ class ProgramOptions { |
| bool print_help() const { return print_help_; } |
| bool read_raw_js_snippet() const { return read_raw_js_snippet_; } |
| bool read_from_stdin() const { return read_from_stdin_; } |
| - std::string filename() const { return filename_; } |
| + bool rebaseline() const { return rebaseline_; } |
| + bool wrap() const { return wrap_; } |
| + bool execute() const { return execute_; } |
| BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const { |
| return const_pool_type_; |
| } |
| + std::string input_filename() const { return input_filename_; } |
| + std::string output_filename() const { return output_file_name_; } |
| + std::string top_function_name() const { return top_function_name_; } |
| private: |
| bool parsing_failed_; |
| bool print_help_; |
| bool read_raw_js_snippet_; |
| bool read_from_stdin_; |
| + bool rebaseline_; |
| + bool wrap_; |
| + bool execute_; |
| BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_; |
| - std::string filename_; |
| + std::string input_filename_; |
| + std::string output_file_name_; |
| + std::string top_function_name_; |
| + |
| + friend void MaybeUpdateOptionsFromHeader(ProgramOptions*, std::istream&); |
|
rmcilroy
2016/02/17 15:24:08
Don't make this a friend, just add setters for the
Stefano Sanfilippo
2016/02/17 16:40:50
Done.
|
| }; |
| class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator { |
| @@ -95,8 +110,6 @@ BytecodeExpectationsPrinter::ConstantPoolType ParseConstantPoolType( |
| ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) { |
| ProgramOptions options; |
| - if (argc <= 1) return options; |
| - |
| for (int i = 1; i < argc; ++i) { |
| if (strcmp(argv[i], "--help") == 0) { |
| options.print_help_ = true; |
| @@ -106,13 +119,23 @@ ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) { |
| options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12); |
| } else if (strcmp(argv[i], "--stdin") == 0) { |
| options.read_from_stdin_ = true; |
| + } else if (strcmp(argv[i], "--rebaseline") == 0) { |
| + options.rebaseline_ = true; |
| + } else if (strcmp(argv[i], "--no-wrap") == 0) { |
| + options.wrap_ = false; |
| + } else if (strcmp(argv[i], "--no-execute") == 0) { |
| + options.execute_ = false; |
| + } else if (strncmp(argv[i], "--output=", 9) == 0) { |
| + options.output_file_name_ = argv[i] + 9; |
| + } else if (strncmp(argv[i], "--wrapper-name=", 15) == 0) { |
| + options.top_function_name_ = argv[i] + 15; |
| } else if (strncmp(argv[i], "--", 2) != 0) { // It doesn't start with -- |
| - if (!options.filename_.empty()) { |
| + if (!options.input_filename_.empty()) { |
| std::cerr << "ERROR: More than one input file specified\n"; |
| options.parsing_failed_ = true; |
| break; |
| } |
| - options.filename_ = argv[i]; |
| + options.input_filename_ = argv[i]; |
| } else { |
| std::cerr << "ERROR: Unknonwn option " << argv[i] << "\n"; |
| options.parsing_failed_ = true; |
| @@ -123,6 +146,48 @@ ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) { |
| return options; |
| } |
| +bool ParseBoolean(const char* string) { |
| + if (strcmp(string, "yes") == 0) { |
| + return true; |
| + } else if (strcmp(string, "no") == 0) { |
| + return false; |
| + } else { |
| + UNREACHABLE(); |
| + return false; |
| + } |
| +} |
| + |
| +void MaybeUpdateOptionsFromHeader(ProgramOptions* options, |
| + std::istream& stream) { // NOLINT |
| + std::string line; |
| + |
| + if (options->read_raw_js_snippet()) return; |
| + |
| + // Skip to the beginning of the options header |
| + while (std::getline(stream, line)) { |
| + if (line == "---") break; |
| + } |
| + |
| + while (std::getline(stream, line)) { |
| + if (line.compare(0, 11, "pool type: ") == 0) { |
| + options->const_pool_type_ = ParseConstantPoolType(line.c_str() + 11); |
| + } else if (line.compare(0, 9, "execute: ") == 0) { |
| + options->execute_ = ParseBoolean(line.c_str() + 9); |
| + } else if (line.compare(0, 6, "wrap: ") == 0) { |
| + options->wrap_ = ParseBoolean(line.c_str() + 6); |
| + } else if (line.compare(0, 14, "wrapper name: ") == 0) { |
| + options->top_function_name_ = line.c_str() + 14; |
| + } else if (line == "---") { |
| + break; |
| + } else if (line.empty()) { |
| + continue; |
| + } else { |
| + UNREACHABLE(); |
| + return; |
| + } |
| + } |
| +} |
| + |
| bool ProgramOptions::Validate() const { |
| if (parsing_failed_) return false; |
| if (print_help_) return true; |
| @@ -133,16 +198,26 @@ bool ProgramOptions::Validate() const { |
| return false; |
| } |
| - if (!read_from_stdin_ && filename_.empty()) { |
| + if (!read_from_stdin_ && input_filename_.empty()) { |
| std::cerr << "ERROR: No input file specified.\n"; |
| return false; |
| } |
| - if (read_from_stdin_ && !filename_.empty()) { |
| + if (read_from_stdin_ && !input_filename_.empty()) { |
| std::cerr << "ERROR: Reading from stdin, but input files supplied.\n"; |
| return false; |
| } |
| + if (!wrap_ && !top_function_name_.empty()) { |
| + std::cerr << "ERROR: Not wrapping, but wrapper name specified.\n"; |
| + return false; |
| + } |
| + |
| + if (rebaseline_ && read_raw_js_snippet_) { |
| + std::cerr << "ERROR: Cannot use --rebaseline on a raw JS snippet.\n"; |
| + return false; |
| + } |
| + |
| return true; |
| } |
| @@ -194,41 +269,44 @@ bool ReadNextSnippet(std::istream& stream, std::string* string_out) { // NOLINT |
| return false; |
| } |
| -void ExtractSnippetsFromStream(std::vector<std::string>* snippet_list, |
| - std::istream& body_stream, // NOLINT |
| - bool read_raw_js_snippet) { |
| - if (read_raw_js_snippet) { |
| - snippet_list->push_back(ReadRawJSSnippet(body_stream)); |
| - } else { |
| - std::string snippet; |
| - while (ReadNextSnippet(body_stream, &snippet)) { |
| - snippet_list->push_back(snippet); |
| +std::string UnescapeString(const std::string& escaped_string) { |
| + std::string unescaped_string; |
| + bool previous_was_backslash = false; |
| + for (char c : escaped_string) { |
| + if (previous_was_backslash) { |
| + // If it was not an escape sequence, emit the previous backslash |
| + if (c != '\\' && c != '"') unescaped_string += '\\'; |
| + unescaped_string += c; |
| + previous_was_backslash = false; |
| + } else { |
| + if (c == '\\') { |
| + previous_was_backslash = true; |
| + // Defer emission to the point where we can check if it was an escape. |
| + } else { |
| + unescaped_string += c; |
| + } |
| } |
| } |
| + return unescaped_string; |
| } |
| -bool ExtractSnippets(std::vector<std::string>* snippet_list, |
| - const ProgramOptions& options) { |
| - if (options.read_from_stdin()) { |
| - ExtractSnippetsFromStream(snippet_list, std::cin, |
| - options.read_raw_js_snippet()); |
| +void ExtractSnippets(std::vector<std::string>* snippet_list, |
| + std::istream& body_stream, // NOLINT |
| + bool read_raw_js_snippet) { |
| + if (read_raw_js_snippet) { |
| + snippet_list->push_back(ReadRawJSSnippet(body_stream)); |
| } else { |
| - std::ifstream body_file(options.filename().c_str()); |
| - if (!body_file.is_open()) { |
| - std::cerr << "ERROR: Could not open '" << options.filename() << "'.\n"; |
| - return false; |
| + std::string snippet; |
| + while (ReadNextSnippet(body_stream, &snippet)) { |
| + snippet_list->push_back(UnescapeString(snippet)); |
| } |
| - ExtractSnippetsFromStream(snippet_list, body_file, |
| - options.read_raw_js_snippet()); |
| } |
| - return true; |
| } |
| -void GenerateExpectationsFile( |
| - std::ostream& stream, // NOLINT |
| - const std::vector<std::string>& snippet_list, |
| - BytecodeExpectationsPrinter::ConstantPoolType const_pool_type, |
| - const char* exec_path) { |
| +void GenerateExpectationsFile(std::ostream& stream, // NOLINT |
| + const std::vector<std::string>& snippet_list, |
| + const ProgramOptions& options, |
| + const char* exec_path) { |
| V8InitializationScope platform(exec_path); |
| { |
| v8::Isolate::Scope isolate_scope(platform.isolate()); |
| @@ -236,12 +314,15 @@ void GenerateExpectationsFile( |
| v8::Local<v8::Context> context = v8::Context::New(platform.isolate()); |
| v8::Context::Scope context_scope(context); |
| - stream << "#\n# Autogenerated by generate-bytecode-expectations\n#\n\n"; |
| - |
| - BytecodeExpectationsPrinter printer(platform.isolate(), const_pool_type); |
| - for (const std::string& snippet : snippet_list) { |
| - printer.PrintExpectation(stream, snippet); |
| + BytecodeExpectationsPrinter printer(platform.isolate(), |
| + options.const_pool_type()); |
| + printer.set_wrap(options.wrap()); |
| + printer.set_execute(options.execute()); |
| + if (!options.top_function_name().empty()) { |
| + printer.set_top_function_name(options.top_function_name()); |
| } |
| + |
| + printer.PrintExpectationsArray(stream, snippet_list); |
| } |
| } |
| @@ -253,10 +334,19 @@ void PrintUsage(const char* exec_path) { |
| " --help Print this help message.\n" |
| " --raw-js Read raw JavaScript, instead of the output format.\n" |
| " --stdin Read from standard input instead of file.\n" |
| + " --rebaseline Rebaseline input snippet file.\n" |
| + " --no-wrap Do not wrap the snippet in a function.\n" |
| + " --no-execute Do not execute after compilation.\n" |
| + " --wrapper-name=foo Specify the name of the wrapper function.\n" |
| + " --output=file.name\n" |
| + " Specify the output file. If not specified, output goes to " |
| + "stdout.\n" |
| " --pool-type=(int|double|string|mixed)\n" |
| - " specify the type of the entries in the constant pool " |
| + " Specify the type of the entries in the constant pool " |
| "(default: mixed).\n" |
| "\n" |
| + "Flags --no-wrap, --no-execute, --wrapper-name and --pool-type will\n" |
| + "be overridden by the options specified in the input file header.\n\n" |
| "Each raw JavaScript file is interpreted as a single snippet.\n\n" |
| "This tool is intended as a help in writing tests.\n" |
| "Please, DO NOT blindly copy and paste the output " |
| @@ -273,11 +363,37 @@ int main(int argc, char** argv) { |
| return options.print_help() ? 0 : 1; |
| } |
| + std::ifstream body_file; |
| + if (!options.read_from_stdin()) { |
| + body_file.open(options.input_filename().c_str()); |
| + if (!body_file.is_open()) { |
| + std::cerr << "ERROR: Could not open '" << options.input_filename() |
| + << "' for reading.\n"; |
| + return 2; |
| + } |
| + } |
| + |
| + std::istream& body_stream = options.read_from_stdin() ? std::cin : body_file; |
|
rmcilroy
2016/02/17 15:24:08
Extract lines 366-376 into a function which return
Stefano Sanfilippo
2016/02/17 16:40:50
Done. I had to resort to a less elegant way of doi
rmcilroy
2016/02/17 17:06:36
Sorry, when I said go back to the way you were ori
Stefano Sanfilippo
2016/02/17 17:31:18
Done. Sorry for the misunderstanding :)
|
| + MaybeUpdateOptionsFromHeader(&options, body_stream); |
|
rmcilroy
2016/02/17 15:24:08
I would do:
if (options->rebaseline) {
UpdateOp
Stefano Sanfilippo
2016/02/17 16:40:50
Done.
|
| + CHECK(options.Validate()); |
| + |
| std::vector<std::string> snippet_list; |
| - if (!ExtractSnippets(&snippet_list, options)) { |
| - return 2; |
| + ExtractSnippets(&snippet_list, body_file, options.read_raw_js_snippet()); |
| + |
| + bool write_to_stdout = |
| + options.output_filename().empty() && !options.rebaseline(); |
| + |
| + std::ofstream output_file; |
| + if (!write_to_stdout) { |
| + output_file.open(options.rebaseline() ? options.input_filename().c_str() |
| + : options.output_filename().c_str()); |
| + if (!output_file.is_open()) { |
| + std::cerr << "ERROR: Could not open '" << options.output_filename() |
| + << "' for writing.\n"; |
| + return 3; |
| + } |
| } |
|
rmcilroy
2016/02/17 15:24:08
Also pull out the ostream creation to a helper fun
Stefano Sanfilippo
2016/02/17 16:40:50
Done, see above.
|
| - GenerateExpectationsFile(std::cout, snippet_list, options.const_pool_type(), |
| - argv[0]); |
| + std::ostream& output_stream = write_to_stdout ? std::cout : output_file; |
| + GenerateExpectationsFile(output_stream, snippet_list, options, argv[0]); |
| } |