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