blob: 53f2e3fce3e532731d5220e19d8b19e0a8c0647a [file] [log] [blame]
Ben Murdoch097c5b22016-05-18 11:27:45 +01001// Copyright 2016 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <cstring>
6#include <fstream>
Ben Murdochda12d292016-06-02 14:46:10 +01007#include <vector>
Ben Murdoch097c5b22016-05-18 11:27:45 +01008
9#include "test/cctest/interpreter/bytecode-expectations-printer.h"
10
11#include "include/libplatform/libplatform.h"
12#include "include/v8.h"
13
14#include "src/base/logging.h"
15#include "src/base/smart-pointers.h"
16#include "src/compiler.h"
17#include "src/interpreter/interpreter.h"
18
Ben Murdochda12d292016-06-02 14:46:10 +010019#ifdef V8_OS_POSIX
20#include <dirent.h>
21#endif
22
Ben Murdoch097c5b22016-05-18 11:27:45 +010023using v8::internal::interpreter::BytecodeExpectationsPrinter;
24
Ben Murdochda12d292016-06-02 14:46:10 +010025#define REPORT_ERROR(MESSAGE) (((std::cerr << "ERROR: ") << MESSAGE) << '\n')
26
Ben Murdoch097c5b22016-05-18 11:27:45 +010027namespace {
28
Ben Murdochda12d292016-06-02 14:46:10 +010029#ifdef V8_OS_POSIX
30const char* kGoldenFilesPath = "test/cctest/interpreter/bytecode_expectations/";
31#endif
32
Ben Murdoch097c5b22016-05-18 11:27:45 +010033class ProgramOptions final {
34 public:
35 static ProgramOptions FromCommandLine(int argc, char** argv);
36
37 ProgramOptions()
38 : parsing_failed_(false),
39 print_help_(false),
40 read_raw_js_snippet_(false),
41 read_from_stdin_(false),
42 rebaseline_(false),
43 wrap_(true),
44 execute_(true),
45 top_level_(false),
Ben Murdoch097c5b22016-05-18 11:27:45 +010046 do_expressions_(false),
Ben Murdochc5610432016-08-08 18:44:38 +010047 ignition_generators_(false),
Ben Murdochda12d292016-06-02 14:46:10 +010048 verbose_(false),
Ben Murdoch097c5b22016-05-18 11:27:45 +010049 const_pool_type_(
50 BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {}
51
52 bool Validate() const;
53 void UpdateFromHeader(std::istream& stream); // NOLINT
54 void PrintHeader(std::ostream& stream) const; // NOLINT
55
56 bool parsing_failed() const { return parsing_failed_; }
57 bool print_help() const { return print_help_; }
58 bool read_raw_js_snippet() const { return read_raw_js_snippet_; }
59 bool read_from_stdin() const { return read_from_stdin_; }
60 bool write_to_stdout() const {
61 return output_filename_.empty() && !rebaseline_;
62 }
63 bool rebaseline() const { return rebaseline_; }
64 bool wrap() const { return wrap_; }
65 bool execute() const { return execute_; }
66 bool top_level() const { return top_level_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +010067 bool do_expressions() const { return do_expressions_; }
Ben Murdochc5610432016-08-08 18:44:38 +010068 bool ignition_generators() const { return ignition_generators_; }
Ben Murdochda12d292016-06-02 14:46:10 +010069 bool verbose() const { return verbose_; }
70 bool suppress_runtime_errors() const { return rebaseline_ && !verbose_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +010071 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const {
72 return const_pool_type_;
73 }
Ben Murdochda12d292016-06-02 14:46:10 +010074 std::vector<std::string> input_filenames() const { return input_filenames_; }
Ben Murdoch097c5b22016-05-18 11:27:45 +010075 std::string output_filename() const { return output_filename_; }
76 std::string test_function_name() const { return test_function_name_; }
77
78 private:
79 bool parsing_failed_;
80 bool print_help_;
81 bool read_raw_js_snippet_;
82 bool read_from_stdin_;
83 bool rebaseline_;
84 bool wrap_;
85 bool execute_;
86 bool top_level_;
Ben Murdoch097c5b22016-05-18 11:27:45 +010087 bool do_expressions_;
Ben Murdochc5610432016-08-08 18:44:38 +010088 bool ignition_generators_;
Ben Murdochda12d292016-06-02 14:46:10 +010089 bool verbose_;
Ben Murdoch097c5b22016-05-18 11:27:45 +010090 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_;
Ben Murdochda12d292016-06-02 14:46:10 +010091 std::vector<std::string> input_filenames_;
Ben Murdoch097c5b22016-05-18 11:27:45 +010092 std::string output_filename_;
93 std::string test_function_name_;
94};
95
96class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator {
97 public:
98 void* Allocate(size_t length) override {
99 void* data = AllocateUninitialized(length);
100 if (data != nullptr) memset(data, 0, length);
101 return data;
102 }
103 void* AllocateUninitialized(size_t length) override { return malloc(length); }
104 void Free(void* data, size_t) override { free(data); }
105};
106
107class V8InitializationScope final {
108 public:
109 explicit V8InitializationScope(const char* exec_path);
110 ~V8InitializationScope();
111
112 v8::Platform* platform() const { return platform_.get(); }
113 v8::Isolate* isolate() const { return isolate_; }
114
115 private:
116 v8::base::SmartPointer<v8::Platform> platform_;
117 v8::Isolate* isolate_;
118
119 DISALLOW_COPY_AND_ASSIGN(V8InitializationScope);
120};
121
122BytecodeExpectationsPrinter::ConstantPoolType ParseConstantPoolType(
123 const char* type_string) {
124 if (strcmp(type_string, "number") == 0) {
125 return BytecodeExpectationsPrinter::ConstantPoolType::kNumber;
126 } else if (strcmp(type_string, "string") == 0) {
127 return BytecodeExpectationsPrinter::ConstantPoolType::kString;
128 } else if (strcmp(type_string, "mixed") == 0) {
129 return BytecodeExpectationsPrinter::ConstantPoolType::kMixed;
130 }
131 return BytecodeExpectationsPrinter::ConstantPoolType::kUnknown;
132}
133
134const char* ConstantPoolTypeToString(
135 BytecodeExpectationsPrinter::ConstantPoolType type) {
136 switch (type) {
137 case BytecodeExpectationsPrinter::ConstantPoolType::kNumber:
138 return "number";
139 case BytecodeExpectationsPrinter::ConstantPoolType::kMixed:
140 return "mixed";
141 case BytecodeExpectationsPrinter::ConstantPoolType::kString:
142 return "string";
143 default:
144 UNREACHABLE();
145 return nullptr;
146 }
147}
148
149bool ParseBoolean(const char* string) {
150 if (strcmp(string, "yes") == 0) {
151 return true;
152 } else if (strcmp(string, "no") == 0) {
153 return false;
154 } else {
155 UNREACHABLE();
156 return false;
157 }
158}
159
160const char* BooleanToString(bool value) { return value ? "yes" : "no"; }
161
Ben Murdochda12d292016-06-02 14:46:10 +0100162#ifdef V8_OS_POSIX
163
164bool StrEndsWith(const char* string, const char* suffix) {
165 int string_size = i::StrLength(string);
166 int suffix_size = i::StrLength(suffix);
167 if (string_size < suffix_size) return false;
168
169 return strcmp(string + (string_size - suffix_size), suffix) == 0;
170}
171
172bool CollectGoldenFiles(std::vector<std::string>* golden_file_list,
173 const char* directory_path) {
174 DIR* directory = opendir(directory_path);
175 if (!directory) return false;
176
177 dirent entry_buffer;
178 dirent* entry;
179
180 while (readdir_r(directory, &entry_buffer, &entry) == 0 && entry) {
181 if (StrEndsWith(entry->d_name, ".golden")) {
182 std::string golden_filename(kGoldenFilesPath);
183 golden_filename += entry->d_name;
184 golden_file_list->push_back(golden_filename);
185 }
186 }
187
188 closedir(directory);
189
190 return true;
191}
192
193#endif // V8_OS_POSIX
194
Ben Murdoch097c5b22016-05-18 11:27:45 +0100195// static
196ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) {
197 ProgramOptions options;
198
199 for (int i = 1; i < argc; ++i) {
200 if (strcmp(argv[i], "--help") == 0) {
201 options.print_help_ = true;
202 } else if (strcmp(argv[i], "--raw-js") == 0) {
203 options.read_raw_js_snippet_ = true;
204 } else if (strncmp(argv[i], "--pool-type=", 12) == 0) {
205 options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12);
206 } else if (strcmp(argv[i], "--stdin") == 0) {
207 options.read_from_stdin_ = true;
208 } else if (strcmp(argv[i], "--rebaseline") == 0) {
209 options.rebaseline_ = true;
210 } else if (strcmp(argv[i], "--no-wrap") == 0) {
211 options.wrap_ = false;
212 } else if (strcmp(argv[i], "--no-execute") == 0) {
213 options.execute_ = false;
214 } else if (strcmp(argv[i], "--top-level") == 0) {
215 options.top_level_ = true;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100216 } else if (strcmp(argv[i], "--do-expressions") == 0) {
217 options.do_expressions_ = true;
Ben Murdochc5610432016-08-08 18:44:38 +0100218 } else if (strcmp(argv[i], "--ignition-generators") == 0) {
219 options.ignition_generators_ = true;
Ben Murdochda12d292016-06-02 14:46:10 +0100220 } else if (strcmp(argv[i], "--verbose") == 0) {
221 options.verbose_ = true;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100222 } else if (strncmp(argv[i], "--output=", 9) == 0) {
223 options.output_filename_ = argv[i] + 9;
224 } else if (strncmp(argv[i], "--test-function-name=", 21) == 0) {
225 options.test_function_name_ = argv[i] + 21;
226 } else if (strncmp(argv[i], "--", 2) != 0) { // It doesn't start with --
Ben Murdochda12d292016-06-02 14:46:10 +0100227 options.input_filenames_.push_back(argv[i]);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100228 } else {
Ben Murdochda12d292016-06-02 14:46:10 +0100229 REPORT_ERROR("Unknown option " << argv[i]);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100230 options.parsing_failed_ = true;
231 break;
232 }
233 }
234
Ben Murdochda12d292016-06-02 14:46:10 +0100235 if (options.rebaseline_ && options.input_filenames_.empty()) {
236#ifdef V8_OS_POSIX
237 if (options.verbose_) {
238 std::cout << "Looking for golden files in " << kGoldenFilesPath << '\n';
239 }
240 if (!CollectGoldenFiles(&options.input_filenames_, kGoldenFilesPath)) {
241 REPORT_ERROR("Golden files autodiscovery failed.");
242 options.parsing_failed_ = true;
243 }
244#else
245 REPORT_ERROR("Golden files autodiscovery requires a POSIX OS, sorry.");
246 options.parsing_failed_ = true;
247#endif
248 }
249
Ben Murdoch097c5b22016-05-18 11:27:45 +0100250 return options;
251}
252
253bool ProgramOptions::Validate() const {
254 if (parsing_failed_) return false;
255 if (print_help_) return true;
256
257 if (const_pool_type_ ==
258 BytecodeExpectationsPrinter::ConstantPoolType::kUnknown) {
Ben Murdochda12d292016-06-02 14:46:10 +0100259 REPORT_ERROR("Unknown constant pool type.");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100260 return false;
261 }
262
Ben Murdochda12d292016-06-02 14:46:10 +0100263 if (!read_from_stdin_ && input_filenames_.empty()) {
264 REPORT_ERROR("No input file specified.");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100265 return false;
266 }
267
Ben Murdochda12d292016-06-02 14:46:10 +0100268 if (read_from_stdin_ && !input_filenames_.empty()) {
269 REPORT_ERROR("Reading from stdin, but input files supplied.");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100270 return false;
271 }
272
273 if (rebaseline_ && read_raw_js_snippet_) {
Ben Murdochda12d292016-06-02 14:46:10 +0100274 REPORT_ERROR("Cannot use --rebaseline on a raw JS snippet.");
275 return false;
276 }
277
278 if (rebaseline_ && !output_filename_.empty()) {
279 REPORT_ERROR("Output file cannot be specified together with --rebaseline.");
280 return false;
281 }
282
283 if (rebaseline_ && read_from_stdin_) {
284 REPORT_ERROR("Cannot --rebaseline when input is --stdin.");
285 return false;
286 }
287
288 if (input_filenames_.size() > 1 && !rebaseline_ && !read_raw_js_snippet()) {
289 REPORT_ERROR(
290 "Multiple input files, but no --rebaseline or --raw-js specified.");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100291 return false;
292 }
293
294 if (top_level_ && !test_function_name_.empty()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100295 REPORT_ERROR(
296 "Test function name specified while processing top level code.");
Ben Murdoch097c5b22016-05-18 11:27:45 +0100297 return false;
298 }
299
300 return true;
301}
302
303void ProgramOptions::UpdateFromHeader(std::istream& stream) {
304 std::string line;
305
306 // Skip to the beginning of the options header
307 while (std::getline(stream, line)) {
308 if (line == "---") break;
309 }
310
311 while (std::getline(stream, line)) {
312 if (line.compare(0, 11, "pool type: ") == 0) {
313 const_pool_type_ = ParseConstantPoolType(line.c_str() + 11);
314 } else if (line.compare(0, 9, "execute: ") == 0) {
315 execute_ = ParseBoolean(line.c_str() + 9);
316 } else if (line.compare(0, 6, "wrap: ") == 0) {
317 wrap_ = ParseBoolean(line.c_str() + 6);
318 } else if (line.compare(0, 20, "test function name: ") == 0) {
319 test_function_name_ = line.c_str() + 20;
320 } else if (line.compare(0, 11, "top level: ") == 0) {
321 top_level_ = ParseBoolean(line.c_str() + 11);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100322 } else if (line.compare(0, 16, "do expressions: ") == 0) {
323 do_expressions_ = ParseBoolean(line.c_str() + 16);
Ben Murdochc5610432016-08-08 18:44:38 +0100324 } else if (line.compare(0, 21, "ignition generators: ") == 0) {
325 ignition_generators_ = ParseBoolean(line.c_str() + 21);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100326 } else if (line == "---") {
327 break;
328 } else if (line.empty()) {
329 continue;
330 } else {
331 UNREACHABLE();
332 return;
333 }
334 }
335}
336
337void ProgramOptions::PrintHeader(std::ostream& stream) const { // NOLINT
338 stream << "---"
339 "\npool type: "
340 << ConstantPoolTypeToString(const_pool_type_)
341 << "\nexecute: " << BooleanToString(execute_)
342 << "\nwrap: " << BooleanToString(wrap_);
343
344 if (!test_function_name_.empty()) {
345 stream << "\ntest function name: " << test_function_name_;
346 }
347
348 if (top_level_) stream << "\ntop level: yes";
Ben Murdoch097c5b22016-05-18 11:27:45 +0100349 if (do_expressions_) stream << "\ndo expressions: yes";
Ben Murdochc5610432016-08-08 18:44:38 +0100350 if (ignition_generators_) stream << "\nignition generators: yes";
Ben Murdoch097c5b22016-05-18 11:27:45 +0100351
352 stream << "\n\n";
353}
354
355V8InitializationScope::V8InitializationScope(const char* exec_path)
356 : platform_(v8::platform::CreateDefaultPlatform()) {
357 i::FLAG_ignition = true;
358 i::FLAG_always_opt = false;
359 i::FLAG_allow_natives_syntax = true;
360
Ben Murdoch61f157c2016-09-16 13:49:30 +0100361 v8::V8::InitializeICUDefaultLocation(exec_path);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100362 v8::V8::InitializeExternalStartupData(exec_path);
363 v8::V8::InitializePlatform(platform_.get());
364 v8::V8::Initialize();
365
366 ArrayBufferAllocator allocator;
367 v8::Isolate::CreateParams create_params;
368 create_params.array_buffer_allocator = &allocator;
369
370 isolate_ = v8::Isolate::New(create_params);
371}
372
373V8InitializationScope::~V8InitializationScope() {
374 isolate_->Dispose();
375 v8::V8::Dispose();
376 v8::V8::ShutdownPlatform();
377}
378
379std::string ReadRawJSSnippet(std::istream& stream) { // NOLINT
380 std::stringstream body_buffer;
381 CHECK(body_buffer << stream.rdbuf());
382 return body_buffer.str();
383}
384
385bool ReadNextSnippet(std::istream& stream, std::string* string_out) { // NOLINT
386 std::string line;
387 bool found_begin_snippet = false;
388 string_out->clear();
389 while (std::getline(stream, line)) {
390 if (line == "snippet: \"") {
391 found_begin_snippet = true;
392 continue;
393 }
394 if (!found_begin_snippet) continue;
395 if (line == "\"") return true;
396 CHECK_GE(line.size(), 2u); // We should have the indent
397 string_out->append(line.begin() + 2, line.end());
398 *string_out += '\n';
399 }
400 return false;
401}
402
403std::string UnescapeString(const std::string& escaped_string) {
404 std::string unescaped_string;
405 bool previous_was_backslash = false;
406 for (char c : escaped_string) {
407 if (previous_was_backslash) {
408 // If it was not an escape sequence, emit the previous backslash
409 if (c != '\\' && c != '"') unescaped_string += '\\';
410 unescaped_string += c;
411 previous_was_backslash = false;
412 } else {
413 if (c == '\\') {
414 previous_was_backslash = true;
415 // Defer emission to the point where we can check if it was an escape.
416 } else {
417 unescaped_string += c;
418 }
419 }
420 }
421 return unescaped_string;
422}
423
424void ExtractSnippets(std::vector<std::string>* snippet_list,
425 std::istream& body_stream, // NOLINT
426 bool read_raw_js_snippet) {
427 if (read_raw_js_snippet) {
428 snippet_list->push_back(ReadRawJSSnippet(body_stream));
429 } else {
430 std::string snippet;
431 while (ReadNextSnippet(body_stream, &snippet)) {
432 snippet_list->push_back(UnescapeString(snippet));
433 }
434 }
435}
436
437void GenerateExpectationsFile(std::ostream& stream, // NOLINT
438 const std::vector<std::string>& snippet_list,
Ben Murdochda12d292016-06-02 14:46:10 +0100439 const V8InitializationScope& platform,
440 const ProgramOptions& options) {
441 v8::Isolate::Scope isolate_scope(platform.isolate());
442 v8::HandleScope handle_scope(platform.isolate());
443 v8::Local<v8::Context> context = v8::Context::New(platform.isolate());
444 v8::Context::Scope context_scope(context);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100445
Ben Murdochda12d292016-06-02 14:46:10 +0100446 BytecodeExpectationsPrinter printer(platform.isolate(),
447 options.const_pool_type());
448 printer.set_wrap(options.wrap());
449 printer.set_execute(options.execute());
450 printer.set_top_level(options.top_level());
451 if (!options.test_function_name().empty()) {
452 printer.set_test_function_name(options.test_function_name());
453 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100454
Ben Murdochda12d292016-06-02 14:46:10 +0100455 if (options.do_expressions()) i::FLAG_harmony_do_expressions = true;
Ben Murdochc5610432016-08-08 18:44:38 +0100456 if (options.ignition_generators()) i::FLAG_ignition_generators = true;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100457
Ben Murdochda12d292016-06-02 14:46:10 +0100458 stream << "#\n# Autogenerated by generate-bytecode-expectations.\n#\n\n";
459 options.PrintHeader(stream);
460 for (const std::string& snippet : snippet_list) {
461 printer.PrintExpectation(stream, snippet);
462 }
463
464 i::FLAG_harmony_do_expressions = false;
465}
466
467bool WriteExpectationsFile(const std::vector<std::string>& snippet_list,
468 const V8InitializationScope& platform,
469 const ProgramOptions& options,
470 const std::string& output_filename) {
471 std::ofstream output_file_handle;
472 if (!options.write_to_stdout()) {
473 output_file_handle.open(output_filename.c_str());
474 if (!output_file_handle.is_open()) {
475 REPORT_ERROR("Could not open " << output_filename << " for writing.");
476 return false;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100477 }
478 }
Ben Murdochda12d292016-06-02 14:46:10 +0100479 std::ostream& output_stream =
480 options.write_to_stdout() ? std::cout : output_file_handle;
481
482 GenerateExpectationsFile(output_stream, snippet_list, platform, options);
483
484 return true;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100485}
486
Ben Murdochda12d292016-06-02 14:46:10 +0100487void PrintMessage(v8::Local<v8::Message> message, v8::Local<v8::Value>) {
488 std::cerr << "INFO: " << *v8::String::Utf8Value(message->Get()) << '\n';
489}
490
491void DiscardMessage(v8::Local<v8::Message>, v8::Local<v8::Value>) {}
492
Ben Murdoch097c5b22016-05-18 11:27:45 +0100493void PrintUsage(const char* exec_path) {
494 std::cerr
495 << "\nUsage: " << exec_path
Ben Murdochda12d292016-06-02 14:46:10 +0100496 << " [OPTIONS]... [INPUT FILES]...\n\n"
Ben Murdoch097c5b22016-05-18 11:27:45 +0100497 "Options:\n"
498 " --help Print this help message.\n"
Ben Murdochda12d292016-06-02 14:46:10 +0100499 " --verbose Emit messages about the progress of the tool.\n"
Ben Murdoch097c5b22016-05-18 11:27:45 +0100500 " --raw-js Read raw JavaScript, instead of the output format.\n"
501 " --stdin Read from standard input instead of file.\n"
502 " --rebaseline Rebaseline input snippet file.\n"
503 " --no-wrap Do not wrap the snippet in a function.\n"
504 " --no-execute Do not execute after compilation.\n"
505 " --test-function-name=foo "
506 "Specify the name of the test function.\n"
Ben Murdochda12d292016-06-02 14:46:10 +0100507 " --top-level Process top level code, not the top-level function.\n"
Ben Murdoch097c5b22016-05-18 11:27:45 +0100508 " --do-expressions Enable harmony_do_expressions flag.\n"
Ben Murdochc5610432016-08-08 18:44:38 +0100509 " --ignition-generators Enable ignition_generators flag.\n"
Ben Murdoch097c5b22016-05-18 11:27:45 +0100510 " --output=file.name\n"
511 " Specify the output file. If not specified, output goes to "
512 "stdout.\n"
513 " --pool-type=(number|string|mixed)\n"
514 " Specify the type of the entries in the constant pool "
515 "(default: mixed).\n"
516 "\n"
517 "When using --rebaseline, flags --no-wrap, --no-execute, "
518 "--test-function-name\nand --pool-type will be overridden by the "
519 "options specified in the input file\nheader.\n\n"
520 "Each raw JavaScript file is interpreted as a single snippet.\n\n"
521 "This tool is intended as a help in writing tests.\n"
522 "Please, DO NOT blindly copy and paste the output "
523 "into the test suite.\n";
524}
525
526} // namespace
527
528int main(int argc, char** argv) {
529 ProgramOptions options = ProgramOptions::FromCommandLine(argc, argv);
530
531 if (!options.Validate() || options.print_help()) {
532 PrintUsage(argv[0]);
533 return options.print_help() ? 0 : 1;
534 }
535
Ben Murdochda12d292016-06-02 14:46:10 +0100536 V8InitializationScope platform(argv[0]);
537 platform.isolate()->AddMessageListener(
538 options.suppress_runtime_errors() ? DiscardMessage : PrintMessage);
Ben Murdoch097c5b22016-05-18 11:27:45 +0100539
540 std::vector<std::string> snippet_list;
Ben Murdoch097c5b22016-05-18 11:27:45 +0100541
Ben Murdochda12d292016-06-02 14:46:10 +0100542 if (options.read_from_stdin()) {
543 // Rebaseline will never get here, so we will always take the
544 // GenerateExpectationsFile at the end of this function.
545 DCHECK(!options.rebaseline());
546 ExtractSnippets(&snippet_list, std::cin, options.read_raw_js_snippet());
547 } else {
548 for (const std::string& input_filename : options.input_filenames()) {
549 if (options.verbose()) {
550 std::cerr << "Processing " << input_filename << '\n';
551 }
552
553 std::ifstream input_stream(input_filename.c_str());
554 if (!input_stream.is_open()) {
555 REPORT_ERROR("Could not open " << input_filename << " for reading.");
556 return 2;
557 }
558
559 ProgramOptions updated_options = options;
560 if (options.rebaseline()) {
561 updated_options.UpdateFromHeader(input_stream);
562 CHECK(updated_options.Validate());
563 }
564
565 ExtractSnippets(&snippet_list, input_stream,
566 options.read_raw_js_snippet());
567
568 if (options.rebaseline()) {
569 if (!WriteExpectationsFile(snippet_list, platform, updated_options,
570 input_filename)) {
571 return 3;
572 }
573 snippet_list.clear();
574 }
575 }
576 }
577
578 if (!options.rebaseline()) {
579 if (!WriteExpectationsFile(snippet_list, platform, options,
580 options.output_filename())) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100581 return 3;
582 }
583 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100584}