1dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/command_line.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <algorithm>
8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <ostream>
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/basictypes.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_path.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h"
133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/string_split.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
163f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "build/build_config.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
183f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#if defined(OS_WIN)
193f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include <windows.h>
203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include <shellapi.h>
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCommandLine* CommandLine::current_process_commandline_ = NULL;
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
25dc0f95d653279beabeb9817299e2902918ba123eKristian Monsennamespace {
26dc0f95d653279beabeb9817299e2902918ba123eKristian Monsentypedef CommandLine::StringType::value_type CharType;
27dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst CharType kSwitchTerminator[] = FILE_PATH_LITERAL("--");
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst CharType kSwitchValueSeparator[] = FILE_PATH_LITERAL("=");
30dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Since we use a lazy match, make sure that longer versions (like "--") are
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// listed before shorter versions (like "-") of similar prefixes.
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
33dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst CharType* const kSwitchPrefixes[] = {L"--", L"-", L"/"};
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Unixes don't use slash as a switch.
36dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst CharType* const kSwitchPrefixes[] = {"--", "-"};
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
40dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Lowercase a string for case-insensitivity of switches.
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Is this desirable? It exists for backwards compatibility on Windows.
42dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid Lowercase(std::string* arg) {
43dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  transform(arg->begin(), arg->end(), arg->begin(), tolower);
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
46dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Quote a string if necessary, such that CommandLineToArgvW() will always
47dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// process it as a single argument.
48dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenstd::wstring WindowsStyleQuote(const std::wstring& arg) {
49dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // We follow the quoting rules of CommandLineToArgvW.
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
51dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (arg.find_first_of(L" \\\"") == std::wstring::npos) {
52dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    // No quoting necessary.
53dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return arg;
54dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  std::wstring out;
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.push_back(L'"');
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (size_t i = 0; i < arg.size(); ++i) {
59dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (arg[i] == '\\') {
60dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // Find the extent of this run of backslashes.
61dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      size_t start = i, end = start + 1;
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      for (; end < arg.size() && arg[end] == '\\'; ++end)
63dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        /* empty */;
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      size_t backslash_count = end - start;
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
66dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // Backslashes are escapes only if the run is followed by a double quote.
67dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // Since we also will end the string with a double quote, we escape for
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // either a double quote or the end of the string.
69dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      if (end == arg.size() || arg[end] == '"') {
70dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        // To quote, we need to output 2x as many backslashes.
71dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        backslash_count *= 2;
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      }
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      for (size_t j = 0; j < backslash_count; ++j)
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        out.push_back('\\');
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      // Advance i to one before the end to balance i++ in loop.
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      i = end - 1;
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else if (arg[i] == '"') {
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      out.push_back('\\');
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      out.push_back('"');
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else {
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      out.push_back(arg[i]);
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  out.push_back('"');
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return out;
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Returns true and fills in |switch_string| and |switch_value| if
92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// |parameter_string| represents a switch.
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool IsSwitch(const CommandLine::StringType& parameter_string,
94dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              std::string* switch_string,
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen              CommandLine::StringType* switch_value) {
96dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  switch_string->clear();
97dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  switch_value->clear();
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CommandLine::StringType prefix(kSwitchPrefixes[i]);
101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (parameter_string.find(prefix) != 0)
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const size_t switch_start = prefix.length();
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    const size_t equals_position = parameter_string.find(
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        kSwitchValueSeparator, switch_start);
107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    CommandLine::StringType switch_native;
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (equals_position == CommandLine::StringType::npos) {
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      switch_native = parameter_string.substr(switch_start);
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      switch_native = parameter_string.substr(
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen          switch_start, equals_position - switch_start);
113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      *switch_value = parameter_string.substr(equals_position + 1);
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    *switch_string = WideToASCII(switch_native);
117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    Lowercase(switch_string);
118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#else
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    *switch_string = switch_native;
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return true;
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return false;
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}  // namespace
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
130dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenCommandLine::CommandLine(NoProgram no_program) {
131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_POSIX)
132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Push an empty argument, because we always assume argv_[0] is a program.
133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  argv_.push_back("");
134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
1353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCommandLine::CommandLine(const FilePath& program) {
138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!program.empty()) {
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    program_ = program.value();
1413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // TODO(evanm): proper quoting here.
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    command_line_string_ = L'"' + program.value() + L'"';
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  argv_.push_back(program.value());
146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_POSIX)
1503345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickCommandLine::CommandLine(int argc, const char* const* argv) {
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  InitFromArgv(argc, argv);
1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
154dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenCommandLine::CommandLine(const StringVector& argv) {
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  InitFromArgv(argv);
1563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif  // OS_POSIX
158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
159dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenCommandLine::~CommandLine() {
160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::Init(int argc, const char* const* argv) {
164dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete current_process_commandline_;
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  current_process_commandline_ = new CommandLine;
166dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
167dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  current_process_commandline_->ParseFromString(::GetCommandLineW());
168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#elif defined(OS_POSIX)
169dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  current_process_commandline_->InitFromArgv(argc, argv);
170dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
172dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
173dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static
174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::Reset() {
175dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(current_process_commandline_);
176dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  delete current_process_commandline_;
177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  current_process_commandline_ = NULL;
178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
180dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static
181dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenCommandLine* CommandLine::ForCurrentProcess() {
182dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(current_process_commandline_);
183dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return current_process_commandline_;
184dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
185dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
186dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
187dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// static
188dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenCommandLine CommandLine::FromString(const std::wstring& command_line) {
189dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  CommandLine cmd;
190dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  cmd.ParseFromString(command_line);
191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return cmd;
192dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
193dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif  // OS_WIN
194dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
195dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_POSIX)
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid CommandLine::InitFromArgv(int argc, const char* const* argv) {
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (int i = 0; i < argc; ++i)
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    argv_.push_back(argv[i]);
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  InitFromArgv(argv_);
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
202dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::InitFromArgv(const StringVector& argv) {
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  argv_ = argv;
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool parse_switches = true;
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 1; i < argv_.size(); ++i) {
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const std::string& arg = argv_[i];
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!parse_switches) {
209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      args_.push_back(arg);
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (arg == kSwitchTerminator) {
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      parse_switches = false;
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string switch_string;
219dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    StringType switch_value;
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (IsSwitch(arg, &switch_string, &switch_value)) {
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      switches_[switch_string] = switch_value;
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      args_.push_back(arg);
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
227dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif  // OS_POSIX
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
229dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenCommandLine::StringType CommandLine::command_line_string() const {
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return command_line_string_;
232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#elif defined(OS_POSIX)
233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return JoinString(argv_, ' ');
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
237dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenFilePath CommandLine::GetProgram() const {
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return FilePath(program_);
240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#else
241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK_GT(argv_.size(), 0U);
242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return FilePath(argv_[0]);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool CommandLine::HasSwitch(const std::string& switch_string) const {
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string lowercased_switch(switch_string);
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Lowercase(&lowercased_switch);
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return switches_.find(lowercased_switch) != switches_.end();
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
2543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstd::string CommandLine::GetSwitchValueASCII(
2553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const std::string& switch_string) const {
256731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  CommandLine::StringType value = GetSwitchValueNative(switch_string);
257731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (!IsStringASCII(value)) {
258731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    LOG(WARNING) << "Value of --" << switch_string << " must be ASCII.";
259731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    return "";
260731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  }
261731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#if defined(OS_WIN)
262731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return WideToASCII(value);
263731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#else
264731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  return value;
265731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#endif
2663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2683345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickFilePath CommandLine::GetSwitchValuePath(
2693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const std::string& switch_string) const {
2703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return FilePath(GetSwitchValueNative(switch_string));
2713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2733345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickCommandLine::StringType CommandLine::GetSwitchValueNative(
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const std::string& switch_string) const {
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string lowercased_switch(switch_string);
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Lowercase(&lowercased_switch);
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
280dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SwitchMap::const_iterator result = switches_.find(lowercased_switch);
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == switches_.end()) {
2833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return CommandLine::StringType();
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return result->second;
2863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
289dc0f95d653279beabeb9817299e2902918ba123eKristian Monsensize_t CommandLine::GetSwitchCount() const {
290dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return switches_.size();
291731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick}
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid CommandLine::AppendSwitch(const std::string& switch_string) {
294dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  command_line_string_.append(L" ");
2963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string));
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switches_[switch_string] = L"";
298dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#elif defined(OS_POSIX)
299dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  argv_.push_back(kSwitchPrefixes[0] + switch_string);
300dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  switches_[switch_string] = "";
301dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
304dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::AppendSwitchPath(const std::string& switch_string,
305dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   const FilePath& path) {
306dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  AppendSwitchNative(switch_string, path.value());
3073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid CommandLine::AppendSwitchNative(const std::string& switch_string,
310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                     const CommandLine::StringType& value) {
311dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
312dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  StringType combined_switch_string =
3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      kSwitchPrefixes[0] + ASCIIToWide(switch_string);
3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!value.empty())
3153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value);
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  command_line_string_.append(L" ");
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  command_line_string_.append(combined_switch_string);
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
3203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  switches_[switch_string] = value;
321dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#elif defined(OS_POSIX)
322dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  StringType combined_switch_string = kSwitchPrefixes[0] + switch_string;
323dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!value.empty())
324dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    combined_switch_string += kSwitchValueSeparator + value;
325dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  argv_.push_back(combined_switch_string);
326dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  switches_[switch_string] = value;
327dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
328dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
329dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
330dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::AppendSwitchASCII(const std::string& switch_string,
331dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                    const std::string& value_string) {
332dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
333dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  AppendSwitchNative(switch_string, ASCIIToWide(value_string));
334dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#elif defined(OS_POSIX)
335dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  AppendSwitchNative(switch_string, value_string);
336dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
337dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
338dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
339dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::AppendSwitches(const CommandLine& other) {
340dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SwitchMap::const_iterator i;
341dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
342dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    AppendSwitchNative(i->first, i->second);
343dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
344dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
345dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::CopySwitchesFrom(const CommandLine& source,
346dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   const char* const switches[],
347dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                                   size_t count) {
348dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (size_t i = 0; i < count; ++i) {
349dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (source.HasSwitch(switches[i])) {
350dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      StringType value = source.GetSwitchValueNative(switches[i]);
351dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      AppendSwitchNative(switches[i], value);
352dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
3543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid CommandLine::AppendArg(const std::string& value) {
357dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  DCHECK(IsStringUTF8(value));
3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  AppendArgNative(UTF8ToWide(value));
360dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#elif defined(OS_POSIX)
361dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  AppendArgNative(value);
362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
364dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
365dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::AppendArgPath(const FilePath& path) {
366dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  AppendArgNative(path.value());
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
369dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::AppendArgNative(const CommandLine::StringType& value) {
370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  command_line_string_.append(L" ");
3723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  command_line_string_.append(WindowsStyleQuote(value));
373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  args_.push_back(value);
374dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#elif defined(OS_POSIX)
375dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(IsStringUTF8(value));
376dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  argv_.push_back(value);
377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
378dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
379dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
380dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::AppendArgs(const CommandLine& other) {
381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if(other.args_.size() <= 0)
382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  command_line_string_.append(L" --");
385dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif  // OS_WIN
386dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  StringVector::const_iterator i;
387dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (i = other.args_.begin(); i != other.args_.end(); ++i)
388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    AppendArgNative(*i);
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid CommandLine::AppendArguments(const CommandLine& other,
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                  bool include_program) {
393dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Verify include_program is used correctly.
395dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  DCHECK(!include_program || !other.GetProgram().empty());
3964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (include_program)
3974a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    program_ = other.program_;
3984a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
3994a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (!command_line_string_.empty())
4004a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    command_line_string_ += L' ';
4014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
4024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  command_line_string_ += other.command_line_string_;
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Verify include_program is used correctly.
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Logic could be shorter but this is clearer.
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(include_program, !other.GetProgram().empty());
4074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
4084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (include_program)
4094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    argv_[0] = other.argv_[0];
4104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
4114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // Skip the first arg when copying since it's the program but push all
4124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  // arguments to our arg vector.
4134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  for (size_t i = 1; i < other.argv_.size(); ++i)
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    argv_.push_back(other.argv_[i]);
415dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
4164a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch
417dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  SwitchMap::const_iterator i;
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    switches_[i->first] = i->second;
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
422dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) {
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The wrapper may have embedded arguments (like "gdb --args"). In this case,
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // we don't pretend to do anything fancy, we just split on spaces.
425dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (wrapper.empty())
426dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
427dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  StringVector wrapper_and_args;
428dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
429dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  base::SplitString(wrapper, ' ', &wrapper_and_args);
430dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  program_ = wrapper_and_args[0];
431dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  command_line_string_ = wrapper + L" " + command_line_string_;
432dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#elif defined(OS_POSIX)
433731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  base::SplitString(wrapper, ' ', &wrapper_and_args);
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end());
435dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
438dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
439dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid CommandLine::ParseFromString(const std::wstring& command_line) {
440dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
442dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (command_line_string_.empty())
443dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
4443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
445dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  int num_args = 0;
446dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  wchar_t** args = NULL;
4473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
448dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);
449dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
450dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Populate program_ with the trimmed version of the first arg.
451dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  TrimWhitespace(args[0], TRIM_ALL, &program_);
452dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
453dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  bool parse_switches = true;
454dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  for (int i = 1; i < num_args; ++i) {
455dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::wstring arg;
456dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    TrimWhitespace(args[i], TRIM_ALL, &arg);
457dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
458dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (!parse_switches) {
459dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      args_.push_back(arg);
460dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      continue;
461dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
462dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
463dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (arg == kSwitchTerminator) {
464dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      parse_switches = false;
465dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      continue;
466dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    }
467dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
468dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::string switch_string;
469dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    std::wstring switch_value;
470dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    if (IsSwitch(arg, &switch_string, &switch_value)) {
471dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      switches_[switch_string] = switch_value;
472dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    } else {
473dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      args_.push_back(arg);
4743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    }
4753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
4763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
477dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (args)
478dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    LocalFree(args);
479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
480dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
4813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
482dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenCommandLine::CommandLine() {
4833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
484