OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/command_line.h" | 5 #include "base/command_line.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 23 matching lines...) Expand all Loading... | |
34 const wchar_t kSwitchTerminator[] = L"--"; | 34 const wchar_t kSwitchTerminator[] = L"--"; |
35 const wchar_t kSwitchValueSeparator[] = L"="; | 35 const wchar_t kSwitchValueSeparator[] = L"="; |
36 #elif defined(OS_POSIX) | 36 #elif defined(OS_POSIX) |
37 // Unixes don't use slash as a switch. | 37 // Unixes don't use slash as a switch. |
38 const char* const kSwitchPrefixes[] = {"--", "-"}; | 38 const char* const kSwitchPrefixes[] = {"--", "-"}; |
39 const char kSwitchTerminator[] = "--"; | 39 const char kSwitchTerminator[] = "--"; |
40 const char kSwitchValueSeparator[] = "="; | 40 const char kSwitchValueSeparator[] = "="; |
41 #endif | 41 #endif |
42 | 42 |
43 #if defined(OS_WIN) | 43 #if defined(OS_WIN) |
44 namespace { | |
Evan Martin
2011/02/10 19:38:31
Thanks for the cleanup! Can you remove the "stati
msw
2011/02/10 19:54:54
Done.
| |
44 // Lowercase a string. This is used to lowercase switch names. | 45 // Lowercase a string. This is used to lowercase switch names. |
45 // Is this what we really want? It seems crazy to me. I've left it in | 46 // Is this what we really want? It seems crazy to me. I've left it in |
46 // for backwards compatibility on Windows. | 47 // for backwards compatibility on Windows. |
47 static void Lowercase(std::string* parameter) { | 48 static void Lowercase(std::string* parameter) { |
48 transform(parameter->begin(), parameter->end(), parameter->begin(), | 49 transform(parameter->begin(), parameter->end(), parameter->begin(), |
49 tolower); | 50 tolower); |
50 } | 51 } |
52 | |
53 // Quote a string if necessary, such that CommandLineToArgvW() will | |
54 // always process it as a single argument. | |
55 static std::wstring WindowsStyleQuote(const std::wstring& arg) { | |
56 // We follow the quoting rules of CommandLineToArgvW. | |
57 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx | |
58 if (arg.find_first_of(L" \\\"") == std::wstring::npos) { | |
59 // No quoting necessary. | |
60 return arg; | |
61 } | |
62 | |
63 std::wstring out; | |
64 out.push_back(L'"'); | |
65 for (size_t i = 0; i < arg.size(); ++i) { | |
66 if (arg[i] == '\\') { | |
67 // Find the extent of this run of backslashes. | |
68 size_t start = i, end = start + 1; | |
69 for (; end < arg.size() && arg[end] == '\\'; ++end) | |
70 /* empty */; | |
71 size_t backslash_count = end - start; | |
72 | |
73 // Backslashes are escapes only if the run is followed by a double quote. | |
74 // Since we also will end the string with a double quote, we escape for | |
75 // either a double quote or the end of the string. | |
76 if (end == arg.size() || arg[end] == '"') { | |
77 // To quote, we need to output 2x as many backslashes. | |
78 backslash_count *= 2; | |
79 } | |
80 for (size_t j = 0; j < backslash_count; ++j) | |
81 out.push_back('\\'); | |
82 | |
83 // Advance i to one before the end to balance i++ in loop. | |
84 i = end - 1; | |
85 } else if (arg[i] == '"') { | |
86 out.push_back('\\'); | |
87 out.push_back('"'); | |
88 } else { | |
89 out.push_back(arg[i]); | |
90 } | |
91 } | |
92 out.push_back('"'); | |
93 | |
94 return out; | |
95 } | |
96 } // namespace | |
51 #endif | 97 #endif |
52 | 98 |
53 CommandLine::~CommandLine() { | 99 CommandLine::~CommandLine() { |
54 } | 100 } |
55 | 101 |
56 #if defined(OS_WIN) | 102 #if defined(OS_WIN) |
57 CommandLine::CommandLine(NoProgram no_program) { | 103 CommandLine::CommandLine(NoProgram no_program) { |
58 } | 104 } |
59 | 105 |
60 void CommandLine::ParseFromString(const std::wstring& command_line) { | 106 void CommandLine::ParseFromString(const std::wstring& command_line) { |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 } | 330 } |
285 #endif | 331 #endif |
286 | 332 |
287 #if defined(OS_WIN) | 333 #if defined(OS_WIN) |
288 void CommandLine::AppendSwitch(const std::string& switch_string) { | 334 void CommandLine::AppendSwitch(const std::string& switch_string) { |
289 command_line_string_.append(L" "); | 335 command_line_string_.append(L" "); |
290 command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string)); | 336 command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string)); |
291 switches_[switch_string] = L""; | 337 switches_[switch_string] = L""; |
292 } | 338 } |
293 | 339 |
294 void CommandLine::AppendSwitchASCII(const std::string& switch_string, | |
295 const std::string& value_string) { | |
296 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); | |
297 } | |
298 | |
299 // Quote a string if necessary, such that CommandLineToArgvW() will | |
300 // always process it as a single argument. | |
301 static std::wstring WindowsStyleQuote(const std::wstring& arg) { | |
302 // We follow the quoting rules of CommandLineToArgvW. | |
303 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx | |
304 if (arg.find_first_of(L" \\\"") == std::wstring::npos) { | |
305 // No quoting necessary. | |
306 return arg; | |
307 } | |
308 | |
309 std::wstring out; | |
310 out.push_back(L'"'); | |
311 for (size_t i = 0; i < arg.size(); ++i) { | |
312 if (arg[i] == '\\') { | |
313 // Find the extent of this run of backslashes. | |
314 size_t start = i, end = start + 1; | |
315 for (; end < arg.size() && arg[end] == '\\'; ++end) | |
316 /* empty */; | |
317 size_t backslash_count = end - start; | |
318 | |
319 // Backslashes are escapes only if the run is followed by a double quote. | |
320 // Since we also will end the string with a double quote, we escape for | |
321 // either a double quote or the end of the string. | |
322 if (end == arg.size() || arg[end] == '"') { | |
323 // To quote, we need to output 2x as many backslashes. | |
324 backslash_count *= 2; | |
325 } | |
326 for (size_t j = 0; j < backslash_count; ++j) | |
327 out.push_back('\\'); | |
328 | |
329 // Advance i to one before the end to balance i++ in loop. | |
330 i = end - 1; | |
331 } else if (arg[i] == '"') { | |
332 out.push_back('\\'); | |
333 out.push_back('"'); | |
334 } else { | |
335 out.push_back(arg[i]); | |
336 } | |
337 } | |
338 out.push_back('"'); | |
339 | |
340 return out; | |
341 } | |
342 | |
343 void CommandLine::AppendSwitchNative(const std::string& switch_string, | 340 void CommandLine::AppendSwitchNative(const std::string& switch_string, |
344 const std::wstring& value) { | 341 const std::wstring& value) { |
345 std::wstring combined_switch_string = | 342 std::wstring combined_switch_string = |
346 kSwitchPrefixes[0] + ASCIIToWide(switch_string); | 343 kSwitchPrefixes[0] + ASCIIToWide(switch_string); |
347 if (!value.empty()) | 344 if (!value.empty()) |
348 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value); | 345 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value); |
349 | 346 |
350 command_line_string_.append(L" "); | 347 command_line_string_.append(L" "); |
351 command_line_string_.append(combined_switch_string); | 348 command_line_string_.append(combined_switch_string); |
352 | 349 |
353 switches_[switch_string] = value; | 350 switches_[switch_string] = value; |
354 } | 351 } |
355 | 352 |
353 void CommandLine::AppendSwitchASCII(const std::string& switch_string, | |
354 const std::string& value_string) { | |
355 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); | |
356 } | |
357 | |
356 void CommandLine::AppendArg(const std::string& value) { | 358 void CommandLine::AppendArg(const std::string& value) { |
357 DCHECK(IsStringUTF8(value)); | 359 DCHECK(IsStringUTF8(value)); |
358 AppendArgNative(UTF8ToWide(value)); | 360 AppendArgNative(UTF8ToWide(value)); |
359 } | 361 } |
360 | 362 |
361 void CommandLine::AppendArgNative(const std::wstring& value) { | 363 void CommandLine::AppendArgNative(const std::wstring& value) { |
362 command_line_string_.append(L" "); | 364 command_line_string_.append(L" "); |
363 command_line_string_.append(WindowsStyleQuote(value)); | 365 command_line_string_.append(WindowsStyleQuote(value)); |
364 args_.push_back(value); | 366 args_.push_back(value); |
365 } | 367 } |
366 | 368 |
367 void CommandLine::AppendArguments(const CommandLine& other, | 369 void CommandLine::AppendArguments(const CommandLine& other, |
368 bool include_program) { | 370 bool include_program) { |
369 // Verify include_program is used correctly. | 371 // Verify include_program is used correctly. |
370 // Logic could be shorter but this is clearer. | 372 DCHECK(!include_program || !other.GetProgram().empty()); |
371 DCHECK_EQ(include_program, !other.GetProgram().empty()); | |
372 if (include_program) | 373 if (include_program) |
373 program_ = other.program_; | 374 program_ = other.program_; |
374 | 375 |
375 if (!command_line_string_.empty()) | 376 if (!command_line_string_.empty()) |
376 command_line_string_ += L' '; | 377 command_line_string_ += L' '; |
377 | 378 |
378 command_line_string_ += other.command_line_string_; | 379 command_line_string_ += other.command_line_string_; |
379 | 380 |
380 std::map<std::string, StringType>::const_iterator i; | 381 std::map<std::string, StringType>::const_iterator i; |
381 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) | 382 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 void CommandLine::PrependWrapper(const std::string& wrapper) { | 445 void CommandLine::PrependWrapper(const std::string& wrapper) { |
445 // The wrapper may have embedded arguments (like "gdb --args"). In this case, | 446 // The wrapper may have embedded arguments (like "gdb --args"). In this case, |
446 // we don't pretend to do anything fancy, we just split on spaces. | 447 // we don't pretend to do anything fancy, we just split on spaces. |
447 std::vector<std::string> wrapper_and_args; | 448 std::vector<std::string> wrapper_and_args; |
448 base::SplitString(wrapper, ' ', &wrapper_and_args); | 449 base::SplitString(wrapper, ' ', &wrapper_and_args); |
449 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end()); | 450 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end()); |
450 } | 451 } |
451 | 452 |
452 #endif | 453 #endif |
453 | 454 |
454 void CommandLine::AppendArgPath(const FilePath& path) { | |
455 AppendArgNative(path.value()); | |
456 } | |
457 | |
458 void CommandLine::AppendSwitchPath(const std::string& switch_string, | 455 void CommandLine::AppendSwitchPath(const std::string& switch_string, |
459 const FilePath& path) { | 456 const FilePath& path) { |
460 AppendSwitchNative(switch_string, path.value()); | 457 AppendSwitchNative(switch_string, path.value()); |
461 } | 458 } |
462 | 459 |
460 void CommandLine::AppendSwitches(const CommandLine& other) { | |
461 std::map<std::string, StringType>::const_iterator i; | |
462 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) | |
463 AppendSwitchNative(i->first, i->second); | |
464 } | |
465 | |
466 void CommandLine::AppendArgPath(const FilePath& path) { | |
467 AppendArgNative(path.value()); | |
468 } | |
469 | |
470 void CommandLine::AppendArgs(const CommandLine& other) { | |
471 if(other.args_.size() <= 0) | |
472 return; | |
473 | |
474 #if defined(OS_WIN) | |
475 command_line_string_.append(L" --"); | |
Evan Martin
2011/02/10 19:38:31
This makes me anxious. Does this mean we do the w
msw
2011/02/10 19:54:54
That's an excellent point, appending switches afte
msw
2011/02/16 23:15:53
I added a comment above the AppendSwitch* declarat
| |
476 #endif // OS_WIN | |
477 std::vector<StringType>::const_iterator i; | |
478 for (i = other.args_.begin(); i != other.args_.end(); ++i) | |
479 AppendArgNative(*i); | |
480 } | |
481 | |
463 void CommandLine::CopySwitchesFrom(const CommandLine& source, | 482 void CommandLine::CopySwitchesFrom(const CommandLine& source, |
464 const char* const switches[], | 483 const char* const switches[], |
465 size_t count) { | 484 size_t count) { |
466 for (size_t i = 0; i < count; ++i) { | 485 for (size_t i = 0; i < count; ++i) { |
467 if (source.HasSwitch(switches[i])) { | 486 if (source.HasSwitch(switches[i])) { |
468 StringType value = source.GetSwitchValueNative(switches[i]); | 487 StringType value = source.GetSwitchValueNative(switches[i]); |
469 AppendSwitchNative(switches[i], value); | 488 AppendSwitchNative(switches[i], value); |
470 } | 489 } |
471 } | 490 } |
472 } | 491 } |
473 | 492 |
474 // private | 493 // private |
475 CommandLine::CommandLine() { | 494 CommandLine::CommandLine() { |
476 } | 495 } |
477 | 496 |
478 // static | 497 // static |
479 CommandLine* CommandLine::ForCurrentProcessMutable() { | 498 CommandLine* CommandLine::ForCurrentProcessMutable() { |
480 DCHECK(current_process_commandline_); | 499 DCHECK(current_process_commandline_); |
481 return current_process_commandline_; | 500 return current_process_commandline_; |
482 } | 501 } |
OLD | NEW |