Chromium Code Reviews| OLD | NEW | 
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include <cstring> | 5 #include <cstring> | 
| 6 #include <fstream> | 6 #include <fstream> | 
| 7 | 7 | 
| 8 #include "test/cctest/interpreter/bytecode-expectations-printer.h" | 8 #include "test/cctest/interpreter/bytecode-expectations-printer.h" | 
| 9 | 9 | 
| 10 #include "include/libplatform/libplatform.h" | 10 #include "include/libplatform/libplatform.h" | 
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 | 21 | 
| 22 class ProgramOptions { | 22 class ProgramOptions { | 
| 23 public: | 23 public: | 
| 24 static ProgramOptions FromCommandLine(int argc, char** argv); | 24 static ProgramOptions FromCommandLine(int argc, char** argv); | 
| 25 | 25 | 
| 26 ProgramOptions() | 26 ProgramOptions() | 
| 27 : parsing_failed_(false), | 27 : parsing_failed_(false), | 
| 28 print_help_(false), | 28 print_help_(false), | 
| 29 read_raw_js_snippet_(false), | 29 read_raw_js_snippet_(false), | 
| 30 read_from_stdin_(false), | 30 read_from_stdin_(false), | 
| 31 rebaseline_(false), | |
| 32 wrap_(true), | |
| 33 execute_(true), | |
| 31 const_pool_type_( | 34 const_pool_type_( | 
| 32 BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {} | 35 BytecodeExpectationsPrinter::ConstantPoolType::kMixed) {} | 
| 33 | 36 | 
| 34 bool Validate() const; | 37 bool Validate() const; | 
| 35 | 38 | 
| 36 bool parsing_failed() const { return parsing_failed_; } | 39 bool parsing_failed() const { return parsing_failed_; } | 
| 37 bool print_help() const { return print_help_; } | 40 bool print_help() const { return print_help_; } | 
| 38 bool read_raw_js_snippet() const { return read_raw_js_snippet_; } | 41 bool read_raw_js_snippet() const { return read_raw_js_snippet_; } | 
| 39 bool read_from_stdin() const { return read_from_stdin_; } | 42 bool read_from_stdin() const { return read_from_stdin_; } | 
| 40 std::string filename() const { return filename_; } | 43 bool write_to_stdout() const { | 
| 44 return output_filename_.empty() && !rebaseline_; | |
| 45 } | |
| 46 bool rebaseline() const { return rebaseline_; } | |
| 47 bool wrap() const { return wrap_; } | |
| 48 bool execute() const { return execute_; } | |
| 41 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const { | 49 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type() const { | 
| 42 return const_pool_type_; | 50 return const_pool_type_; | 
| 43 } | 51 } | 
| 52 std::string input_filename() const { return input_filename_; } | |
| 53 std::string output_filename() const { return output_filename_; } | |
| 54 std::string top_function_name() const { return top_function_name_; } | |
| 55 | |
| 56 void set_const_pool_type( | |
| 57 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type) { | |
| 58 const_pool_type_ = const_pool_type; | |
| 59 } | |
| 60 void set_execute(bool execute) { execute_ = execute; } | |
| 61 void set_wrap(bool wrap) { wrap_ = wrap; } | |
| 62 void set_top_function_name(const std::string& top_function_name) { | |
| 63 top_function_name_ = top_function_name; | |
| 64 } | |
| 44 | 65 | 
| 45 private: | 66 private: | 
| 46 bool parsing_failed_; | 67 bool parsing_failed_; | 
| 47 bool print_help_; | 68 bool print_help_; | 
| 48 bool read_raw_js_snippet_; | 69 bool read_raw_js_snippet_; | 
| 49 bool read_from_stdin_; | 70 bool read_from_stdin_; | 
| 71 bool rebaseline_; | |
| 72 bool wrap_; | |
| 73 bool execute_; | |
| 50 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_; | 74 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type_; | 
| 51 std::string filename_; | 75 std::string input_filename_; | 
| 76 std::string output_filename_; | |
| 77 std::string top_function_name_; | |
| 52 }; | 78 }; | 
| 53 | 79 | 
| 54 class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator { | 80 class ArrayBufferAllocator final : public v8::ArrayBuffer::Allocator { | 
| 55 public: | 81 public: | 
| 56 void* Allocate(size_t length) override { | 82 void* Allocate(size_t length) override { | 
| 57 void* data = AllocateUninitialized(length); | 83 void* data = AllocateUninitialized(length); | 
| 58 if (data != nullptr) memset(data, 0, length); | 84 if (data != nullptr) memset(data, 0, length); | 
| 59 return data; | 85 return data; | 
| 60 } | 86 } | 
| 61 void* AllocateUninitialized(size_t length) override { return malloc(length); } | 87 void* AllocateUninitialized(size_t length) override { return malloc(length); } | 
| (...skipping 26 matching lines...) Expand all Loading... | |
| 88 } else if (strcmp(type_string, "mixed") == 0) { | 114 } else if (strcmp(type_string, "mixed") == 0) { | 
| 89 return BytecodeExpectationsPrinter::ConstantPoolType::kMixed; | 115 return BytecodeExpectationsPrinter::ConstantPoolType::kMixed; | 
| 90 } | 116 } | 
| 91 return BytecodeExpectationsPrinter::ConstantPoolType::kUnknown; | 117 return BytecodeExpectationsPrinter::ConstantPoolType::kUnknown; | 
| 92 } | 118 } | 
| 93 | 119 | 
| 94 // static | 120 // static | 
| 95 ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) { | 121 ProgramOptions ProgramOptions::FromCommandLine(int argc, char** argv) { | 
| 96 ProgramOptions options; | 122 ProgramOptions options; | 
| 97 | 123 | 
| 98 if (argc <= 1) return options; | |
| 99 | |
| 100 for (int i = 1; i < argc; ++i) { | 124 for (int i = 1; i < argc; ++i) { | 
| 101 if (strcmp(argv[i], "--help") == 0) { | 125 if (strcmp(argv[i], "--help") == 0) { | 
| 102 options.print_help_ = true; | 126 options.print_help_ = true; | 
| 103 } else if (strcmp(argv[i], "--raw-js") == 0) { | 127 } else if (strcmp(argv[i], "--raw-js") == 0) { | 
| 104 options.read_raw_js_snippet_ = true; | 128 options.read_raw_js_snippet_ = true; | 
| 105 } else if (strncmp(argv[i], "--pool-type=", 12) == 0) { | 129 } else if (strncmp(argv[i], "--pool-type=", 12) == 0) { | 
| 106 options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12); | 130 options.const_pool_type_ = ParseConstantPoolType(argv[i] + 12); | 
| 107 } else if (strcmp(argv[i], "--stdin") == 0) { | 131 } else if (strcmp(argv[i], "--stdin") == 0) { | 
| 108 options.read_from_stdin_ = true; | 132 options.read_from_stdin_ = true; | 
| 133 } else if (strcmp(argv[i], "--rebaseline") == 0) { | |
| 134 options.rebaseline_ = true; | |
| 135 } else if (strcmp(argv[i], "--no-wrap") == 0) { | |
| 136 options.wrap_ = false; | |
| 137 } else if (strcmp(argv[i], "--no-execute") == 0) { | |
| 138 options.execute_ = false; | |
| 139 } else if (strncmp(argv[i], "--output=", 9) == 0) { | |
| 140 options.output_filename_ = argv[i] + 9; | |
| 141 } else if (strncmp(argv[i], "--wrapper-name=", 15) == 0) { | |
| 142 options.top_function_name_ = argv[i] + 15; | |
| 109 } else if (strncmp(argv[i], "--", 2) != 0) { // It doesn't start with -- | 143 } else if (strncmp(argv[i], "--", 2) != 0) { // It doesn't start with -- | 
| 110 if (!options.filename_.empty()) { | 144 if (!options.input_filename_.empty()) { | 
| 111 std::cerr << "ERROR: More than one input file specified\n"; | 145 std::cerr << "ERROR: More than one input file specified\n"; | 
| 112 options.parsing_failed_ = true; | 146 options.parsing_failed_ = true; | 
| 113 break; | 147 break; | 
| 114 } | 148 } | 
| 115 options.filename_ = argv[i]; | 149 options.input_filename_ = argv[i]; | 
| 116 } else { | 150 } else { | 
| 117 std::cerr << "ERROR: Unknonwn option " << argv[i] << "\n"; | 151 std::cerr << "ERROR: Unknonwn option " << argv[i] << "\n"; | 
| 118 options.parsing_failed_ = true; | 152 options.parsing_failed_ = true; | 
| 119 break; | 153 break; | 
| 120 } | 154 } | 
| 121 } | 155 } | 
| 122 | 156 | 
| 123 return options; | 157 return options; | 
| 124 } | 158 } | 
| 125 | 159 | 
| 160 bool ParseBoolean(const char* string) { | |
| 161 if (strcmp(string, "yes") == 0) { | |
| 162 return true; | |
| 163 } else if (strcmp(string, "no") == 0) { | |
| 164 return false; | |
| 165 } else { | |
| 166 UNREACHABLE(); | |
| 167 return false; | |
| 168 } | |
| 169 } | |
| 170 | |
| 171 void UpdateOptionsFromHeader(ProgramOptions* options, | |
| 
 
rmcilroy
2016/02/18 09:58:33
Nit - make this a member function of ProgramOption
 
Stefano Sanfilippo
2016/02/18 11:14:12
Done.
 
 | |
| 172 std::istream& stream) { // NOLINT | |
| 173 std::string line; | |
| 174 | |
| 175 // Skip to the beginning of the options header | |
| 176 while (std::getline(stream, line)) { | |
| 177 if (line == "---") break; | |
| 178 } | |
| 179 | |
| 180 while (std::getline(stream, line)) { | |
| 181 if (line.compare(0, 11, "pool type: ") == 0) { | |
| 182 options->set_const_pool_type(ParseConstantPoolType(line.c_str() + 11)); | |
| 183 } else if (line.compare(0, 9, "execute: ") == 0) { | |
| 184 options->set_execute(ParseBoolean(line.c_str() + 9)); | |
| 185 } else if (line.compare(0, 6, "wrap: ") == 0) { | |
| 186 options->set_wrap(ParseBoolean(line.c_str() + 6)); | |
| 187 } else if (line.compare(0, 14, "wrapper name: ") == 0) { | |
| 188 options->set_top_function_name(line.c_str() + 14); | |
| 189 } else if (line == "---") { | |
| 190 break; | |
| 191 } else if (line.empty()) { | |
| 192 continue; | |
| 193 } else { | |
| 194 UNREACHABLE(); | |
| 195 return; | |
| 196 } | |
| 197 } | |
| 198 } | |
| 199 | |
| 126 bool ProgramOptions::Validate() const { | 200 bool ProgramOptions::Validate() const { | 
| 127 if (parsing_failed_) return false; | 201 if (parsing_failed_) return false; | 
| 128 if (print_help_) return true; | 202 if (print_help_) return true; | 
| 129 | 203 | 
| 130 if (const_pool_type_ == | 204 if (const_pool_type_ == | 
| 131 BytecodeExpectationsPrinter::ConstantPoolType::kUnknown) { | 205 BytecodeExpectationsPrinter::ConstantPoolType::kUnknown) { | 
| 132 std::cerr << "ERROR: Unknown constant pool type.\n"; | 206 std::cerr << "ERROR: Unknown constant pool type.\n"; | 
| 133 return false; | 207 return false; | 
| 134 } | 208 } | 
| 135 | 209 | 
| 136 if (!read_from_stdin_ && filename_.empty()) { | 210 if (!read_from_stdin_ && input_filename_.empty()) { | 
| 137 std::cerr << "ERROR: No input file specified.\n"; | 211 std::cerr << "ERROR: No input file specified.\n"; | 
| 138 return false; | 212 return false; | 
| 139 } | 213 } | 
| 140 | 214 | 
| 141 if (read_from_stdin_ && !filename_.empty()) { | 215 if (read_from_stdin_ && !input_filename_.empty()) { | 
| 142 std::cerr << "ERROR: Reading from stdin, but input files supplied.\n"; | 216 std::cerr << "ERROR: Reading from stdin, but input files supplied.\n"; | 
| 143 return false; | 217 return false; | 
| 144 } | 218 } | 
| 145 | 219 | 
| 220 if (!wrap_ && !top_function_name_.empty()) { | |
| 221 std::cerr << "ERROR: Not wrapping, but wrapper name specified.\n"; | |
| 222 return false; | |
| 223 } | |
| 224 | |
| 225 if (rebaseline_ && read_raw_js_snippet_) { | |
| 226 std::cerr << "ERROR: Cannot use --rebaseline on a raw JS snippet.\n"; | |
| 227 return false; | |
| 228 } | |
| 229 | |
| 146 return true; | 230 return true; | 
| 147 } | 231 } | 
| 148 | 232 | 
| 149 V8InitializationScope::V8InitializationScope(const char* exec_path) | 233 V8InitializationScope::V8InitializationScope(const char* exec_path) | 
| 150 : platform_(v8::platform::CreateDefaultPlatform()) { | 234 : platform_(v8::platform::CreateDefaultPlatform()) { | 
| 151 i::FLAG_ignition = true; | 235 i::FLAG_ignition = true; | 
| 152 i::FLAG_always_opt = false; | 236 i::FLAG_always_opt = false; | 
| 153 i::FLAG_allow_natives_syntax = true; | 237 i::FLAG_allow_natives_syntax = true; | 
| 154 | 238 | 
| 155 v8::V8::InitializeICU(); | 239 v8::V8::InitializeICU(); | 
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 187 } | 271 } | 
| 188 if (!found_begin_snippet) continue; | 272 if (!found_begin_snippet) continue; | 
| 189 if (line == "\"") return true; | 273 if (line == "\"") return true; | 
| 190 CHECK_GE(line.size(), 2u); // We should have the indent | 274 CHECK_GE(line.size(), 2u); // We should have the indent | 
| 191 string_out->append(line.begin() + 2, line.end()); | 275 string_out->append(line.begin() + 2, line.end()); | 
| 192 *string_out += '\n'; | 276 *string_out += '\n'; | 
| 193 } | 277 } | 
| 194 return false; | 278 return false; | 
| 195 } | 279 } | 
| 196 | 280 | 
| 197 void ExtractSnippetsFromStream(std::vector<std::string>* snippet_list, | 281 std::string UnescapeString(const std::string& escaped_string) { | 
| 198 std::istream& body_stream, // NOLINT | 282 std::string unescaped_string; | 
| 199 bool read_raw_js_snippet) { | 283 bool previous_was_backslash = false; | 
| 284 for (char c : escaped_string) { | |
| 285 if (previous_was_backslash) { | |
| 286 // If it was not an escape sequence, emit the previous backslash | |
| 287 if (c != '\\' && c != '"') unescaped_string += '\\'; | |
| 288 unescaped_string += c; | |
| 289 previous_was_backslash = false; | |
| 290 } else { | |
| 291 if (c == '\\') { | |
| 292 previous_was_backslash = true; | |
| 293 // Defer emission to the point where we can check if it was an escape. | |
| 294 } else { | |
| 295 unescaped_string += c; | |
| 296 } | |
| 297 } | |
| 298 } | |
| 299 return unescaped_string; | |
| 300 } | |
| 301 | |
| 302 void ExtractSnippets(std::vector<std::string>* snippet_list, | |
| 303 std::istream& body_stream, // NOLINT | |
| 304 bool read_raw_js_snippet) { | |
| 200 if (read_raw_js_snippet) { | 305 if (read_raw_js_snippet) { | 
| 201 snippet_list->push_back(ReadRawJSSnippet(body_stream)); | 306 snippet_list->push_back(ReadRawJSSnippet(body_stream)); | 
| 202 } else { | 307 } else { | 
| 203 std::string snippet; | 308 std::string snippet; | 
| 204 while (ReadNextSnippet(body_stream, &snippet)) { | 309 while (ReadNextSnippet(body_stream, &snippet)) { | 
| 205 snippet_list->push_back(snippet); | 310 snippet_list->push_back(UnescapeString(snippet)); | 
| 206 } | 311 } | 
| 207 } | 312 } | 
| 208 } | 313 } | 
| 209 | 314 | 
| 210 bool ExtractSnippets(std::vector<std::string>* snippet_list, | 315 const char* ConstantPoolTypeToString( | 
| 211 const ProgramOptions& options) { | 316 BytecodeExpectationsPrinter::ConstantPoolType type) { | 
| 212 if (options.read_from_stdin()) { | 317 switch (type) { | 
| 213 ExtractSnippetsFromStream(snippet_list, std::cin, | 318 case BytecodeExpectationsPrinter::ConstantPoolType::kDouble: | 
| 214 options.read_raw_js_snippet()); | 319 return "double"; | 
| 215 } else { | 320 case BytecodeExpectationsPrinter::ConstantPoolType::kInteger: | 
| 216 std::ifstream body_file(options.filename().c_str()); | 321 return "integer"; | 
| 217 if (!body_file.is_open()) { | 322 case BytecodeExpectationsPrinter::ConstantPoolType::kMixed: | 
| 218 std::cerr << "ERROR: Could not open '" << options.filename() << "'.\n"; | 323 return "mixed"; | 
| 219 return false; | 324 case BytecodeExpectationsPrinter::ConstantPoolType::kString: | 
| 220 } | 325 return "string"; | 
| 221 ExtractSnippetsFromStream(snippet_list, body_file, | 326 default: | 
| 222 options.read_raw_js_snippet()); | 327 UNREACHABLE(); | 
| 328 return nullptr; | |
| 223 } | 329 } | 
| 224 return true; | |
| 225 } | 330 } | 
| 226 | 331 | 
| 227 void GenerateExpectationsFile( | 332 const char* BooleanToString(bool value) { return value ? "yes" : "no"; } | 
| 228 std::ostream& stream, // NOLINT | 333 | 
| 229 const std::vector<std::string>& snippet_list, | 334 void PrintOptionsHeader(std::ostream& stream, // NOLINT, | 
| 
 
rmcilroy
2016/02/18 09:58:33
Also make this a member on ProgramOptions and call
 
Stefano Sanfilippo
2016/02/18 11:14:12
Done the first part. I have grouped helpers at the
 
 | |
| 230 BytecodeExpectationsPrinter::ConstantPoolType const_pool_type, | 335 const ProgramOptions& options) { | 
| 231 const char* exec_path) { | 336 stream << "---" | 
| 337 "\npool type: " | |
| 338 << ConstantPoolTypeToString(options.const_pool_type()) | |
| 339 << "\nexecute: " << BooleanToString(options.execute()) | |
| 340 << "\nwrap: " << BooleanToString(options.wrap()); | |
| 341 | |
| 342 if (!options.top_function_name().empty()) { | |
| 343 stream << "\nwrapper name: " << options.top_function_name(); | |
| 344 } | |
| 345 | |
| 346 stream << "\n\n"; | |
| 347 } | |
| 348 | |
| 349 void GenerateExpectationsFile(std::ostream& stream, // NOLINT | |
| 350 const std::vector<std::string>& snippet_list, | |
| 351 const ProgramOptions& options, | |
| 352 const char* exec_path) { | |
| 232 V8InitializationScope platform(exec_path); | 353 V8InitializationScope platform(exec_path); | 
| 233 { | 354 { | 
| 234 v8::Isolate::Scope isolate_scope(platform.isolate()); | 355 v8::Isolate::Scope isolate_scope(platform.isolate()); | 
| 235 v8::HandleScope handle_scope(platform.isolate()); | 356 v8::HandleScope handle_scope(platform.isolate()); | 
| 236 v8::Local<v8::Context> context = v8::Context::New(platform.isolate()); | 357 v8::Local<v8::Context> context = v8::Context::New(platform.isolate()); | 
| 237 v8::Context::Scope context_scope(context); | 358 v8::Context::Scope context_scope(context); | 
| 238 | 359 | 
| 360 BytecodeExpectationsPrinter printer(platform.isolate(), | |
| 361 options.const_pool_type()); | |
| 362 printer.set_wrap(options.wrap()); | |
| 363 printer.set_execute(options.execute()); | |
| 364 if (!options.top_function_name().empty()) { | |
| 365 printer.set_top_function_name(options.top_function_name()); | |
| 366 } | |
| 367 | |
| 239 stream << "#\n# Autogenerated by generate-bytecode-expectations\n#\n\n"; | 368 stream << "#\n# Autogenerated by generate-bytecode-expectations\n#\n\n"; | 
| 240 | 369 PrintOptionsHeader(stream, options); | 
| 241 BytecodeExpectationsPrinter printer(platform.isolate(), const_pool_type); | |
| 242 for (const std::string& snippet : snippet_list) { | 370 for (const std::string& snippet : snippet_list) { | 
| 243 printer.PrintExpectation(stream, snippet); | 371 printer.PrintExpectation(stream, snippet); | 
| 244 } | 372 } | 
| 245 } | 373 } | 
| 246 } | 374 } | 
| 247 | 375 | 
| 248 void PrintUsage(const char* exec_path) { | 376 void PrintUsage(const char* exec_path) { | 
| 249 std::cerr | 377 std::cerr | 
| 250 << "\nUsage: " << exec_path | 378 << "\nUsage: " << exec_path | 
| 251 << " [OPTIONS]... [INPUT FILE]\n\n" | 379 << " [OPTIONS]... [INPUT FILE]\n\n" | 
| 252 "Options:\n" | 380 "Options:\n" | 
| 253 " --help Print this help message.\n" | 381 " --help Print this help message.\n" | 
| 254 " --raw-js Read raw JavaScript, instead of the output format.\n" | 382 " --raw-js Read raw JavaScript, instead of the output format.\n" | 
| 255 " --stdin Read from standard input instead of file.\n" | 383 " --stdin Read from standard input instead of file.\n" | 
| 384 " --rebaseline Rebaseline input snippet file.\n" | |
| 385 " --no-wrap Do not wrap the snippet in a function.\n" | |
| 386 " --no-execute Do not execute after compilation.\n" | |
| 387 " --wrapper-name=foo Specify the name of the wrapper function.\n" | |
| 388 " --output=file.name\n" | |
| 389 " Specify the output file. If not specified, output goes to " | |
| 390 "stdout.\n" | |
| 256 " --pool-type=(int|double|string|mixed)\n" | 391 " --pool-type=(int|double|string|mixed)\n" | 
| 257 " specify the type of the entries in the constant pool " | 392 " Specify the type of the entries in the constant pool " | 
| 258 "(default: mixed).\n" | 393 "(default: mixed).\n" | 
| 259 "\n" | 394 "\n" | 
| 395 "When using --rebaseline, flags --no-wrap, --no-execute, " | |
| 396 "--wrapper-name and \n--pool-type will be overridden by the options " | |
| 397 "specified in the input file\n" | |
| 398 "header.\n\n" | |
| 260 "Each raw JavaScript file is interpreted as a single snippet.\n\n" | 399 "Each raw JavaScript file is interpreted as a single snippet.\n\n" | 
| 261 "This tool is intended as a help in writing tests.\n" | 400 "This tool is intended as a help in writing tests.\n" | 
| 262 "Please, DO NOT blindly copy and paste the output " | 401 "Please, DO NOT blindly copy and paste the output " | 
| 263 "into the test suite.\n"; | 402 "into the test suite.\n"; | 
| 264 } | 403 } | 
| 265 | 404 | 
| 266 } // namespace | 405 } // namespace | 
| 267 | 406 | 
| 268 int main(int argc, char** argv) { | 407 int main(int argc, char** argv) { | 
| 269 ProgramOptions options = ProgramOptions::FromCommandLine(argc, argv); | 408 ProgramOptions options = ProgramOptions::FromCommandLine(argc, argv); | 
| 270 | 409 | 
| 271 if (!options.Validate() || options.print_help()) { | 410 if (!options.Validate() || options.print_help()) { | 
| 272 PrintUsage(argv[0]); | 411 PrintUsage(argv[0]); | 
| 273 return options.print_help() ? 0 : 1; | 412 return options.print_help() ? 0 : 1; | 
| 274 } | 413 } | 
| 275 | 414 | 
| 415 std::ifstream input_file_handle; | |
| 416 if (!options.read_from_stdin()) { | |
| 417 input_file_handle.open(options.input_filename().c_str()); | |
| 418 if (!input_file_handle.is_open()) { | |
| 419 std::cerr << "ERROR: Could not open '" << options.input_filename() | |
| 420 << "' for reading.\n"; | |
| 421 return 2; | |
| 422 } | |
| 423 } | |
| 424 std::istream& input_stream = | |
| 425 options.read_from_stdin() ? std::cin : input_file_handle; | |
| 426 | |
| 427 if (!options.rebaseline()) { | |
| 428 UpdateOptionsFromHeader(&options, input_stream); | |
| 429 } | |
| 430 CHECK(options.Validate()); | |
| 431 | |
| 276 std::vector<std::string> snippet_list; | 432 std::vector<std::string> snippet_list; | 
| 277 if (!ExtractSnippets(&snippet_list, options)) { | 433 ExtractSnippets(&snippet_list, input_stream, options.read_raw_js_snippet()); | 
| 278 return 2; | 434 | 
| 435 std::ofstream output_file_handle; | |
| 436 if (!options.write_to_stdout()) { | |
| 437 output_file_handle.open(options.rebaseline() | |
| 438 ? options.input_filename().c_str() | |
| 439 : options.output_filename().c_str()); | |
| 440 if (!output_file_handle.is_open()) { | |
| 441 std::cerr << "ERROR: Could not open '" << options.output_filename() | |
| 442 << "' for writing.\n"; | |
| 443 return 3; | |
| 444 } | |
| 279 } | 445 } | 
| 446 std::ostream& output_stream = | |
| 447 options.write_to_stdout() ? std::cout : output_file_handle; | |
| 280 | 448 | 
| 281 GenerateExpectationsFile(std::cout, snippet_list, options.const_pool_type(), | 449 GenerateExpectationsFile(output_stream, snippet_list, options, argv[0]); | 
| 282 argv[0]); | |
| 283 } | 450 } | 
| OLD | NEW |