command_line.cc revision 868fa2fe829687343ffae624259930155e16dbd8
13d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// Copyright (c) 2012 The Chromium Authors. All rights reserved. 23d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// Use of this source code is governed by a BSD-style license that can be 33d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// found in the LICENSE file. 43d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 50a16b22e64336d01967bc2a25c7c3a3bde0358afOscar Fuentes#include "base/command_line.h" 60a16b22e64336d01967bc2a25c7c3a3bde0358afOscar Fuentes 70a16b22e64336d01967bc2a25c7c3a3bde0358afOscar Fuentes#include <algorithm> 81221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#include <ostream> 91221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi 101221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#include "base/basictypes.h" 111221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#include "base/files/file_path.h" 121221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#include "base/logging.h" 131221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#include "base/string_util.h" 141221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#include "base/strings/string_split.h" 151221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#include "base/strings/utf_string_conversions.h" 161221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#include "build/build_config.h" 171221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi 181221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#if defined(OS_WIN) 191221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#include <windows.h> 201221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#include <shellapi.h> 211221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi#endif 221221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi 231221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumiusing base::FilePath; 241221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi 251221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA TakumiCommandLine* CommandLine::current_process_commandline_ = NULL; 261221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumi 271221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takuminamespace { 281221139f1089c7f7afaf0aff1049625a8d31be9dNAKAMURA Takumiconst CommandLine::CharType kSwitchTerminator[] = FILE_PATH_LITERAL("--"); 29da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentesconst CommandLine::CharType kSwitchValueSeparator[] = FILE_PATH_LITERAL("="); 30da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes// Since we use a lazy match, make sure that longer versions (like "--") are 31420d23c3d6c0fd0a5ec8f03acbbd222a377339daRafael Espindola// listed before shorter versions (like "-") of similar prefixes. 323d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#if defined(OS_WIN) 332c5e0b8b981dc9d1ea575037b9befa8c3b6102b8Oscar Fuentesconst CommandLine::CharType* const kSwitchPrefixes[] = {L"--", L"-", L"/"}; 343d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#elif defined(OS_POSIX) 353d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// Unixes don't use slash as a switch. 363d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesconst CommandLine::CharType* const kSwitchPrefixes[] = {"--", "-"}; 373d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#endif 38da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes 39da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentessize_t GetSwitchPrefixLength(const CommandLine::StringType& string) { 40da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) { 413d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes CommandLine::StringType prefix(kSwitchPrefixes[i]); 4260b531270b412621bf3d94186e96a38920ae78e8Oscar Fuentes if (string.compare(0, prefix.length(), prefix) == 0) 433d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return prefix.length(); 443d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes } 4560b531270b412621bf3d94186e96a38920ae78e8Oscar Fuentes return 0; 463d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 473d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 483d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// Fills in |switch_string| and |switch_value| if |string| is a switch. 493d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// This will preserve the input switch prefix in the output |switch_string|. 503d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesbool IsSwitch(const CommandLine::StringType& string, 5160b531270b412621bf3d94186e96a38920ae78e8Oscar Fuentes CommandLine::StringType* switch_string, 523d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes CommandLine::StringType* switch_value) { 533d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes switch_string->clear(); 5460b531270b412621bf3d94186e96a38920ae78e8Oscar Fuentes switch_value->clear(); 553d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes size_t prefix_length = GetSwitchPrefixLength(string); 563d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (prefix_length == 0 || prefix_length == string.length()) 5760b531270b412621bf3d94186e96a38920ae78e8Oscar Fuentes return false; 583d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 593d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes const size_t equals_position = string.find(kSwitchValueSeparator); 603d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes *switch_string = string.substr(0, equals_position); 613d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (equals_position != CommandLine::StringType::npos) 623d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes *switch_value = string.substr(equals_position + 1); 633d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return true; 643d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 653d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 663d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// Append switches and arguments, keeping switches before arguments. 673d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid AppendSwitchesAndArguments(CommandLine& command_line, 683d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes const CommandLine::StringVector& argv) { 69de98db33fb10a13ead2fa56d6d4c944cedb8fbadOscar Fuentes bool parse_switches = true; 703d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes for (size_t i = 1; i < argv.size(); ++i) { 716a660d4a438ba79d5d1aaccfe2ffecdef3d7d2f1Oscar Fuentes CommandLine::StringType arg = argv[i]; 726a660d4a438ba79d5d1aaccfe2ffecdef3d7d2f1Oscar Fuentes TrimWhitespace(arg, TRIM_ALL, &arg); 736a660d4a438ba79d5d1aaccfe2ffecdef3d7d2f1Oscar Fuentes 743d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes CommandLine::StringType switch_string; 75006bfeba06b99ac08a829b12a5f3cb748b810b02Oscar Fuentes CommandLine::StringType switch_value; 763d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes parse_switches &= (arg != kSwitchTerminator); 77da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes if (parse_switches && IsSwitch(arg, &switch_string, &switch_value)) { 78da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes#if defined(OS_WIN) 79da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes command_line.AppendSwitchNative(WideToASCII(switch_string), switch_value); 80da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes#elif defined(OS_POSIX) 81da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes command_line.AppendSwitchNative(switch_string, switch_value); 82da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes#endif 833d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes } else { 8419823b19baaaa7638e4e69d7e1342dfee0ef9f2fOscar Fuentes command_line.AppendArgNative(arg); 853d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes } 86e29b0aca51e3568a92869daa70c4a0351750fd1eNAKAMURA Takumi } 87e29b0aca51e3568a92869daa70c4a0351750fd1eNAKAMURA Takumi} 88e29b0aca51e3568a92869daa70c4a0351750fd1eNAKAMURA Takumi 89e29b0aca51e3568a92869daa70c4a0351750fd1eNAKAMURA Takumi// Lowercase switches for backwards compatiblity *on Windows*. 903d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesstd::string LowerASCIIOnWindows(const std::string& string) { 913d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#if defined(OS_WIN) 923d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return StringToLowerASCII(string); 933d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#elif defined(OS_POSIX) 943d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return string; 953d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#endif 963d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 973d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 983d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 993d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#if defined(OS_WIN) 1003d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// Quote a string as necessary for CommandLineToArgvW compatiblity *on Windows*. 1013c00a83c3362dc7d066454936ad36fbfb3fd26c5Oscar Fuentesstd::wstring QuoteForCommandLineToArgvW(const std::wstring& arg) { 1023d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // We follow the quoting rules of CommandLineToArgvW. 1033d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx 1043d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (arg.find_first_of(L" \\\"") == std::wstring::npos) { 1053d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // No quoting necessary. 1063d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return arg; 1073c00a83c3362dc7d066454936ad36fbfb3fd26c5Oscar Fuentes } 1083d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 1093d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes std::wstring out; 1103d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes out.push_back(L'"'); 1113d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes for (size_t i = 0; i < arg.size(); ++i) { 1123d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (arg[i] == '\\') { 1136a660d4a438ba79d5d1aaccfe2ffecdef3d7d2f1Oscar Fuentes // Find the extent of this run of backslashes. 1143d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes size_t start = i, end = start + 1; 1153d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes for (; end < arg.size() && arg[end] == '\\'; ++end) 116b5b10c25f72f983f5876c0091cc98be36a6a3f0aOscar Fuentes /* empty */; 1173d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes size_t backslash_count = end - start; 1183d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 1193d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // Backslashes are escapes only if the run is followed by a double quote. 1203d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // Since we also will end the string with a double quote, we escape for 1213d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // either a double quote or the end of the string. 1223d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (end == arg.size() || arg[end] == '"') { 1233d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // To quote, we need to output 2x as many backslashes. 1243d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes backslash_count *= 2; 1253c00a83c3362dc7d066454936ad36fbfb3fd26c5Oscar Fuentes } 1263d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes for (size_t j = 0; j < backslash_count; ++j) 1273d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes out.push_back('\\'); 1283d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 1293d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // Advance i to one before the end to balance i++ in loop. 1303d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes i = end - 1; 1313d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes } else if (arg[i] == '"') { 1323d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes out.push_back('\\'); 1336a660d4a438ba79d5d1aaccfe2ffecdef3d7d2f1Oscar Fuentes out.push_back('"'); 1346a660d4a438ba79d5d1aaccfe2ffecdef3d7d2f1Oscar Fuentes } else { 1356a660d4a438ba79d5d1aaccfe2ffecdef3d7d2f1Oscar Fuentes out.push_back(arg[i]); 136da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes } 137da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes } 138da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes out.push_back('"'); 139da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes 140596937914548c181f2504aad3b709189e87a561bOscar Fuentes return out; 141da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes} 142da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes#endif 143596937914548c181f2504aad3b709189e87a561bOscar Fuentes 144da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes} // namespace 145da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes 146596937914548c181f2504aad3b709189e87a561bOscar FuentesCommandLine::CommandLine(NoProgram no_program) 147da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes : argv_(1), 1483d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes begin_args_(1) { 149c6cf5fe595cd3cec3f8320ec29118e0e2b39b28cEdward O'Callaghan} 1503d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 1513d01fc7de86c75926e4e5ac7cc49f0116018893dOscar FuentesCommandLine::CommandLine(const FilePath& program) 152de98db33fb10a13ead2fa56d6d4c944cedb8fbadOscar Fuentes : argv_(1), 1533d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes begin_args_(1) { 15419823b19baaaa7638e4e69d7e1342dfee0ef9f2fOscar Fuentes SetProgram(program); 15519823b19baaaa7638e4e69d7e1342dfee0ef9f2fOscar Fuentes} 15619823b19baaaa7638e4e69d7e1342dfee0ef9f2fOscar Fuentes 1573d01fc7de86c75926e4e5ac7cc49f0116018893dOscar FuentesCommandLine::CommandLine(int argc, const CommandLine::CharType* const* argv) 158006bfeba06b99ac08a829b12a5f3cb748b810b02Oscar Fuentes : argv_(1), 1593d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes begin_args_(1) { 1603d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes InitFromArgv(argc, argv); 1613d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 1623d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 1633d01fc7de86c75926e4e5ac7cc49f0116018893dOscar FuentesCommandLine::CommandLine(const StringVector& argv) 164006bfeba06b99ac08a829b12a5f3cb748b810b02Oscar Fuentes : argv_(1), 1653d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes begin_args_(1) { 1663d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes InitFromArgv(argv); 1673d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 1683d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 1693d01fc7de86c75926e4e5ac7cc49f0116018893dOscar FuentesCommandLine::~CommandLine() { 170006bfeba06b99ac08a829b12a5f3cb748b810b02Oscar Fuentes} 1713d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 1723d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// static 1733d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesbool CommandLine::Init(int argc, const char* const* argv) { 1743d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (current_process_commandline_) { 1753d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // If this is intentional, Reset() must be called first. If we are using 1766a660d4a438ba79d5d1aaccfe2ffecdef3d7d2f1Oscar Fuentes // the shared build mode, we have to share a single object across multiple 1773d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // shared libraries. 1783d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return false; 17978e2074eeeee266f4b6b212800f00e9acddecb15Oscar Fuentes } 1803d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 1813d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes current_process_commandline_ = new CommandLine(NO_PROGRAM); 18219823b19baaaa7638e4e69d7e1342dfee0ef9f2fOscar Fuentes#if defined(OS_WIN) 1833d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes current_process_commandline_->ParseFromString(::GetCommandLineW()); 1843d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#elif defined(OS_POSIX) 1853d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes current_process_commandline_->InitFromArgv(argc, argv); 1863d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#endif 1873d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 18801746745f1287effa1772ef51b973988afcea699Douglas Gregor return true; 1893d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 1903d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 1913d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// static 1923d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid CommandLine::Reset() { 1933d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes DCHECK(current_process_commandline_); 1943d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes delete current_process_commandline_; 1953d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes current_process_commandline_ = NULL; 1963d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 1973d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 1983d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// static 1993d01fc7de86c75926e4e5ac7cc49f0116018893dOscar FuentesCommandLine* CommandLine::ForCurrentProcess() { 2003d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes DCHECK(current_process_commandline_); 2013d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return current_process_commandline_; 2023d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 2033c00a83c3362dc7d066454936ad36fbfb3fd26c5Oscar Fuentes 2043d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#if defined(OS_WIN) 2053d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes// static 2063d01fc7de86c75926e4e5ac7cc49f0116018893dOscar FuentesCommandLine CommandLine::FromString(const std::wstring& command_line) { 2073d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes CommandLine cmd(NO_PROGRAM); 2083d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes cmd.ParseFromString(command_line); 2093d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return cmd; 2103d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 2113d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#endif 2123d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 2133d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid CommandLine::InitFromArgv(int argc, 2143d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes const CommandLine::CharType* const* argv) { 215d413c01088ff0bf9ab1d856f75ef2ba84427fd6dOscar Fuentes StringVector new_argv; 2163d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes for (int i = 0; i < argc; ++i) 2173d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes new_argv.push_back(argv[i]); 2183d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes InitFromArgv(new_argv); 2193d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 2203d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 2213d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid CommandLine::InitFromArgv(const StringVector& argv) { 2223d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes argv_ = StringVector(1); 223da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes begin_args_ = 1; 224da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes SetProgram(argv.empty() ? FilePath() : FilePath(argv[0])); 225da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes AppendSwitchesAndArguments(*this, argv); 2263d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 2273d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 2283d01fc7de86c75926e4e5ac7cc49f0116018893dOscar FuentesCommandLine::StringType CommandLine::GetCommandLineString() const { 2293d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes StringType string(argv_[0]); 2303d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#if defined(OS_WIN) 2313d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes string = QuoteForCommandLineToArgvW(string); 2323d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#endif 2333d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes StringType params(GetArgumentsString()); 23478e2074eeeee266f4b6b212800f00e9acddecb15Oscar Fuentes if (!params.empty()) { 2353d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes string.append(StringType(FILE_PATH_LITERAL(" "))); 2363d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes string.append(params); 2373c00a83c3362dc7d066454936ad36fbfb3fd26c5Oscar Fuentes } 2383d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return string; 2393d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 2403c00a83c3362dc7d066454936ad36fbfb3fd26c5Oscar Fuentes 2413d01fc7de86c75926e4e5ac7cc49f0116018893dOscar FuentesCommandLine::StringType CommandLine::GetArgumentsString() const { 2423d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes StringType params; 2433d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // Append switches and arguments. 2443d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes bool parse_switches = true; 2453d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes for (size_t i = 1; i < argv_.size(); ++i) { 2463d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes StringType arg = argv_[i]; 2473d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes StringType switch_string; 2483d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes StringType switch_value; 2493d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes parse_switches &= arg != kSwitchTerminator; 2503d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (i > 1) 2513d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes params.append(StringType(FILE_PATH_LITERAL(" "))); 252ef23d711bc4ff72799693f40c15b29cfdabd89a0Douglas Gregor if (parse_switches && IsSwitch(arg, &switch_string, &switch_value)) { 2533d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes params.append(switch_string); 2543d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (!switch_value.empty()) { 255006bfeba06b99ac08a829b12a5f3cb748b810b02Oscar Fuentes#if defined(OS_WIN) 2563d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes switch_value = QuoteForCommandLineToArgvW(switch_value); 2573d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#endif 258006bfeba06b99ac08a829b12a5f3cb748b810b02Oscar Fuentes params.append(kSwitchValueSeparator + switch_value); 2593d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes } 2603d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes } 2613d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes else { 2623d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#if defined(OS_WIN) 2633d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes arg = QuoteForCommandLineToArgvW(arg); 264a4e387933940539d811e4ec8561fc101a9fed48aDouglas Gregor#endif 2653d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes params.append(arg); 2663d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes } 267a4e387933940539d811e4ec8561fc101a9fed48aDouglas Gregor } 2683d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return params; 2693d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 270a4e387933940539d811e4ec8561fc101a9fed48aDouglas Gregor 2713d01fc7de86c75926e4e5ac7cc49f0116018893dOscar FuentesFilePath CommandLine::GetProgram() const { 2723d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return FilePath(argv_[0]); 2733d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 2743d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 2753d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid CommandLine::SetProgram(const FilePath& program) { 2763d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes TrimWhitespace(program.value(), TRIM_ALL, &argv_[0]); 2773d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 2783d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 2793d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesbool CommandLine::HasSwitch(const std::string& switch_string) const { 2803d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return switches_.find(LowerASCIIOnWindows(switch_string)) != switches_.end(); 2813d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 2823d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 2833d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesstd::string CommandLine::GetSwitchValueASCII( 2843d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes const std::string& switch_string) const { 2853d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes StringType value = GetSwitchValueNative(switch_string); 286a447cfea453b582092a7a1e5a7f71e695981c4d2Oscar Fuentes if (!IsStringASCII(value)) { 2873d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes DLOG(WARNING) << "Value of switch (" << switch_string << ") must be ASCII."; 2886a660d4a438ba79d5d1aaccfe2ffecdef3d7d2f1Oscar Fuentes return std::string(); 2896a660d4a438ba79d5d1aaccfe2ffecdef3d7d2f1Oscar Fuentes } 2906a660d4a438ba79d5d1aaccfe2ffecdef3d7d2f1Oscar Fuentes#if defined(OS_WIN) 2913d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return WideToASCII(value); 292006bfeba06b99ac08a829b12a5f3cb748b810b02Oscar Fuentes#else 2933d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return value; 294da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes#endif 295da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes} 296da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes 297da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar FuentesFilePath CommandLine::GetSwitchValuePath( 298da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes const std::string& switch_string) const { 299da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes return FilePath(GetSwitchValueNative(switch_string)); 3003d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 3013d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 3023d01fc7de86c75926e4e5ac7cc49f0116018893dOscar FuentesCommandLine::StringType CommandLine::GetSwitchValueNative( 3033d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes const std::string& switch_string) const { 3043d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes SwitchMap::const_iterator result = switches_.end(); 3053d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes result = switches_.find(LowerASCIIOnWindows(switch_string)); 306da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes return result == switches_.end() ? StringType() : result->second; 307da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes} 308da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes 309111fd9ce64726867c634dc8bbe042c6eb8de85fcOscar Fuentesvoid CommandLine::AppendSwitch(const std::string& switch_string) { 310ec8b2a95303ef51acdf5b034ab8f4371665fc136Oscar Fuentes AppendSwitchNative(switch_string, StringType()); 311ec8b2a95303ef51acdf5b034ab8f4371665fc136Oscar Fuentes} 3123d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 3133d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid CommandLine::AppendSwitchPath(const std::string& switch_string, 3143d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes const FilePath& path) { 315c7077c701541f7d07d41f3926f7ea9edd204347cDouglas Gregor AppendSwitchNative(switch_string, path.value()); 316c7077c701541f7d07d41f3926f7ea9edd204347cDouglas Gregor} 317c7077c701541f7d07d41f3926f7ea9edd204347cDouglas Gregor 3183d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid CommandLine::AppendSwitchNative(const std::string& switch_string, 31978e2074eeeee266f4b6b212800f00e9acddecb15Oscar Fuentes const CommandLine::StringType& value) { 3203d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes std::string switch_key(LowerASCIIOnWindows(switch_string)); 3213d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#if defined(OS_WIN) 32278e2074eeeee266f4b6b212800f00e9acddecb15Oscar Fuentes StringType combined_switch_string(ASCIIToWide(switch_key)); 3233d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#elif defined(OS_POSIX) 3243d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes StringType combined_switch_string(switch_string); 3253d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#endif 3263d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes size_t prefix_length = GetSwitchPrefixLength(combined_switch_string); 3273d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes switches_[switch_key.substr(prefix_length)] = value; 32878e2074eeeee266f4b6b212800f00e9acddecb15Oscar Fuentes // Preserve existing switch prefixes in |argv_|; only append one if necessary. 3293d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (prefix_length == 0) 3303d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes combined_switch_string = kSwitchPrefixes[0] + combined_switch_string; 3313d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (!value.empty()) 3323d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes combined_switch_string += kSwitchValueSeparator + value; 3334c297c9153899a41c541474187a3e3a8dbf8a794Chris Lattner // Append the switch and update the switches/arguments divider |begin_args_|. 3344c297c9153899a41c541474187a3e3a8dbf8a794Chris Lattner argv_.insert(argv_.begin() + begin_args_++, combined_switch_string); 3354c297c9153899a41c541474187a3e3a8dbf8a794Chris Lattner} 336da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes 337da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentesvoid CommandLine::AppendSwitchASCII(const std::string& switch_string, 338da7e2870eb43c464d06a2eea5edf42abdc59a9f1Oscar Fuentes const std::string& value_string) { 3393d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#if defined(OS_WIN) 340c6cf5fe595cd3cec3f8320ec29118e0e2b39b28cEdward O'Callaghan AppendSwitchNative(switch_string, ASCIIToWide(value_string)); 3413d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#elif defined(OS_POSIX) 342b7a8d400be7ce9e275c6e09a2a90fbacd0566476Jeffrey Yasskin AppendSwitchNative(switch_string, value_string); 343b7a8d400be7ce9e275c6e09a2a90fbacd0566476Jeffrey Yasskin#endif 344b7a8d400be7ce9e275c6e09a2a90fbacd0566476Jeffrey Yasskin} 3453d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 34678e2074eeeee266f4b6b212800f00e9acddecb15Oscar Fuentesvoid CommandLine::CopySwitchesFrom(const CommandLine& source, 3473d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes const char* const switches[], 3483d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes size_t count) { 3493d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes for (size_t i = 0; i < count; ++i) { 3503d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (source.HasSwitch(switches[i])) 3513d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes AppendSwitchNative(switches[i], source.GetSwitchValueNative(switches[i])); 3523d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes } 3533d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 3543d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 3553d01fc7de86c75926e4e5ac7cc49f0116018893dOscar FuentesCommandLine::StringVector CommandLine::GetArgs() const { 3563d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // Gather all arguments after the last switch (may include kSwitchTerminator). 3573d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes StringVector args(argv_.begin() + begin_args_, argv_.end()); 35878e2074eeeee266f4b6b212800f00e9acddecb15Oscar Fuentes // Erase only the first kSwitchTerminator (maybe "--" is a legitimate page?) 3593d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes StringVector::iterator switch_terminator = 3603d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes std::find(args.begin(), args.end(), kSwitchTerminator); 3613d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes if (switch_terminator != args.end()) 3623d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes args.erase(switch_terminator); 3633d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return args; 36478e2074eeeee266f4b6b212800f00e9acddecb15Oscar Fuentes} 3653d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 3663d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid CommandLine::AppendArg(const std::string& value) { 3673d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#if defined(OS_WIN) 3683d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes DCHECK(IsStringUTF8(value)); 3693d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes AppendArgNative(UTF8ToWide(value)); 3703d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#elif defined(OS_POSIX) 3713d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes AppendArgNative(value); 3723d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#endif 3733d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 3743d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 3753d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid CommandLine::AppendArgPath(const FilePath& path) { 3763d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes AppendArgNative(path.value()); 3773d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 3783d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 3793d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid CommandLine::AppendArgNative(const CommandLine::StringType& value) { 3803d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes argv_.push_back(value); 3813d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 3823c00a83c3362dc7d066454936ad36fbfb3fd26c5Oscar Fuentes 3833d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid CommandLine::AppendArguments(const CommandLine& other, 3843d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes bool include_program) { 3853c00a83c3362dc7d066454936ad36fbfb3fd26c5Oscar Fuentes if (include_program) 3863d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes SetProgram(other.GetProgram()); 3873d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes AppendSwitchesAndArguments(*this, other.argv()); 3883c00a83c3362dc7d066454936ad36fbfb3fd26c5Oscar Fuentes} 3893d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 3903d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentesvoid CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) { 3910cddc49b91db628353dbd7f97b8092b44d39d348Jeffrey Yasskin if (wrapper.empty()) 3923d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes return; 3933d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes // The wrapper may have embedded arguments (like "gdb --args"). In this case, 3940cddc49b91db628353dbd7f97b8092b44d39d348Jeffrey Yasskin // we don't pretend to do anything fancy, we just split on spaces. 395ed1c0ffe0b2287deaee7cba7506c93aa34c6d4b7Jeffrey Yasskin StringVector wrapper_argv; 3963d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes base::SplitString(wrapper, FILE_PATH_LITERAL(' '), &wrapper_argv); 3973c00a83c3362dc7d066454936ad36fbfb3fd26c5Oscar Fuentes // Prepend the wrapper and update the switches/arguments |begin_args_|. 3983d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes argv_.insert(argv_.begin(), wrapper_argv.begin(), wrapper_argv.end()); 3993d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes begin_args_ += wrapper_argv.size(); 400de98db33fb10a13ead2fa56d6d4c944cedb8fbadOscar Fuentes} 4013d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 4023d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#if defined(OS_WIN) 4033c00a83c3362dc7d066454936ad36fbfb3fd26c5Oscar Fuentesvoid CommandLine::ParseFromString(const std::wstring& command_line) { 4043d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes std::wstring command_line_string; 405111fd9ce64726867c634dc8bbe042c6eb8de85fcOscar Fuentes TrimWhitespace(command_line, TRIM_ALL, &command_line_string); 406111fd9ce64726867c634dc8bbe042c6eb8de85fcOscar Fuentes if (command_line_string.empty()) 407111fd9ce64726867c634dc8bbe042c6eb8de85fcOscar Fuentes return; 4083d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes 409de98db33fb10a13ead2fa56d6d4c944cedb8fbadOscar Fuentes int num_args = 0; 4103d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes wchar_t** args = NULL; 4113d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes args = ::CommandLineToArgvW(command_line_string.c_str(), &num_args); 41278e2074eeeee266f4b6b212800f00e9acddecb15Oscar Fuentes 4133d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes DPLOG_IF(FATAL, !args) << "CommandLineToArgvW failed on command line: " 4143d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes << command_line; 4153d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes InitFromArgv(num_args, args); 4163d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes LocalFree(args); 4173d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes} 4183d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes#endif 4193d01fc7de86c75926e4e5ac7cc49f0116018893dOscar Fuentes