| OLD | NEW |
| 1 // Copyright (c) 2011 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" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| (...skipping 22 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 { | |
| 45 // Lowercase a string. This is used to lowercase switch names. | 44 // Lowercase a string. This is used to lowercase switch names. |
| 46 // Is this what we really want? It seems crazy to me. I've left it in | 45 // Is this what we really want? It seems crazy to me. I've left it in |
| 47 // for backwards compatibility on Windows. | 46 // for backwards compatibility on Windows. |
| 48 void Lowercase(std::string* parameter) { | 47 static void Lowercase(std::string* parameter) { |
| 49 transform(parameter->begin(), parameter->end(), parameter->begin(), | 48 transform(parameter->begin(), parameter->end(), parameter->begin(), |
| 50 tolower); | 49 tolower); |
| 51 } | 50 } |
| 52 | |
| 53 // Quote a string if necessary, such that CommandLineToArgvW() will | |
| 54 // always process it as a single argument. | |
| 55 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 | |
| 97 #endif | 51 #endif |
| 98 | 52 |
| 99 CommandLine::~CommandLine() { | 53 CommandLine::~CommandLine() { |
| 100 } | 54 } |
| 101 | 55 |
| 102 #if defined(OS_WIN) | 56 #if defined(OS_WIN) |
| 103 CommandLine::CommandLine(NoProgram no_program) { | 57 CommandLine::CommandLine(NoProgram no_program) { |
| 104 } | 58 } |
| 105 | 59 |
| 106 void CommandLine::ParseFromString(const std::wstring& command_line) { | 60 void CommandLine::ParseFromString(const std::wstring& command_line) { |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 } | 284 } |
| 331 #endif | 285 #endif |
| 332 | 286 |
| 333 #if defined(OS_WIN) | 287 #if defined(OS_WIN) |
| 334 void CommandLine::AppendSwitch(const std::string& switch_string) { | 288 void CommandLine::AppendSwitch(const std::string& switch_string) { |
| 335 command_line_string_.append(L" "); | 289 command_line_string_.append(L" "); |
| 336 command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string)); | 290 command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string)); |
| 337 switches_[switch_string] = L""; | 291 switches_[switch_string] = L""; |
| 338 } | 292 } |
| 339 | 293 |
| 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 |
| 340 void CommandLine::AppendSwitchNative(const std::string& switch_string, | 343 void CommandLine::AppendSwitchNative(const std::string& switch_string, |
| 341 const std::wstring& value) { | 344 const std::wstring& value) { |
| 342 std::wstring combined_switch_string = | 345 std::wstring combined_switch_string = |
| 343 kSwitchPrefixes[0] + ASCIIToWide(switch_string); | 346 kSwitchPrefixes[0] + ASCIIToWide(switch_string); |
| 344 if (!value.empty()) | 347 if (!value.empty()) |
| 345 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value); | 348 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value); |
| 346 | 349 |
| 347 command_line_string_.append(L" "); | 350 command_line_string_.append(L" "); |
| 348 command_line_string_.append(combined_switch_string); | 351 command_line_string_.append(combined_switch_string); |
| 349 | 352 |
| 350 switches_[switch_string] = value; | 353 switches_[switch_string] = value; |
| 351 } | 354 } |
| 352 | 355 |
| 353 void CommandLine::AppendSwitchASCII(const std::string& switch_string, | |
| 354 const std::string& value_string) { | |
| 355 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); | |
| 356 } | |
| 357 | |
| 358 void CommandLine::AppendArg(const std::string& value) { | 356 void CommandLine::AppendArg(const std::string& value) { |
| 359 DCHECK(IsStringUTF8(value)); | 357 DCHECK(IsStringUTF8(value)); |
| 360 AppendArgNative(UTF8ToWide(value)); | 358 AppendArgNative(UTF8ToWide(value)); |
| 361 } | 359 } |
| 362 | 360 |
| 363 void CommandLine::AppendArgNative(const std::wstring& value) { | 361 void CommandLine::AppendArgNative(const std::wstring& value) { |
| 364 command_line_string_.append(L" "); | 362 command_line_string_.append(L" "); |
| 365 command_line_string_.append(WindowsStyleQuote(value)); | 363 command_line_string_.append(WindowsStyleQuote(value)); |
| 366 args_.push_back(value); | 364 args_.push_back(value); |
| 367 } | 365 } |
| 368 | 366 |
| 369 void CommandLine::AppendArguments(const CommandLine& other, | 367 void CommandLine::AppendArguments(const CommandLine& other, |
| 370 bool include_program) { | 368 bool include_program) { |
| 371 // Verify include_program is used correctly. | 369 // Verify include_program is used correctly. |
| 372 DCHECK(!include_program || !other.GetProgram().empty()); | 370 // Logic could be shorter but this is clearer. |
| 371 DCHECK_EQ(include_program, !other.GetProgram().empty()); |
| 373 if (include_program) | 372 if (include_program) |
| 374 program_ = other.program_; | 373 program_ = other.program_; |
| 375 | 374 |
| 376 if (!command_line_string_.empty()) | 375 if (!command_line_string_.empty()) |
| 377 command_line_string_ += L' '; | 376 command_line_string_ += L' '; |
| 378 | 377 |
| 379 command_line_string_ += other.command_line_string_; | 378 command_line_string_ += other.command_line_string_; |
| 380 | 379 |
| 381 std::map<std::string, StringType>::const_iterator i; | 380 std::map<std::string, StringType>::const_iterator i; |
| 382 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) | 381 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 445 void CommandLine::PrependWrapper(const std::string& wrapper) { | 444 void CommandLine::PrependWrapper(const std::string& wrapper) { |
| 446 // The wrapper may have embedded arguments (like "gdb --args"). In this case, | 445 // The wrapper may have embedded arguments (like "gdb --args"). In this case, |
| 447 // we don't pretend to do anything fancy, we just split on spaces. | 446 // we don't pretend to do anything fancy, we just split on spaces. |
| 448 std::vector<std::string> wrapper_and_args; | 447 std::vector<std::string> wrapper_and_args; |
| 449 base::SplitString(wrapper, ' ', &wrapper_and_args); | 448 base::SplitString(wrapper, ' ', &wrapper_and_args); |
| 450 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end()); | 449 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end()); |
| 451 } | 450 } |
| 452 | 451 |
| 453 #endif | 452 #endif |
| 454 | 453 |
| 454 void CommandLine::AppendArgPath(const FilePath& path) { |
| 455 AppendArgNative(path.value()); |
| 456 } |
| 457 |
| 455 void CommandLine::AppendSwitchPath(const std::string& switch_string, | 458 void CommandLine::AppendSwitchPath(const std::string& switch_string, |
| 456 const FilePath& path) { | 459 const FilePath& path) { |
| 457 AppendSwitchNative(switch_string, path.value()); | 460 AppendSwitchNative(switch_string, path.value()); |
| 458 } | 461 } |
| 459 | 462 |
| 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" --"); | |
| 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 | |
| 482 void CommandLine::CopySwitchesFrom(const CommandLine& source, | 463 void CommandLine::CopySwitchesFrom(const CommandLine& source, |
| 483 const char* const switches[], | 464 const char* const switches[], |
| 484 size_t count) { | 465 size_t count) { |
| 485 for (size_t i = 0; i < count; ++i) { | 466 for (size_t i = 0; i < count; ++i) { |
| 486 if (source.HasSwitch(switches[i])) { | 467 if (source.HasSwitch(switches[i])) { |
| 487 StringType value = source.GetSwitchValueNative(switches[i]); | 468 StringType value = source.GetSwitchValueNative(switches[i]); |
| 488 AppendSwitchNative(switches[i], value); | 469 AppendSwitchNative(switches[i], value); |
| 489 } | 470 } |
| 490 } | 471 } |
| 491 } | 472 } |
| 492 | 473 |
| 493 // private | 474 // private |
| 494 CommandLine::CommandLine() { | 475 CommandLine::CommandLine() { |
| 495 } | 476 } |
| 496 | 477 |
| 497 // static | 478 // static |
| 498 CommandLine* CommandLine::ForCurrentProcessMutable() { | 479 CommandLine* CommandLine::ForCurrentProcessMutable() { |
| 499 DCHECK(current_process_commandline_); | 480 DCHECK(current_process_commandline_); |
| 500 return current_process_commandline_; | 481 return current_process_commandline_; |
| 501 } | 482 } |
| OLD | NEW |