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]); |
} |