OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 #include <ostream> | 8 #include <ostream> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
16 #include "build/build_config.h" | 16 #include "build/build_config.h" |
17 | 17 |
18 #if defined(OS_WIN) | 18 #if defined(OS_WIN) |
19 #include <windows.h> | 19 #include <windows.h> |
20 #include <shellapi.h> | 20 #include <shellapi.h> |
21 #endif | 21 #endif |
22 | 22 |
23 using base::FilePath; | 23 namespace base { |
24 | 24 |
25 CommandLine* CommandLine::current_process_commandline_ = NULL; | 25 CommandLine* CommandLine::current_process_commandline_ = NULL; |
26 | 26 |
27 namespace { | 27 namespace { |
| 28 |
28 const CommandLine::CharType kSwitchTerminator[] = FILE_PATH_LITERAL("--"); | 29 const CommandLine::CharType kSwitchTerminator[] = FILE_PATH_LITERAL("--"); |
29 const CommandLine::CharType kSwitchValueSeparator[] = FILE_PATH_LITERAL("="); | 30 const CommandLine::CharType kSwitchValueSeparator[] = FILE_PATH_LITERAL("="); |
30 | 31 |
31 // Since we use a lazy match, make sure that longer versions (like "--") are | 32 // Since we use a lazy match, make sure that longer versions (like "--") are |
32 // listed before shorter versions (like "-") of similar prefixes. | 33 // listed before shorter versions (like "-") of similar prefixes. |
33 #if defined(OS_WIN) | 34 #if defined(OS_WIN) |
34 // By putting slash last, we can control whether it is treaded as a switch | 35 // By putting slash last, we can control whether it is treaded as a switch |
35 // value by changing the value of switch_prefix_count to be one less than | 36 // value by changing the value of switch_prefix_count to be one less than |
36 // the array size. | 37 // the array size. |
37 const CommandLine::CharType* const kSwitchPrefixes[] = {L"--", L"-", L"/"}; | 38 const CommandLine::CharType* const kSwitchPrefixes[] = {L"--", L"-", L"/"}; |
(...skipping 29 matching lines...) Expand all Loading... |
67 *switch_value = string.substr(equals_position + 1); | 68 *switch_value = string.substr(equals_position + 1); |
68 return true; | 69 return true; |
69 } | 70 } |
70 | 71 |
71 // Append switches and arguments, keeping switches before arguments. | 72 // Append switches and arguments, keeping switches before arguments. |
72 void AppendSwitchesAndArguments(CommandLine& command_line, | 73 void AppendSwitchesAndArguments(CommandLine& command_line, |
73 const CommandLine::StringVector& argv) { | 74 const CommandLine::StringVector& argv) { |
74 bool parse_switches = true; | 75 bool parse_switches = true; |
75 for (size_t i = 1; i < argv.size(); ++i) { | 76 for (size_t i = 1; i < argv.size(); ++i) { |
76 CommandLine::StringType arg = argv[i]; | 77 CommandLine::StringType arg = argv[i]; |
77 base::TrimWhitespace(arg, base::TRIM_ALL, &arg); | 78 TrimWhitespace(arg, TRIM_ALL, &arg); |
78 | 79 |
79 CommandLine::StringType switch_string; | 80 CommandLine::StringType switch_string; |
80 CommandLine::StringType switch_value; | 81 CommandLine::StringType switch_value; |
81 parse_switches &= (arg != kSwitchTerminator); | 82 parse_switches &= (arg != kSwitchTerminator); |
82 if (parse_switches && IsSwitch(arg, &switch_string, &switch_value)) { | 83 if (parse_switches && IsSwitch(arg, &switch_string, &switch_value)) { |
83 #if defined(OS_WIN) | 84 #if defined(OS_WIN) |
84 command_line.AppendSwitchNative(base::UTF16ToASCII(switch_string), | 85 command_line.AppendSwitchNative(UTF16ToASCII(switch_string), |
85 switch_value); | 86 switch_value); |
86 #elif defined(OS_POSIX) | 87 #elif defined(OS_POSIX) |
87 command_line.AppendSwitchNative(switch_string, switch_value); | 88 command_line.AppendSwitchNative(switch_string, switch_value); |
88 #endif | 89 #endif |
89 } else { | 90 } else { |
90 command_line.AppendArgNative(arg); | 91 command_line.AppendArgNative(arg); |
91 } | 92 } |
92 } | 93 } |
93 } | 94 } |
94 | 95 |
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 } | 288 } |
288 } | 289 } |
289 return params; | 290 return params; |
290 } | 291 } |
291 | 292 |
292 FilePath CommandLine::GetProgram() const { | 293 FilePath CommandLine::GetProgram() const { |
293 return FilePath(argv_[0]); | 294 return FilePath(argv_[0]); |
294 } | 295 } |
295 | 296 |
296 void CommandLine::SetProgram(const FilePath& program) { | 297 void CommandLine::SetProgram(const FilePath& program) { |
297 base::TrimWhitespace(program.value(), base::TRIM_ALL, &argv_[0]); | 298 TrimWhitespace(program.value(), TRIM_ALL, &argv_[0]); |
298 } | 299 } |
299 | 300 |
300 bool CommandLine::HasSwitch(const std::string& switch_string) const { | 301 bool CommandLine::HasSwitch(const std::string& switch_string) const { |
301 return switches_.find(LowerASCIIOnWindows(switch_string)) != switches_.end(); | 302 return switches_.find(LowerASCIIOnWindows(switch_string)) != switches_.end(); |
302 } | 303 } |
303 | 304 |
304 std::string CommandLine::GetSwitchValueASCII( | 305 std::string CommandLine::GetSwitchValueASCII( |
305 const std::string& switch_string) const { | 306 const std::string& switch_string) const { |
306 StringType value = GetSwitchValueNative(switch_string); | 307 StringType value = GetSwitchValueNative(switch_string); |
307 if (!IsStringASCII(value)) { | 308 if (!IsStringASCII(value)) { |
308 DLOG(WARNING) << "Value of switch (" << switch_string << ") must be ASCII."; | 309 DLOG(WARNING) << "Value of switch (" << switch_string << ") must be ASCII."; |
309 return std::string(); | 310 return std::string(); |
310 } | 311 } |
311 #if defined(OS_WIN) | 312 #if defined(OS_WIN) |
312 return base::UTF16ToASCII(value); | 313 return UTF16ToASCII(value); |
313 #else | 314 #else |
314 return value; | 315 return value; |
315 #endif | 316 #endif |
316 } | 317 } |
317 | 318 |
318 FilePath CommandLine::GetSwitchValuePath( | 319 FilePath CommandLine::GetSwitchValuePath( |
319 const std::string& switch_string) const { | 320 const std::string& switch_string) const { |
320 return FilePath(GetSwitchValueNative(switch_string)); | 321 return FilePath(GetSwitchValueNative(switch_string)); |
321 } | 322 } |
322 | 323 |
(...skipping 10 matching lines...) Expand all Loading... |
333 | 334 |
334 void CommandLine::AppendSwitchPath(const std::string& switch_string, | 335 void CommandLine::AppendSwitchPath(const std::string& switch_string, |
335 const FilePath& path) { | 336 const FilePath& path) { |
336 AppendSwitchNative(switch_string, path.value()); | 337 AppendSwitchNative(switch_string, path.value()); |
337 } | 338 } |
338 | 339 |
339 void CommandLine::AppendSwitchNative(const std::string& switch_string, | 340 void CommandLine::AppendSwitchNative(const std::string& switch_string, |
340 const CommandLine::StringType& value) { | 341 const CommandLine::StringType& value) { |
341 std::string switch_key(LowerASCIIOnWindows(switch_string)); | 342 std::string switch_key(LowerASCIIOnWindows(switch_string)); |
342 #if defined(OS_WIN) | 343 #if defined(OS_WIN) |
343 StringType combined_switch_string(base::ASCIIToWide(switch_key)); | 344 StringType combined_switch_string(ASCIIToWide(switch_key)); |
344 #elif defined(OS_POSIX) | 345 #elif defined(OS_POSIX) |
345 StringType combined_switch_string(switch_string); | 346 StringType combined_switch_string(switch_string); |
346 #endif | 347 #endif |
347 size_t prefix_length = GetSwitchPrefixLength(combined_switch_string); | 348 size_t prefix_length = GetSwitchPrefixLength(combined_switch_string); |
348 switches_[switch_key.substr(prefix_length)] = value; | 349 switches_[switch_key.substr(prefix_length)] = value; |
349 // Preserve existing switch prefixes in |argv_|; only append one if necessary. | 350 // Preserve existing switch prefixes in |argv_|; only append one if necessary. |
350 if (prefix_length == 0) | 351 if (prefix_length == 0) |
351 combined_switch_string = kSwitchPrefixes[0] + combined_switch_string; | 352 combined_switch_string = kSwitchPrefixes[0] + combined_switch_string; |
352 if (!value.empty()) | 353 if (!value.empty()) |
353 combined_switch_string += kSwitchValueSeparator + value; | 354 combined_switch_string += kSwitchValueSeparator + value; |
354 // Append the switch and update the switches/arguments divider |begin_args_|. | 355 // Append the switch and update the switches/arguments divider |begin_args_|. |
355 argv_.insert(argv_.begin() + begin_args_++, combined_switch_string); | 356 argv_.insert(argv_.begin() + begin_args_++, combined_switch_string); |
356 } | 357 } |
357 | 358 |
358 void CommandLine::AppendSwitchASCII(const std::string& switch_string, | 359 void CommandLine::AppendSwitchASCII(const std::string& switch_string, |
359 const std::string& value_string) { | 360 const std::string& value_string) { |
360 #if defined(OS_WIN) | 361 #if defined(OS_WIN) |
361 AppendSwitchNative(switch_string, base::ASCIIToWide(value_string)); | 362 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); |
362 #elif defined(OS_POSIX) | 363 #elif defined(OS_POSIX) |
363 AppendSwitchNative(switch_string, value_string); | 364 AppendSwitchNative(switch_string, value_string); |
364 #endif | 365 #endif |
365 } | 366 } |
366 | 367 |
367 void CommandLine::CopySwitchesFrom(const CommandLine& source, | 368 void CommandLine::CopySwitchesFrom(const CommandLine& source, |
368 const char* const switches[], | 369 const char* const switches[], |
369 size_t count) { | 370 size_t count) { |
370 for (size_t i = 0; i < count; ++i) { | 371 for (size_t i = 0; i < count; ++i) { |
371 if (source.HasSwitch(switches[i])) | 372 if (source.HasSwitch(switches[i])) |
372 AppendSwitchNative(switches[i], source.GetSwitchValueNative(switches[i])); | 373 AppendSwitchNative(switches[i], source.GetSwitchValueNative(switches[i])); |
373 } | 374 } |
374 } | 375 } |
375 | 376 |
376 CommandLine::StringVector CommandLine::GetArgs() const { | 377 CommandLine::StringVector CommandLine::GetArgs() const { |
377 // Gather all arguments after the last switch (may include kSwitchTerminator). | 378 // Gather all arguments after the last switch (may include kSwitchTerminator). |
378 StringVector args(argv_.begin() + begin_args_, argv_.end()); | 379 StringVector args(argv_.begin() + begin_args_, argv_.end()); |
379 // Erase only the first kSwitchTerminator (maybe "--" is a legitimate page?) | 380 // Erase only the first kSwitchTerminator (maybe "--" is a legitimate page?) |
380 StringVector::iterator switch_terminator = | 381 StringVector::iterator switch_terminator = |
381 std::find(args.begin(), args.end(), kSwitchTerminator); | 382 std::find(args.begin(), args.end(), kSwitchTerminator); |
382 if (switch_terminator != args.end()) | 383 if (switch_terminator != args.end()) |
383 args.erase(switch_terminator); | 384 args.erase(switch_terminator); |
384 return args; | 385 return args; |
385 } | 386 } |
386 | 387 |
387 void CommandLine::AppendArg(const std::string& value) { | 388 void CommandLine::AppendArg(const std::string& value) { |
388 #if defined(OS_WIN) | 389 #if defined(OS_WIN) |
389 DCHECK(IsStringUTF8(value)); | 390 DCHECK(IsStringUTF8(value)); |
390 AppendArgNative(base::UTF8ToWide(value)); | 391 AppendArgNative(UTF8ToWide(value)); |
391 #elif defined(OS_POSIX) | 392 #elif defined(OS_POSIX) |
392 AppendArgNative(value); | 393 AppendArgNative(value); |
393 #endif | 394 #endif |
394 } | 395 } |
395 | 396 |
396 void CommandLine::AppendArgPath(const FilePath& path) { | 397 void CommandLine::AppendArgPath(const FilePath& path) { |
397 AppendArgNative(path.value()); | 398 AppendArgNative(path.value()); |
398 } | 399 } |
399 | 400 |
400 void CommandLine::AppendArgNative(const CommandLine::StringType& value) { | 401 void CommandLine::AppendArgNative(const CommandLine::StringType& value) { |
401 argv_.push_back(value); | 402 argv_.push_back(value); |
402 } | 403 } |
403 | 404 |
404 void CommandLine::AppendArguments(const CommandLine& other, | 405 void CommandLine::AppendArguments(const CommandLine& other, |
405 bool include_program) { | 406 bool include_program) { |
406 if (include_program) | 407 if (include_program) |
407 SetProgram(other.GetProgram()); | 408 SetProgram(other.GetProgram()); |
408 AppendSwitchesAndArguments(*this, other.argv()); | 409 AppendSwitchesAndArguments(*this, other.argv()); |
409 } | 410 } |
410 | 411 |
411 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) { | 412 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) { |
412 if (wrapper.empty()) | 413 if (wrapper.empty()) |
413 return; | 414 return; |
414 // The wrapper may have embedded arguments (like "gdb --args"). In this case, | 415 // The wrapper may have embedded arguments (like "gdb --args"). In this case, |
415 // we don't pretend to do anything fancy, we just split on spaces. | 416 // we don't pretend to do anything fancy, we just split on spaces. |
416 StringVector wrapper_argv; | 417 StringVector wrapper_argv; |
417 base::SplitString(wrapper, FILE_PATH_LITERAL(' '), &wrapper_argv); | 418 SplitString(wrapper, FILE_PATH_LITERAL(' '), &wrapper_argv); |
418 // Prepend the wrapper and update the switches/arguments |begin_args_|. | 419 // Prepend the wrapper and update the switches/arguments |begin_args_|. |
419 argv_.insert(argv_.begin(), wrapper_argv.begin(), wrapper_argv.end()); | 420 argv_.insert(argv_.begin(), wrapper_argv.begin(), wrapper_argv.end()); |
420 begin_args_ += wrapper_argv.size(); | 421 begin_args_ += wrapper_argv.size(); |
421 } | 422 } |
422 | 423 |
423 #if defined(OS_WIN) | 424 #if defined(OS_WIN) |
424 void CommandLine::ParseFromString(const std::wstring& command_line) { | 425 void CommandLine::ParseFromString(const std::wstring& command_line) { |
425 std::wstring command_line_string; | 426 std::wstring command_line_string; |
426 base::TrimWhitespace(command_line, base::TRIM_ALL, &command_line_string); | 427 TrimWhitespace(command_line, TRIM_ALL, &command_line_string); |
427 if (command_line_string.empty()) | 428 if (command_line_string.empty()) |
428 return; | 429 return; |
429 | 430 |
430 int num_args = 0; | 431 int num_args = 0; |
431 wchar_t** args = NULL; | 432 wchar_t** args = NULL; |
432 args = ::CommandLineToArgvW(command_line_string.c_str(), &num_args); | 433 args = ::CommandLineToArgvW(command_line_string.c_str(), &num_args); |
433 | 434 |
434 DPLOG_IF(FATAL, !args) << "CommandLineToArgvW failed on command line: " | 435 DPLOG_IF(FATAL, !args) << "CommandLineToArgvW failed on command line: " |
435 << command_line; | 436 << UTF16ToUTF8(command_line); |
436 InitFromArgv(num_args, args); | 437 InitFromArgv(num_args, args); |
437 LocalFree(args); | 438 LocalFree(args); |
438 } | 439 } |
439 #endif | 440 #endif |
| 441 |
| 442 } // namespace base |
OLD | NEW |