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