Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: courgette/courgette_tool.cc

Issue 2827103002: [Courgette] Refactor: Add CourgetteFlow; improve courgette_tool.cc help text. (Closed)
Patch Set: More renames, for consistency. Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium 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 <stdarg.h>
5 #include <stddef.h> 6 #include <stddef.h>
6 #include <stdint.h> 7 #include <stdint.h>
7 8
9 #include <initializer_list>
8 #include <memory> 10 #include <memory>
9 #include <string> 11 #include <string>
10 #include <vector> 12 #include <vector>
11 13
12 #include "base/at_exit.h" 14 #include "base/at_exit.h"
13 #include "base/command_line.h" 15 #include "base/command_line.h"
14 #include "base/files/file_path.h" 16 #include "base/files/file_path.h"
15 #include "base/files/file_util.h" 17 #include "base/files/file_util.h"
16 #include "base/files/memory_mapped_file.h" 18 #include "base/files/memory_mapped_file.h"
17 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/macros.h"
18 #include "base/strings/string_number_conversions.h" 21 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h" 22 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h" 23 #include "base/strings/utf_string_conversions.h"
21 #include "courgette/assembly_program.h" 24 #include "courgette/assembly_program.h"
22 #include "courgette/courgette.h" 25 #include "courgette/courgette.h"
26 #include "courgette/courgette_flow.h"
23 #include "courgette/encoded_program.h" 27 #include "courgette/encoded_program.h"
24 #include "courgette/program_detector.h" 28 #include "courgette/program_detector.h"
25 #include "courgette/streams.h" 29 #include "courgette/streams.h"
26 #include "courgette/third_party/bsdiff/bsdiff.h" 30 #include "courgette/third_party/bsdiff/bsdiff.h"
27 31
32 namespace {
33
34 using courgette::CourgetteFlow;
35
36 const char kUsageGen[] = "-gen <old_in> <new_in> <patch_out>";
37 const char kUsageApply[] = "-apply <old_in> <patch_in> <new_out>";
38 const char kUsageGenbsdiff[] = "-genbsdiff <old_in> <new_in> <patch_out>";
39 const char kUsageApplybsdiff[] = "-applybsdiff <old_in> <patch_in> <new_out>";
40 const char kUsageSupported[] = "-supported <exec_file_in>";
41 const char kUsageDis[] = "-dis <exec_file_in> <assembly_file_out>";
42 const char kUsageAsm[] = "-asm <assembly_file_in> <exec_file_out>";
43 const char kUsageDisadj[] = "-disadj <old_in> <new_in> <new_assembly_file_out>";
44 const char kUsageGen1[] = "-gen1[au] <old_in> <new_in> <patch_base_out>";
45
46 /******** Utilities to print help and exit ********/
47
28 void PrintHelp() { 48 void PrintHelp() {
29 fprintf(stderr, 49 fprintf(stderr, "Main Usage:\n");
30 "Usage:\n" 50 for (auto usage :
31 " courgette -supported <executable_file>\n" 51 {kUsageGen, kUsageApply, kUsageGenbsdiff, kUsageApplybsdiff}) {
32 " courgette -dis <executable_file> <binary_assembly_file>\n" 52 fprintf(stderr, " courgette %s\n", usage);
33 " courgette -asm <binary_assembly_file> <executable_file>\n" 53 }
34 " courgette -disadj <executable_file> <reference> <binary_assembly_file>\n" 54 fprintf(stderr, "Diagnosis Usage:\n");
35 " courgette -gen <v1> <v2> <patch>\n" 55 for (auto usage :
36 " courgette -apply <v1> <patch> <v2>\n" 56 {kUsageSupported, kUsageDis, kUsageAsm, kUsageDisadj, kUsageGen1}) {
37 "\n"); 57 fprintf(stderr, " courgette %s\n", usage);
58 }
38 } 59 }
39 60
40 void UsageProblem(const char* message) { 61 void UsageProblem(const char* message) {
41 fprintf(stderr, "%s", message); 62 fprintf(stderr, "%s", message);
42 fprintf(stderr, "\n"); 63 fprintf(stderr, "\n");
43 PrintHelp(); 64 PrintHelp();
44 exit(1); 65 exit(1);
45 } 66 }
46 67
47 void Problem(const char* format, ...) { 68 void Problem(const char* format, ...) {
48 va_list args; 69 va_list args;
49 va_start(args, format); 70 va_start(args, format);
50 vfprintf(stderr, format, args); 71 vfprintf(stderr, format, args);
51 fprintf(stderr, "\n"); 72 fprintf(stderr, "\n");
52 va_end(args); 73 va_end(args);
53 exit(1); 74 exit(1);
54 } 75 }
55 76
77 /******** BufferedFileReader ********/
78
56 // A file reader that calls Problem() on failure. 79 // A file reader that calls Problem() on failure.
57 class BufferedFileReader { 80 class BufferedFileReader : public courgette::BasicBuffer {
58 public: 81 public:
59 BufferedFileReader(const base::FilePath& file_name, const char* kind) { 82 BufferedFileReader(const base::FilePath& file_name, const char* kind) {
60 if (!buffer_.Initialize(file_name)) 83 if (!buffer_.Initialize(file_name))
61 Problem("Can't read %s file.", kind); 84 Problem("Can't read %s file.", kind);
62 } 85 }
63 const uint8_t* data() const { return buffer_.data(); } 86
64 size_t length() const { return buffer_.length(); } 87 // courgette::BasicBuffer:
88 const uint8_t* data() const override { return buffer_.data(); }
89 size_t length() const override { return buffer_.length(); }
65 90
66 private: 91 private:
67 base::MemoryMappedFile buffer_; 92 base::MemoryMappedFile buffer_;
93
94 DISALLOW_COPY_AND_ASSIGN(BufferedFileReader);
68 }; 95 };
69 96
97 /******** Various helpers ********/
98
70 void WriteSinkToFile(const courgette::SinkStream *sink, 99 void WriteSinkToFile(const courgette::SinkStream *sink,
71 const base::FilePath& output_file) { 100 const base::FilePath& output_file) {
72 int count = 101 int count =
73 base::WriteFile(output_file, 102 base::WriteFile(output_file,
74 reinterpret_cast<const char*>(sink->Buffer()), 103 reinterpret_cast<const char*>(sink->Buffer()),
75 static_cast<int>(sink->Length())); 104 static_cast<int>(sink->Length()));
76 if (count == -1) 105 if (count == -1)
77 Problem("Can't write output."); 106 Problem("Can't write output.");
78 if (static_cast<size_t>(count) != sink->Length()) 107 if (static_cast<size_t>(count) != sink->Length())
79 Problem("Incomplete write."); 108 Problem("Incomplete write.");
80 } 109 }
81 110
82 void Disassemble(const base::FilePath& input_file,
83 const base::FilePath& output_file) {
84 BufferedFileReader buffer(input_file, "input");
85
86 std::unique_ptr<courgette::AssemblyProgram> program;
87 const courgette::Status parse_status = courgette::ParseDetectedExecutable(
88 buffer.data(), buffer.length(), &program);
89 if (parse_status != courgette::C_OK)
90 Problem("Can't parse input (code = %d).", parse_status);
91
92 std::unique_ptr<courgette::EncodedProgram> encoded;
93 const courgette::Status encode_status = Encode(*program, &encoded);
94 if (encode_status != courgette::C_OK)
95 Problem("Can't encode program.");
96
97 program.reset();
98
99 courgette::SinkStreamSet sinks;
100 const courgette::Status write_status =
101 courgette::WriteEncodedProgram(encoded.get(), &sinks);
102 if (write_status != courgette::C_OK)
103 Problem("Can't serialize encoded program.");
104
105 encoded.reset();
106
107 courgette::SinkStream sink;
108 if (!sinks.CopyTo(&sink))
109 Problem("Can't combine serialized encoded program streams.");
110
111 WriteSinkToFile(&sink, output_file);
112 }
113
114 bool Supported(const base::FilePath& input_file) { 111 bool Supported(const base::FilePath& input_file) {
115 bool result = false; 112 bool result = false;
116 113
117 BufferedFileReader buffer(input_file, "input"); 114 BufferedFileReader buffer(input_file, "input");
118 115
119 courgette::ExecutableType type; 116 courgette::ExecutableType type;
120 size_t detected_length; 117 size_t detected_length;
121 118
122 DetectExecutableType(buffer.data(), buffer.length(), &type, &detected_length); 119 DetectExecutableType(buffer.data(), buffer.length(), &type, &detected_length);
123 120
(...skipping 22 matching lines...) Expand all
146 case courgette::EXE_WIN_32_X64: 143 case courgette::EXE_WIN_32_X64:
147 format = "Windows 64 PE"; 144 format = "Windows 64 PE";
148 result = true; 145 result = true;
149 break; 146 break;
150 } 147 }
151 148
152 printf("%s Executable\n", format.c_str()); 149 printf("%s Executable\n", format.c_str());
153 return result; 150 return result;
154 } 151 }
155 152
156 void DisassembleAndAdjust(const base::FilePath& program_file, 153 void Disassemble(const base::FilePath& input_file,
157 const base::FilePath& model_file, 154 const base::FilePath& output_file) {
158 const base::FilePath& output_file) { 155 CourgetteFlow flow;
159 BufferedFileReader program_buffer(program_file, "program"); 156 BufferedFileReader input_buffer(input_file, flow.name(flow.ONLY));
160 BufferedFileReader model_buffer(model_file, "model"); 157 flow.ReadAssemblyProgramFromBuffer(flow.ONLY, input_buffer, false);
161 158 flow.CreateEncodedProgramFromAssemblyProgram(flow.ONLY);
162 std::unique_ptr<courgette::AssemblyProgram> program; 159 flow.DestroyAssemblyProgram(flow.ONLY);
163 const courgette::Status parse_program_status = 160 flow.WriteSinkStreamSetFromEncodedProgram(flow.ONLY);
164 courgette::ParseDetectedExecutable(program_buffer.data(), 161 flow.DestroyEncodedProgram(flow.ONLY);
165 program_buffer.length(), &program);
166 if (parse_program_status != courgette::C_OK)
167 Problem("Can't parse program input (code = %d).", parse_program_status);
168
169 std::unique_ptr<courgette::AssemblyProgram> model;
170 const courgette::Status parse_model_status =
171 courgette::ParseDetectedExecutable(model_buffer.data(),
172 model_buffer.length(), &model);
173 if (parse_model_status != courgette::C_OK)
174 Problem("Can't parse model input (code = %d).", parse_model_status);
175
176 const courgette::Status adjust_status = Adjust(*model, program.get());
177 if (adjust_status != courgette::C_OK)
178 Problem("Can't adjust program.");
179
180 model.reset();
181
182 std::unique_ptr<courgette::EncodedProgram> encoded;
183 const courgette::Status encode_status = Encode(*program, &encoded);
184 if (encode_status != courgette::C_OK)
185 Problem("Can't encode program.");
186
187 program.reset();
188
189 courgette::SinkStreamSet sinks;
190 const courgette::Status write_status =
191 courgette::WriteEncodedProgram(encoded.get(), &sinks);
192 if (write_status != courgette::C_OK)
193 Problem("Can't serialize encoded program.");
194
195 encoded.reset();
196
197 courgette::SinkStream sink; 162 courgette::SinkStream sink;
198 if (!sinks.CopyTo(&sink)) 163 flow.WriteSinkStreamFromSinkStreamSet(flow.ONLY, &sink);
199 Problem("Can't combine serialized encoded program streams."); 164 if (flow.failed())
165 Problem(flow.message().c_str());
200 166
201 WriteSinkToFile(&sink, output_file); 167 WriteSinkToFile(&sink, output_file);
chrisha 2017/04/24 18:15:50 Does this still need to happen, even if failed() i
huangs 2017/04/24 20:08:14 Problem() calls exit(1), so on failure this will n
202 } 168 }
169
170 void DisassembleAndAdjust(const base::FilePath& old_file,
171 const base::FilePath& new_file,
172 const base::FilePath& output_file) {
173 CourgetteFlow flow;
174 BufferedFileReader old_buffer(old_file, flow.name(flow.OLD));
175 BufferedFileReader new_buffer(new_file, flow.name(flow.NEW));
176 flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, true);
177 flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, true);
178 flow.AdjustNewAssemblyProgramToMatchOld();
179 flow.DestroyAssemblyProgram(flow.OLD);
180 flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW);
181 flow.DestroyAssemblyProgram(flow.NEW);
182 flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW);
183 flow.DestroyEncodedProgram(flow.NEW);
184 courgette::SinkStream sink;
185 flow.WriteSinkStreamFromSinkStreamSet(flow.NEW, &sink);
186 if (flow.failed())
187 Problem(flow.message().c_str());
188
189 WriteSinkToFile(&sink, output_file);
190 }
203 191
204 // Diffs two executable files, write a set of files for the diff, one file per 192 // Diffs two executable files, write a set of files for the diff, one file per
205 // stream of the EncodedProgram format. Each file is the bsdiff between the 193 // stream of the EncodedProgram format. Each file is the bsdiff between the
206 // original file's stream and the new file's stream. This is completely 194 // original file's stream and the new file's stream. This is completely
207 // uninteresting to users, but it is handy for seeing how much each which 195 // uninteresting to users, but it is handy for seeing how much each which
208 // streams are contributing to the final file size. Adjustment is optional. 196 // streams are contributing to the final file size. Adjustment is optional.
209 void DisassembleAdjustDiff(const base::FilePath& model_file, 197 void DisassembleAdjustDiff(const base::FilePath& old_file,
210 const base::FilePath& program_file, 198 const base::FilePath& new_file,
211 const base::FilePath& output_file_root, 199 const base::FilePath& output_file_root,
212 bool adjust) { 200 bool adjust) {
213 BufferedFileReader model_buffer(model_file, "old"); 201 CourgetteFlow flow;
214 BufferedFileReader program_buffer(program_file, "new"); 202 BufferedFileReader old_buffer(old_file, flow.name(flow.OLD));
215 203 BufferedFileReader new_buffer(new_file, flow.name(flow.NEW));
216 auto parser = adjust ? courgette::ParseDetectedExecutableWithAnnotation 204 flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, adjust);
217 : courgette::ParseDetectedExecutable; 205 flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, adjust);
218 206 if (adjust)
219 std::unique_ptr<courgette::AssemblyProgram> model; 207 flow.AdjustNewAssemblyProgramToMatchOld();
220 const courgette::Status parse_model_status = 208 flow.CreateEncodedProgramFromAssemblyProgram(flow.OLD);
221 parser(model_buffer.data(), model_buffer.length(), &model); 209 flow.DestroyAssemblyProgram(flow.OLD);
222 if (parse_model_status != courgette::C_OK) 210 flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW);
223 Problem("Can't parse model input (code = %d).", parse_model_status); 211 flow.DestroyAssemblyProgram(flow.NEW);
224 212 flow.WriteSinkStreamSetFromEncodedProgram(flow.OLD);
225 std::unique_ptr<courgette::AssemblyProgram> program; 213 flow.DestroyEncodedProgram(flow.OLD);
226 const courgette::Status parse_program_status = 214 flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW);
227 parser(program_buffer.data(), program_buffer.length(), &program); 215 flow.DestroyEncodedProgram(flow.NEW);
228 if (parse_program_status != courgette::C_OK) 216 if (flow.failed())
229 Problem("Can't parse program input (code = %d).", parse_program_status); 217 Problem(flow.message().c_str());
230
231 if (adjust) {
232 const courgette::Status adjust_status = Adjust(*model, program.get());
233 if (adjust_status != courgette::C_OK)
234 Problem("Can't adjust program.");
235 }
236
237 std::unique_ptr<courgette::EncodedProgram> encoded_program;
238 const courgette::Status encode_program_status =
239 Encode(*program, &encoded_program);
240 if (encode_program_status != courgette::C_OK)
241 Problem("Can't encode program.");
242
243 program.reset();
244
245 std::unique_ptr<courgette::EncodedProgram> encoded_model;
246 const courgette::Status encode_model_status = Encode(*model, &encoded_model);
247 if (encode_model_status != courgette::C_OK)
248 Problem("Can't encode model.");
249
250 model.reset();
251
252 courgette::SinkStreamSet program_sinks;
253 const courgette::Status write_program_status =
254 courgette::WriteEncodedProgram(encoded_program.get(), &program_sinks);
255 if (write_program_status != courgette::C_OK)
256 Problem("Can't serialize encoded program.");
257
258 encoded_program.reset();
259
260 courgette::SinkStreamSet model_sinks;
261 const courgette::Status write_model_status =
262 courgette::WriteEncodedProgram(encoded_model.get(), &model_sinks);
263 if (write_model_status != courgette::C_OK)
264 Problem("Can't serialize encoded model.");
265
266 encoded_model.reset();
267 218
268 courgette::SinkStream empty_sink; 219 courgette::SinkStream empty_sink;
269 for (int i = 0; ; ++i) { 220 for (int i = 0; ; ++i) {
270 courgette::SinkStream* old_stream = model_sinks.stream(i); 221 courgette::SinkStream* old_stream = flow.data(flow.OLD)->sinks.stream(i);
271 courgette::SinkStream* new_stream = program_sinks.stream(i); 222 courgette::SinkStream* new_stream = flow.data(flow.NEW)->sinks.stream(i);
272 if (old_stream == NULL && new_stream == NULL) 223 if (old_stream == NULL && new_stream == NULL)
273 break; 224 break;
274 225
275 courgette::SourceStream old_source; 226 courgette::SourceStream old_source;
276 courgette::SourceStream new_source; 227 courgette::SourceStream new_source;
277 old_source.Init(old_stream ? *old_stream : empty_sink); 228 old_source.Init(old_stream ? *old_stream : empty_sink);
278 new_source.Init(new_stream ? *new_stream : empty_sink); 229 new_source.Init(new_stream ? *new_stream : empty_sink);
279 courgette::SinkStream patch_stream; 230 courgette::SinkStream patch_stream;
280 bsdiff::BSDiffStatus status = 231 bsdiff::BSDiffStatus status =
281 bsdiff::CreateBinaryPatch(&old_source, &new_source, &patch_stream); 232 bsdiff::CreateBinaryPatch(&old_source, &new_source, &patch_stream);
282 if (status != bsdiff::OK) 233 if (status != bsdiff::OK)
283 Problem("-xxx failed."); 234 Problem("-xxx failed.");
284 235
285 std::string append = std::string("-") + base::IntToString(i); 236 std::string append = std::string("-") + base::IntToString(i);
286 237
287 WriteSinkToFile(&patch_stream, 238 WriteSinkToFile(&patch_stream,
288 output_file_root.InsertBeforeExtensionASCII(append)); 239 output_file_root.InsertBeforeExtensionASCII(append));
289 } 240 }
290 } 241 }
291 242
292 void Assemble(const base::FilePath& input_file, 243 void Assemble(const base::FilePath& input_file,
293 const base::FilePath& output_file) { 244 const base::FilePath& output_file) {
294 BufferedFileReader buffer(input_file, "input"); 245 CourgetteFlow flow;
295 246 BufferedFileReader input_buffer(input_file, flow.name(flow.ONLY));
296 courgette::SourceStreamSet sources; 247 flow.ReadSourceStreamSetFromBuffer(flow.ONLY, input_buffer);
297 if (!sources.Init(buffer.data(), buffer.length())) 248 flow.ReadEncodedProgramFromSourceStreamSet(flow.ONLY);
298 Problem("Bad input file.");
299
300 std::unique_ptr<courgette::EncodedProgram> encoded;
301 const courgette::Status read_status =
302 courgette::ReadEncodedProgram(&sources, &encoded);
303 if (read_status != courgette::C_OK)
304 Problem("Bad encoded program.");
305
306 courgette::SinkStream sink; 249 courgette::SinkStream sink;
307 250 flow.WriteExecutableFromEncodedProgram(flow.ONLY, &sink);
308 const courgette::Status assemble_status = 251 if (flow.failed())
309 courgette::Assemble(encoded.get(), &sink); 252 Problem(flow.message().c_str());
310 if (assemble_status != courgette::C_OK)
311 Problem("Can't assemble.");
312 253
313 WriteSinkToFile(&sink, output_file); 254 WriteSinkToFile(&sink, output_file);
314 } 255 }
315 256
316 void GenerateEnsemblePatch(const base::FilePath& old_file, 257 void GenerateEnsemblePatch(const base::FilePath& old_file,
317 const base::FilePath& new_file, 258 const base::FilePath& new_file,
318 const base::FilePath& patch_file) { 259 const base::FilePath& patch_file) {
319 BufferedFileReader old_buffer(old_file, "'old' input"); 260 BufferedFileReader old_buffer(old_file, "'old' input");
320 BufferedFileReader new_buffer(new_file, "'new' input"); 261 BufferedFileReader new_buffer(new_file, "'new' input");
321 262
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 courgette::SinkStream new_stream; 364 courgette::SinkStream new_stream;
424 bsdiff::BSDiffStatus status = 365 bsdiff::BSDiffStatus status =
425 bsdiff::ApplyBinaryPatch(&old_stream, &patch_stream, &new_stream); 366 bsdiff::ApplyBinaryPatch(&old_stream, &patch_stream, &new_stream);
426 367
427 if (status != bsdiff::OK) 368 if (status != bsdiff::OK)
428 Problem("-applybsdiff failed."); 369 Problem("-applybsdiff failed.");
429 370
430 WriteSinkToFile(&new_stream, new_file); 371 WriteSinkToFile(&new_stream, new_file);
431 } 372 }
432 373
374 } // namespace
375
433 int main(int argc, const char* argv[]) { 376 int main(int argc, const char* argv[]) {
434 base::AtExitManager at_exit_manager; 377 base::AtExitManager at_exit_manager;
435 base::CommandLine::Init(argc, argv); 378 base::CommandLine::Init(argc, argv);
436 const base::CommandLine& command_line = 379 const base::CommandLine& command_line =
437 *base::CommandLine::ForCurrentProcess(); 380 *base::CommandLine::ForCurrentProcess();
438 381
439 logging::LoggingSettings settings; 382 logging::LoggingSettings settings;
440 settings.logging_dest = logging::LOG_TO_ALL; 383 settings.logging_dest = logging::LOG_TO_ALL;
441 settings.log_file = FILE_PATH_LITERAL("courgette.log"); 384 settings.log_file = FILE_PATH_LITERAL("courgette.log");
442 (void)logging::InitLogging(settings); 385 (void)logging::InitLogging(settings);
(...skipping 18 matching lines...) Expand all
461 404
462 // '-repeat=N' is for debugging. Running many iterations can reveal leaks and 405 // '-repeat=N' is for debugging. Running many iterations can reveal leaks and
463 // bugs in cleanup. 406 // bugs in cleanup.
464 int repeat_count = 1; 407 int repeat_count = 1;
465 std::string repeat_switch = command_line.GetSwitchValueASCII("repeat"); 408 std::string repeat_switch = command_line.GetSwitchValueASCII("repeat");
466 if (!repeat_switch.empty()) 409 if (!repeat_switch.empty())
467 if (!base::StringToInt(repeat_switch, &repeat_count)) 410 if (!base::StringToInt(repeat_switch, &repeat_count))
468 repeat_count = 1; 411 repeat_count = 1;
469 412
470 if (cmd_sup + cmd_dis + cmd_asm + cmd_disadj + cmd_make_patch + 413 if (cmd_sup + cmd_dis + cmd_asm + cmd_disadj + cmd_make_patch +
471 cmd_apply_patch + cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch + 414 cmd_apply_patch + cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch +
472 cmd_spread_1_adjusted + cmd_spread_1_unadjusted 415 cmd_spread_1_adjusted + cmd_spread_1_unadjusted !=
473 != 1) 416 1) {
474 UsageProblem( 417 UsageProblem(
475 "Must have exactly one of:\n" 418 "First argument must be one of:\n"
476 " -supported -asm, -dis, -disadj, -gen or -apply, -genbsdiff" 419 " -supported, -asm, -dis, -disadj, -gen, -apply, -genbsdiff,"
477 " or -applybsdiff."); 420 " -applybsdiff, or -gen1[au].");
421 }
478 422
479 while (repeat_count-- > 0) { 423 while (repeat_count-- > 0) {
480 if (cmd_sup) { 424 if (cmd_sup) {
481 if (values.size() != 1) 425 if (values.size() != 1)
482 UsageProblem("-supported <executable_file>"); 426 UsageProblem(kUsageSupported);
483 return !Supported(values[0]); 427 return !Supported(values[0]);
484 } else if (cmd_dis) { 428 } else if (cmd_dis) {
485 if (values.size() != 2) 429 if (values.size() != 2)
486 UsageProblem("-dis <executable_file> <courgette_file>"); 430 UsageProblem(kUsageDis);
487 Disassemble(values[0], values[1]); 431 Disassemble(values[0], values[1]);
488 } else if (cmd_asm) { 432 } else if (cmd_asm) {
489 if (values.size() != 2) 433 if (values.size() != 2)
490 UsageProblem("-asm <courgette_file_input> <executable_file_output>"); 434 UsageProblem(kUsageAsm);
491 Assemble(values[0], values[1]); 435 Assemble(values[0], values[1]);
492 } else if (cmd_disadj) { 436 } else if (cmd_disadj) {
493 if (values.size() != 3) 437 if (values.size() != 3)
494 UsageProblem("-disadj <executable_file> <model> <courgette_file>"); 438 UsageProblem(kUsageDisadj);
495 DisassembleAndAdjust(values[0], values[1], values[2]); 439 DisassembleAndAdjust(values[0], values[1], values[2]);
496 } else if (cmd_make_patch) { 440 } else if (cmd_make_patch) {
497 if (values.size() != 3) 441 if (values.size() != 3)
498 UsageProblem("-gen <old_file> <new_file> <patch_file>"); 442 UsageProblem(kUsageGen);
499 GenerateEnsemblePatch(values[0], values[1], values[2]); 443 GenerateEnsemblePatch(values[0], values[1], values[2]);
500 } else if (cmd_apply_patch) { 444 } else if (cmd_apply_patch) {
501 if (values.size() != 3) 445 if (values.size() != 3)
502 UsageProblem("-apply <old_file> <patch_file> <new_file>"); 446 UsageProblem(kUsageApply);
503 ApplyEnsemblePatch(values[0], values[1], values[2]); 447 ApplyEnsemblePatch(values[0], values[1], values[2]);
504 } else if (cmd_make_bsdiff_patch) { 448 } else if (cmd_make_bsdiff_patch) {
505 if (values.size() != 3) 449 if (values.size() != 3)
506 UsageProblem("-genbsdiff <old_file> <new_file> <patch_file>"); 450 UsageProblem(kUsageGenbsdiff);
507 GenerateBSDiffPatch(values[0], values[1], values[2]); 451 GenerateBSDiffPatch(values[0], values[1], values[2]);
508 } else if (cmd_apply_bsdiff_patch) { 452 } else if (cmd_apply_bsdiff_patch) {
509 if (values.size() != 3) 453 if (values.size() != 3)
510 UsageProblem("-applybsdiff <old_file> <patch_file> <new_file>"); 454 UsageProblem(kUsageApplybsdiff);
511 ApplyBSDiffPatch(values[0], values[1], values[2]); 455 ApplyBSDiffPatch(values[0], values[1], values[2]);
512 } else if (cmd_spread_1_adjusted || cmd_spread_1_unadjusted) { 456 } else if (cmd_spread_1_adjusted || cmd_spread_1_unadjusted) {
513 if (values.size() != 3) 457 if (values.size() != 3)
514 UsageProblem("-gen1[au] <old_file> <new_file> <patch_files_root>"); 458 UsageProblem(kUsageGen1);
515 DisassembleAdjustDiff(values[0], values[1], values[2], 459 DisassembleAdjustDiff(values[0], values[1], values[2],
516 cmd_spread_1_adjusted); 460 cmd_spread_1_adjusted);
517 } else { 461 } else {
518 UsageProblem("No operation specified"); 462 UsageProblem("No operation specified");
519 } 463 }
520 } 464 }
521 465
522 return 0; 466 return 0;
523 } 467 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698