Chromium Code Reviews| 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 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <windows.h> | 8 #include <windows.h> |
| 9 #include <shellapi.h> | 9 #include <shellapi.h> |
| 10 #elif defined(OS_POSIX) | 10 #elif defined(OS_POSIX) |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 // static | 107 // static |
| 108 CommandLine CommandLine::FromString(const std::wstring& command_line) { | 108 CommandLine CommandLine::FromString(const std::wstring& command_line) { |
| 109 CommandLine cmd; | 109 CommandLine cmd; |
| 110 cmd.ParseFromString(command_line); | 110 cmd.ParseFromString(command_line); |
| 111 return cmd; | 111 return cmd; |
| 112 } | 112 } |
| 113 | 113 |
| 114 CommandLine::CommandLine(const FilePath& program) { | 114 CommandLine::CommandLine(const FilePath& program) { |
| 115 if (!program.empty()) { | 115 if (!program.empty()) { |
| 116 program_ = program.value(); | 116 program_ = program.value(); |
| 117 // TODO(evanm): proper quoting here. | |
| 117 command_line_string_ = L'"' + program.value() + L'"'; | 118 command_line_string_ = L'"' + program.value() + L'"'; |
| 118 } | 119 } |
| 119 } | 120 } |
| 120 | 121 |
| 121 #elif defined(OS_POSIX) | 122 #elif defined(OS_POSIX) |
| 122 CommandLine::CommandLine(ArgumentsOnly args_only) { | 123 CommandLine::CommandLine(ArgumentsOnly args_only) { |
| 123 // Push an empty argument, because we always assume argv_[0] is a program. | 124 // Push an empty argument, because we always assume argv_[0] is a program. |
| 124 argv_.push_back(""); | 125 argv_.push_back(""); |
| 125 } | 126 } |
| 126 | 127 |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 381 command_line_string_.append(L" "); | 382 command_line_string_.append(L" "); |
| 382 command_line_string_.append(prefixed_switch_string); | 383 command_line_string_.append(prefixed_switch_string); |
| 383 switches_[switch_string] = L""; | 384 switches_[switch_string] = L""; |
| 384 } | 385 } |
| 385 | 386 |
| 386 void CommandLine::AppendSwitchASCII(const std::string& switch_string, | 387 void CommandLine::AppendSwitchASCII(const std::string& switch_string, |
| 387 const std::string& value_string) { | 388 const std::string& value_string) { |
| 388 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); | 389 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); |
| 389 } | 390 } |
| 390 | 391 |
| 392 // Quote a string if necessary, such that CommandLineToArgvW() will | |
| 393 // always process it as a single argument. | |
| 394 static std::wstring WindowsStyleQuote(const std::wstring& arg) { | |
| 395 // We follow the quoting rules of CommandLineToArgvW. | |
| 396 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx | |
| 397 if (arg.find_first_of(L" \\\"") == std::wstring::npos) { | |
| 398 // No quoting necessary. | |
| 399 return arg; | |
|
cpu_(ooo_6.6-7.5)
2010/08/06 20:09:04
I am lost on that first if(). So arg = L"ab cd" do
Evan Martin
2010/08/06 20:10:59
It's saying: if we *don't* find any spaces \ or "
cpu_(ooo_6.6-7.5)
2010/08/07 01:00:27
Got it.
What confused me what the check for ("),
| |
| 400 } | |
| 401 | |
| 402 std::wstring out; | |
| 403 out.push_back(L'"'); | |
| 404 for (size_t i = 0; i < arg.size(); ++i) { | |
| 405 if (arg[i] == '\\') { | |
| 406 // Find the extent of this run of backslashes. | |
| 407 int start = i, end = start + 1; | |
| 408 for (; end < arg.size() && arg[end] == '\\'; ++end) | |
| 409 /* empty */; | |
| 410 int backslash_count = end - start; | |
| 411 | |
| 412 // Backslashes are escapes only if the run is followed by a double quote. | |
| 413 // Since we also will end the string with a double quote, we escape for | |
| 414 // either a double quote or the end of the string. | |
| 415 if (end == static_cast<int>(arg.size()) || arg[end] == '"') { | |
| 416 // To quote, we need to output 2x as many backslashes. | |
| 417 backslash_count *= 2; | |
| 418 } | |
| 419 for (size_t j = 0; j < backslash_count; ++j) | |
| 420 out.push_back('\\'); | |
| 421 | |
| 422 // Advance i to one before the end to balance i++ in loop. | |
| 423 i = end - 1; | |
| 424 } else if (arg[i] == '"') { | |
| 425 out.push_back('\\'); | |
| 426 out.push_back('"'); | |
| 427 } else { | |
| 428 out.push_back(arg[i]); | |
| 429 } | |
| 430 } | |
| 431 out.push_back('"'); | |
| 432 | |
| 433 return out; | |
| 434 } | |
| 435 | |
| 391 void CommandLine::AppendSwitchNative(const std::string& switch_string, | 436 void CommandLine::AppendSwitchNative(const std::string& switch_string, |
| 392 const std::wstring& value_string) { | 437 const std::wstring& value_string) { |
| 393 std::wstring value_string_edit; | 438 std::wstring quoted_value_string = WindowsStyleQuote(value_string); |
| 394 | |
| 395 // NOTE(jhughes): If the value contains a quotation mark at one | |
| 396 // end but not both, you may get unusable output. | |
| 397 if (!value_string.empty() && | |
| 398 (value_string.find(L" ") != std::wstring::npos) && | |
| 399 (value_string[0] != L'"') && | |
|
cpu_(ooo_6.6-7.5)
2010/08/09 23:00:33
my last comment was due to line 399 here. I guess
| |
| 400 (value_string[value_string.length() - 1] != L'"')) { | |
| 401 // need to provide quotes | |
| 402 value_string_edit = StringPrintf(L"\"%ls\"", value_string.c_str()); | |
| 403 } else { | |
| 404 value_string_edit = value_string; | |
| 405 } | |
| 406 | |
| 407 std::wstring combined_switch_string = | 439 std::wstring combined_switch_string = |
| 408 PrefixedSwitchStringWithValue(switch_string, value_string_edit); | 440 PrefixedSwitchStringWithValue(switch_string, quoted_value_string); |
| 409 | 441 |
| 410 command_line_string_.append(L" "); | 442 command_line_string_.append(L" "); |
| 411 command_line_string_.append(combined_switch_string); | 443 command_line_string_.append(combined_switch_string); |
| 412 | 444 |
| 413 switches_[switch_string] = value_string; | 445 switches_[switch_string] = value_string; |
| 414 } | 446 } |
| 415 | 447 |
| 416 void CommandLine::AppendLooseValue(const std::wstring& value) { | 448 void CommandLine::AppendLooseValue(const std::wstring& value) { |
| 417 // TODO(evan): quoting? | 449 // TODO(evan): the quoting here is wrong, but current callers rely on it |
| 450 // being wrong. I have another branch which fixes all the callers. | |
| 418 command_line_string_.append(L" "); | 451 command_line_string_.append(L" "); |
| 419 command_line_string_.append(value); | 452 command_line_string_.append(value); |
| 420 args_.push_back(value); | 453 args_.push_back(value); |
| 421 } | 454 } |
| 422 | 455 |
| 423 void CommandLine::AppendArguments(const CommandLine& other, | 456 void CommandLine::AppendArguments(const CommandLine& other, |
| 424 bool include_program) { | 457 bool include_program) { |
| 425 // Verify include_program is used correctly. | 458 // Verify include_program is used correctly. |
| 426 // Logic could be shorter but this is clearer. | 459 // Logic could be shorter but this is clearer. |
| 427 DCHECK_EQ(include_program, !other.GetProgram().empty()); | 460 DCHECK_EQ(include_program, !other.GetProgram().empty()); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 499 if (source.HasSwitch(switches[i])) { | 532 if (source.HasSwitch(switches[i])) { |
| 500 StringType value = source.GetSwitchValueNative(switches[i]); | 533 StringType value = source.GetSwitchValueNative(switches[i]); |
| 501 AppendSwitchNative(switches[i], value); | 534 AppendSwitchNative(switches[i], value); |
| 502 } | 535 } |
| 503 } | 536 } |
| 504 } | 537 } |
| 505 | 538 |
| 506 // private | 539 // private |
| 507 CommandLine::CommandLine() { | 540 CommandLine::CommandLine() { |
| 508 } | 541 } |
| OLD | NEW |