Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Side by Side Diff: base/command_line.cc

Issue 6526040: CommandLine refactoring and cleanup. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address some comments. Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/command_line.h" 5 #include "base/command_line.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <ostream> 8 #include <ostream>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
11 #include "base/file_path.h" 11 #include "base/file_path.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/string_split.h" 13 #include "base/string_split.h"
14 #include "base/string_util.h" 14 #include "base/string_util.h"
15 #include "base/utf_string_conversions.h" 15 #include "base/utf_string_conversions.h"
16 #include "build/build_config.h" 16 #include "build/build_config.h"
17 17
18 #if defined(OS_WIN) 18 #if defined(OS_WIN)
19 #include <windows.h> 19 #include <windows.h>
20 #include <shellapi.h> 20 #include <shellapi.h>
21 #endif 21 #endif
22 22
23 CommandLine* CommandLine::current_process_commandline_ = NULL; 23 CommandLine* CommandLine::current_process_commandline_ = NULL;
24 24
25 namespace { 25 namespace {
26 typedef CommandLine::StringType::value_type CharType; 26 const CommandLine::CharType kSwitchTerminator[] = FILE_PATH_LITERAL("--");
27 27 const CommandLine::CharType kSwitchValueSeparator[] = FILE_PATH_LITERAL("=");
28 const CharType kSwitchTerminator[] = FILE_PATH_LITERAL("--");
29 const CharType kSwitchValueSeparator[] = FILE_PATH_LITERAL("=");
30 // Since we use a lazy match, make sure that longer versions (like "--") are 28 // Since we use a lazy match, make sure that longer versions (like "--") are
31 // listed before shorter versions (like "-") of similar prefixes. 29 // listed before shorter versions (like "-") of similar prefixes.
32 #if defined(OS_WIN) 30 #if defined(OS_WIN)
33 const CharType* const kSwitchPrefixes[] = {L"--", L"-", L"/"}; 31 const CommandLine::CharType* const kSwitchPrefixes[] = {L"--", L"-", L"/"};
34 #elif defined(OS_POSIX) 32 #elif defined(OS_POSIX)
35 // Unixes don't use slash as a switch. 33 // Unixes don't use slash as a switch.
36 const CharType* const kSwitchPrefixes[] = {"--", "-"}; 34 const CommandLine::CharType* const kSwitchPrefixes[] = {"--", "-"};
37 #endif 35 #endif
38 36
37 // Get the string in its platform's native string type.
38 // TODO(msw): Use string16 throughout.
39 CommandLine::StringType GetNativeString(const std::string& string) {
grt (UTC plus 2) 2011/05/11 14:27:32 These two functions assume that |string| is or can
msw 2011/05/12 00:37:47 I nixed GetNativeString and refactored, pushing ou
39 #if defined(OS_WIN) 40 #if defined(OS_WIN)
41 return ASCIIToWide(string);
42 #elif defined(OS_POSIX)
43 return string;
44 #endif
45 }
46
47 // Get the string in its platform's native string type.
48 // TODO(msw): Use string16 throughout.
49 CommandLine::StringType GetNativeString(const std::wstring& string) {
50 #if defined(OS_WIN)
51 return string;
52 #elif defined(OS_POSIX)
53 return WideToASCII(string);
54 #endif
55 }
56
40 // Lowercase a string for case-insensitivity of switches. 57 // Lowercase a string for case-insensitivity of switches.
grt (UTC plus 2) 2011/05/11 14:27:32 consider wrapping these in #if defined(OS_WIN) to
msw 2011/05/12 00:37:47 I nixed Lowercase for StringToLowerASCII, but wrap
41 // Is this desirable? It exists for backwards compatibility on Windows. 58 // This exists for backwards compatibility *on Windows*.
42 void Lowercase(std::string* arg) { 59 void Lowercase(std::string* arg) {
43 transform(arg->begin(), arg->end(), arg->begin(), tolower); 60 transform(arg->begin(), arg->end(), arg->begin(), tolower);
44 } 61 }
45 62
46 // Quote a string if necessary, such that CommandLineToArgvW() will always 63 // Quote a string as necessary for CommandLineToArgvW compatiblity *on Windows*.
47 // process it as a single argument. 64 std::wstring QuoteForCommandLineToArgvW(const std::wstring& arg) {
48 std::wstring WindowsStyleQuote(const std::wstring& arg) {
49 // We follow the quoting rules of CommandLineToArgvW. 65 // We follow the quoting rules of CommandLineToArgvW.
50 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx 66 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
51 if (arg.find_first_of(L" \\\"") == std::wstring::npos) { 67 if (arg.find_first_of(L" \\\"") == std::wstring::npos) {
52 // No quoting necessary. 68 // No quoting necessary.
53 return arg; 69 return arg;
54 } 70 }
55 71
56 std::wstring out; 72 std::wstring out;
57 out.push_back(L'"'); 73 out.push_back(L'"');
58 for (size_t i = 0; i < arg.size(); ++i) { 74 for (size_t i = 0; i < arg.size(); ++i) {
(...skipping 20 matching lines...) Expand all
79 out.push_back('\\'); 95 out.push_back('\\');
80 out.push_back('"'); 96 out.push_back('"');
81 } else { 97 } else {
82 out.push_back(arg[i]); 98 out.push_back(arg[i]);
83 } 99 }
84 } 100 }
85 out.push_back('"'); 101 out.push_back('"');
86 102
87 return out; 103 return out;
88 } 104 }
89 #endif
90 105
91 // Returns true and fills in |switch_string| and |switch_value| if 106 size_t GetSwitchPrefixLength(const CommandLine::StringType& string) {
92 // |parameter_string| represents a switch. 107 for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
93 bool IsSwitch(const CommandLine::StringType& parameter_string, 108 CommandLine::StringType prefix(kSwitchPrefixes[i]);
109 if (string.find(prefix) == 0)
110 return prefix.length();
111 }
112 return 0;
113 }
114
115 // Fills in |switch_string| and |switch_value| if |string| is a switch.
116 bool IsSwitch(const CommandLine::StringType& string,
94 std::string* switch_string, 117 std::string* switch_string,
95 CommandLine::StringType* switch_value) { 118 CommandLine::StringType* switch_value) {
96 switch_string->clear(); 119 switch_string->clear();
97 switch_value->clear(); 120 switch_value->clear();
121 if (GetSwitchPrefixLength(string) == 0)
122 return false;
98 123
99 for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) { 124 const size_t equals_position = string.find(kSwitchValueSeparator);
100 CommandLine::StringType prefix(kSwitchPrefixes[i]); 125 CommandLine::StringType switch_native = string.substr(0, equals_position);
101 if (parameter_string.find(prefix) != 0) 126 #if defined(OS_WIN)
102 continue; 127 *switch_string = WideToASCII(switch_native);
128 Lowercase(switch_string);
129 #elif defined(OS_POSIX)
130 *switch_string = switch_native;
131 #endif
132 if(equals_position != CommandLine::StringType::npos)
133 *switch_value = string.substr(equals_position + 1);
134 return true;
135 }
103 136
104 const size_t switch_start = prefix.length(); 137 void AppendSwitchesAndArguments(CommandLine& command_line,
105 const size_t equals_position = parameter_string.find( 138 const CommandLine::StringVector& argv) {
106 kSwitchValueSeparator, switch_start); 139 // Append switches and arguments, keeping switches before arguments.
107 CommandLine::StringType switch_native; 140 bool parse_switches = true;
108 if (equals_position == CommandLine::StringType::npos) { 141 for (size_t i = 1; i < argv.size(); ++i) {
109 switch_native = parameter_string.substr(switch_start); 142 CommandLine::StringType arg = argv[i];
110 } else { 143 TrimWhitespace(arg, TRIM_ALL, &arg);
111 switch_native = parameter_string.substr(
112 switch_start, equals_position - switch_start);
113 *switch_value = parameter_string.substr(equals_position + 1);
114 }
115 #if defined(OS_WIN)
116 *switch_string = WideToASCII(switch_native);
117 Lowercase(switch_string);
118 #else
119 *switch_string = switch_native;
120 #endif
121 144
122 return true; 145 std::string switch_string;
146 CommandLine::StringType switch_value;
147 parse_switches &= arg != kSwitchTerminator;
148 if (parse_switches && IsSwitch(arg, &switch_string, &switch_value))
149 command_line.AppendSwitchNative(switch_string, switch_value);
150 else
151 command_line.AppendArgNative(arg);
123 } 152 }
124
125 return false;
126 } 153 }
127 154
128 } // namespace 155 } // namespace
129 156
130 CommandLine::CommandLine(NoProgram no_program) { 157 CommandLine::CommandLine(NoProgram no_program)
131 #if defined(OS_POSIX) 158 : argv_(1),
132 // Push an empty argument, because we always assume argv_[0] is a program. 159 begin_args_(1) {
133 argv_.push_back("");
134 #endif
135 } 160 }
136 161
137 CommandLine::CommandLine(const FilePath& program) { 162 CommandLine::CommandLine(const FilePath& program)
138 #if defined(OS_WIN) 163 : argv_(1),
139 if (!program.empty()) { 164 begin_args_(1) {
140 program_ = program.value(); 165 SetProgram(program);
141 // TODO(evanm): proper quoting here.
142 command_line_string_ = L'"' + program.value() + L'"';
143 }
144 #elif defined(OS_POSIX)
145 argv_.push_back(program.value());
146 #endif
147 } 166 }
148 167
149 #if defined(OS_POSIX) 168 CommandLine::CommandLine(int argc, const CommandLine::CharType* const* argv)
150 CommandLine::CommandLine(int argc, const char* const* argv) { 169 : argv_(1),
170 begin_args_(1) {
151 InitFromArgv(argc, argv); 171 InitFromArgv(argc, argv);
152 } 172 }
153 173
154 CommandLine::CommandLine(const StringVector& argv) { 174 CommandLine::CommandLine(const StringVector& argv)
175 : argv_(1),
176 begin_args_(1) {
155 InitFromArgv(argv); 177 InitFromArgv(argv);
156 } 178 }
157 #endif // OS_POSIX
158 179
159 CommandLine::~CommandLine() { 180 CommandLine::~CommandLine() {
160 } 181 }
161 182
162 // static 183 // static
163 void CommandLine::Init(int argc, const char* const* argv) { 184 void CommandLine::Init(int argc, const char* const* argv) {
164 delete current_process_commandline_; 185 delete current_process_commandline_;
165 current_process_commandline_ = new CommandLine; 186 current_process_commandline_ = new CommandLine(NO_PROGRAM);
166 #if defined(OS_WIN) 187 #if defined(OS_WIN)
167 current_process_commandline_->ParseFromString(::GetCommandLineW()); 188 current_process_commandline_->ParseFromString(::GetCommandLineW());
168 #elif defined(OS_POSIX) 189 #elif defined(OS_POSIX)
169 current_process_commandline_->InitFromArgv(argc, argv); 190 current_process_commandline_->InitFromArgv(argc, argv);
170 #endif 191 #endif
171 } 192 }
172 193
173 // static 194 // static
174 void CommandLine::Reset() { 195 void CommandLine::Reset() {
175 DCHECK(current_process_commandline_); 196 DCHECK(current_process_commandline_);
176 delete current_process_commandline_; 197 delete current_process_commandline_;
177 current_process_commandline_ = NULL; 198 current_process_commandline_ = NULL;
178 } 199 }
179 200
180 // static 201 // static
181 CommandLine* CommandLine::ForCurrentProcess() { 202 CommandLine* CommandLine::ForCurrentProcess() {
182 DCHECK(current_process_commandline_); 203 DCHECK(current_process_commandline_);
183 return current_process_commandline_; 204 return current_process_commandline_;
184 } 205 }
185 206
186 #if defined(OS_WIN) 207 #if defined(OS_WIN)
187 // static 208 // static
188 CommandLine CommandLine::FromString(const std::wstring& command_line) { 209 CommandLine CommandLine::FromString(const std::wstring& command_line) {
189 CommandLine cmd; 210 CommandLine cmd(NO_PROGRAM);
190 cmd.ParseFromString(command_line); 211 cmd.ParseFromString(command_line);
191 return cmd; 212 return cmd;
192 } 213 }
193 #endif // OS_WIN 214 #endif
194 215
195 #if defined(OS_POSIX) 216 void CommandLine::InitFromArgv(int argc,
196 void CommandLine::InitFromArgv(int argc, const char* const* argv) { 217 const CommandLine::CharType* const* argv) {
218 StringVector new_argv;
197 for (int i = 0; i < argc; ++i) 219 for (int i = 0; i < argc; ++i)
198 argv_.push_back(argv[i]); 220 new_argv.push_back(argv[i]);
199 InitFromArgv(argv_); 221 InitFromArgv(new_argv);
200 } 222 }
201 223
202 void CommandLine::InitFromArgv(const StringVector& argv) { 224 void CommandLine::InitFromArgv(const StringVector& argv) {
203 argv_ = argv; 225 argv_ = StringVector(1);
226 begin_args_ = 1;
227 SetProgram(argv.empty() ? FilePath() : FilePath(argv[0]));
228 AppendSwitchesAndArguments(*this, argv);
229 }
230
231 CommandLine::StringType CommandLine::command_line_string() const {
232 StringType string(argv_[0]);
233 #if defined(OS_WIN)
234 string = QuoteForCommandLineToArgvW(string);
235 #endif
236 // Append switches and arguments.
204 bool parse_switches = true; 237 bool parse_switches = true;
205 for (size_t i = 1; i < argv_.size(); ++i) { 238 for (size_t i = 1; i < argv_.size(); ++i) {
206 const std::string& arg = argv_[i]; 239 CommandLine::StringType arg = argv_[i];
207 240 std::string switch_string;
208 if (!parse_switches) { 241 CommandLine::StringType switch_value;
209 args_.push_back(arg); 242 parse_switches &= argv_[i] != kSwitchTerminator;
210 continue; 243 string.append(StringType(FILE_PATH_LITERAL(" ")));
244 if (parse_switches && IsSwitch(argv_[i], &switch_string, &switch_value)) {
245 string.append(GetNativeString(switch_string));
246 if (!switch_value.empty()) {
247 #if defined(OS_WIN)
248 switch_value = QuoteForCommandLineToArgvW(switch_value);
249 #endif
250 string.append(kSwitchValueSeparator + switch_value);
251 }
211 } 252 }
212 253 else {
213 if (arg == kSwitchTerminator) { 254 #if defined(OS_WIN)
214 parse_switches = false; 255 arg = QuoteForCommandLineToArgvW(arg);
215 continue; 256 #endif
216 } 257 string.append(arg);
217
218 std::string switch_string;
219 StringType switch_value;
220 if (IsSwitch(arg, &switch_string, &switch_value)) {
221 switches_[switch_string] = switch_value;
222 } else {
223 args_.push_back(arg);
224 } 258 }
225 } 259 }
226 } 260 return string;
227 #endif // OS_POSIX
228
229 CommandLine::StringType CommandLine::command_line_string() const {
230 #if defined(OS_WIN)
231 return command_line_string_;
232 #elif defined(OS_POSIX)
233 return JoinString(argv_, ' ');
234 #endif
235 } 261 }
236 262
237 FilePath CommandLine::GetProgram() const { 263 FilePath CommandLine::GetProgram() const {
238 #if defined(OS_WIN) 264 return FilePath(program_string_);
239 return FilePath(program_); 265 }
240 #else 266
241 DCHECK_GT(argv_.size(), 0U); 267 void CommandLine::SetProgram(const FilePath& program) {
242 return FilePath(argv_[0]); 268 program_string_ = program.value();
243 #endif 269 TrimWhitespace(program_string_, TRIM_ALL, &program_string_);
270 argv_[0] = program_string_;
244 } 271 }
245 272
246 bool CommandLine::HasSwitch(const std::string& switch_string) const { 273 bool CommandLine::HasSwitch(const std::string& switch_string) const {
247 std::string lowercased_switch(switch_string); 274 std::string lowercased_switch(switch_string);
248 #if defined(OS_WIN) 275 #if defined(OS_WIN)
249 Lowercase(&lowercased_switch); 276 Lowercase(&lowercased_switch);
250 #endif 277 #endif
251 return switches_.find(lowercased_switch) != switches_.end(); 278 return switches_.find(lowercased_switch) != switches_.end();
252 } 279 }
253 280
254 std::string CommandLine::GetSwitchValueASCII( 281 std::string CommandLine::GetSwitchValueASCII(
255 const std::string& switch_string) const { 282 const std::string& switch_string) const {
256 CommandLine::StringType value = GetSwitchValueNative(switch_string); 283 StringType value = GetSwitchValueNative(switch_string);
257 if (!IsStringASCII(value)) { 284 if (!IsStringASCII(value)) {
258 LOG(WARNING) << "Value of --" << switch_string << " must be ASCII."; 285 LOG(WARNING) << "Value of --" << switch_string << " must be ASCII.";
259 return ""; 286 return "";
260 } 287 }
261 #if defined(OS_WIN) 288 #if defined(OS_WIN)
262 return WideToASCII(value); 289 return WideToASCII(value);
263 #else 290 #else
264 return value; 291 return value;
265 #endif 292 #endif
266 } 293 }
267 294
268 FilePath CommandLine::GetSwitchValuePath( 295 FilePath CommandLine::GetSwitchValuePath(
269 const std::string& switch_string) const { 296 const std::string& switch_string) const {
270 return FilePath(GetSwitchValueNative(switch_string)); 297 return FilePath(GetSwitchValueNative(switch_string));
271 } 298 }
272 299
273 CommandLine::StringType CommandLine::GetSwitchValueNative( 300 CommandLine::StringType CommandLine::GetSwitchValueNative(
274 const std::string& switch_string) const { 301 const std::string& switch_string) const {
275 std::string lowercased_switch(switch_string); 302 std::string lowercased_switch(switch_string);
276 #if defined(OS_WIN) 303 #if defined(OS_WIN)
277 Lowercase(&lowercased_switch); 304 Lowercase(&lowercased_switch);
278 #endif 305 #endif
279
280 SwitchMap::const_iterator result = switches_.find(lowercased_switch); 306 SwitchMap::const_iterator result = switches_.find(lowercased_switch);
281 307 return result == switches_.end() ? StringType() : result->second;
282 if (result == switches_.end()) {
283 return CommandLine::StringType();
284 } else {
285 return result->second;
286 }
287 } 308 }
288 309
289 size_t CommandLine::GetSwitchCount() const { 310 size_t CommandLine::GetSwitchCount() const {
290 return switches_.size(); 311 return switches_.size();
291 } 312 }
292 313
293 void CommandLine::AppendSwitch(const std::string& switch_string) { 314 void CommandLine::AppendSwitch(const std::string& switch_string) {
294 #if defined(OS_WIN) 315 AppendSwitchNative(switch_string, StringType());
295 command_line_string_.append(L" ");
296 command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string));
297 switches_[switch_string] = L"";
298 #elif defined(OS_POSIX)
299 argv_.push_back(kSwitchPrefixes[0] + switch_string);
300 switches_[switch_string] = "";
301 #endif
302 } 316 }
303 317
304 void CommandLine::AppendSwitchPath(const std::string& switch_string, 318 void CommandLine::AppendSwitchPath(const std::string& switch_string,
305 const FilePath& path) { 319 const FilePath& path) {
306 AppendSwitchNative(switch_string, path.value()); 320 AppendSwitchNative(switch_string, path.value());
307 } 321 }
308 322
309 void CommandLine::AppendSwitchNative(const std::string& switch_string, 323 void CommandLine::AppendSwitchNative(const std::string& switch_string,
310 const CommandLine::StringType& value) { 324 const CommandLine::StringType& value) {
311 #if defined(OS_WIN) 325 StringType combined_switch_string = GetNativeString(switch_string);
312 StringType combined_switch_string = 326 size_t prefix_length = GetSwitchPrefixLength(combined_switch_string);
313 kSwitchPrefixes[0] + ASCIIToWide(switch_string); 327 switches_[switch_string.substr(prefix_length)] = value;
314 if (!value.empty()) 328 // Preserve existing switch prefixes in |argv_|; only append one if necessary.
315 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value); 329 if (prefix_length == 0)
316 330 combined_switch_string = kSwitchPrefixes[0] + combined_switch_string;
317 command_line_string_.append(L" ");
318 command_line_string_.append(combined_switch_string);
319
320 switches_[switch_string] = value;
321 #elif defined(OS_POSIX)
322 StringType combined_switch_string = kSwitchPrefixes[0] + switch_string;
323 if (!value.empty()) 331 if (!value.empty())
324 combined_switch_string += kSwitchValueSeparator + value; 332 combined_switch_string += kSwitchValueSeparator + value;
325 argv_.push_back(combined_switch_string); 333 // Append the switch and update the switches/arguments divider |begin_args_|.
326 switches_[switch_string] = value; 334 argv_.insert(argv_.begin() + begin_args_++, combined_switch_string);
327 #endif
328 } 335 }
329 336
330 void CommandLine::AppendSwitchASCII(const std::string& switch_string, 337 void CommandLine::AppendSwitchASCII(const std::string& switch_string,
331 const std::string& value_string) { 338 const std::string& value_string) {
332 #if defined(OS_WIN) 339 AppendSwitchNative(switch_string, GetNativeString(value_string));
333 AppendSwitchNative(switch_string, ASCIIToWide(value_string));
334 #elif defined(OS_POSIX)
335 AppendSwitchNative(switch_string, value_string);
336 #endif
337 }
338
339 void CommandLine::AppendSwitches(const CommandLine& other) {
340 SwitchMap::const_iterator i;
341 for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
342 AppendSwitchNative(i->first, i->second);
343 } 340 }
344 341
345 void CommandLine::CopySwitchesFrom(const CommandLine& source, 342 void CommandLine::CopySwitchesFrom(const CommandLine& source,
346 const char* const switches[], 343 const char* const switches[],
347 size_t count) { 344 size_t count) {
348 for (size_t i = 0; i < count; ++i) { 345 for (size_t i = 0; i < count; ++i)
349 if (source.HasSwitch(switches[i])) { 346 if (source.HasSwitch(switches[i]))
350 StringType value = source.GetSwitchValueNative(switches[i]); 347 AppendSwitchNative(switches[i], source.GetSwitchValueNative(switches[i]));
351 AppendSwitchNative(switches[i], value); 348 }
352 } 349
353 } 350 CommandLine::StringVector CommandLine::args() const {
351 // Gather all arguments after the last switch (may include kSwitchTerminator).
352 StringVector args(argv_.begin() + begin_args_, argv_.end());
353 // Erase only the first kSwitchTerminator (maybe "--" is a legitimate page?)
354 StringVector::iterator switch_terminator =
355 std::find(args.begin(), args.end(), kSwitchTerminator);
356 if (switch_terminator != args.end())
357 args.erase(switch_terminator);
358 return args;
354 } 359 }
355 360
356 void CommandLine::AppendArg(const std::string& value) { 361 void CommandLine::AppendArg(const std::string& value) {
357 #if defined(OS_WIN) 362 #if defined(OS_WIN)
358 DCHECK(IsStringUTF8(value)); 363 DCHECK(IsStringUTF8(value));
359 AppendArgNative(UTF8ToWide(value)); 364 AppendArgNative(UTF8ToWide(value));
360 #elif defined(OS_POSIX) 365 #elif defined(OS_POSIX)
361 AppendArgNative(value); 366 AppendArgNative(value);
362 #endif 367 #endif
363 } 368 }
364 369
365 void CommandLine::AppendArgPath(const FilePath& path) { 370 void CommandLine::AppendArgPath(const FilePath& path) {
366 AppendArgNative(path.value()); 371 AppendArgNative(path.value());
367 } 372 }
368 373
369 void CommandLine::AppendArgNative(const CommandLine::StringType& value) { 374 void CommandLine::AppendArgNative(const CommandLine::StringType& value) {
370 #if defined(OS_WIN)
371 command_line_string_.append(L" ");
372 command_line_string_.append(WindowsStyleQuote(value));
373 args_.push_back(value);
374 #elif defined(OS_POSIX)
375 DCHECK(IsStringUTF8(value));
376 argv_.push_back(value); 375 argv_.push_back(value);
377 #endif
378 }
379
380 void CommandLine::AppendArgs(const CommandLine& other) {
381 if(other.args_.size() <= 0)
382 return;
383 #if defined(OS_WIN)
384 command_line_string_.append(L" --");
385 #endif // OS_WIN
386 StringVector::const_iterator i;
387 for (i = other.args_.begin(); i != other.args_.end(); ++i)
388 AppendArgNative(*i);
389 } 376 }
390 377
391 void CommandLine::AppendArguments(const CommandLine& other, 378 void CommandLine::AppendArguments(const CommandLine& other,
392 bool include_program) { 379 bool include_program) {
393 #if defined(OS_WIN)
394 // Verify include_program is used correctly.
395 DCHECK(!include_program || !other.GetProgram().empty());
396 if (include_program) 380 if (include_program)
397 program_ = other.program_; 381 SetProgram(other.GetProgram());
398 382 AppendSwitchesAndArguments(*this, other.argv());
399 if (!command_line_string_.empty())
400 command_line_string_ += L' ';
401
402 command_line_string_ += other.command_line_string_;
403 #elif defined(OS_POSIX)
404 // Verify include_program is used correctly.
405 // Logic could be shorter but this is clearer.
406 DCHECK_EQ(include_program, !other.GetProgram().empty());
407
408 if (include_program)
409 argv_[0] = other.argv_[0];
410
411 // Skip the first arg when copying since it's the program but push all
412 // arguments to our arg vector.
413 for (size_t i = 1; i < other.argv_.size(); ++i)
414 argv_.push_back(other.argv_[i]);
415 #endif
416
417 SwitchMap::const_iterator i;
418 for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
419 switches_[i->first] = i->second;
420 } 383 }
421 384
422 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) { 385 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) {
386 if (wrapper.empty())
387 return;
423 // The wrapper may have embedded arguments (like "gdb --args"). In this case, 388 // The wrapper may have embedded arguments (like "gdb --args"). In this case,
424 // we don't pretend to do anything fancy, we just split on spaces. 389 // we don't pretend to do anything fancy, we just split on spaces.
425 if (wrapper.empty()) 390 StringVector wrapper_argv;
426 return; 391 base::SplitString(wrapper, FILE_PATH_LITERAL(' '), &wrapper_argv);
427 StringVector wrapper_and_args; 392 // Prepend the wrapper and update the switches/arguments |begin_args_|.
428 #if defined(OS_WIN) 393 argv_.insert(argv_.begin(), wrapper_argv.begin(), wrapper_argv.end());
429 base::SplitString(wrapper, ' ', &wrapper_and_args); 394 begin_args_ += wrapper_argv.size();
430 program_ = wrapper_and_args[0];
431 command_line_string_ = wrapper + L" " + command_line_string_;
432 #elif defined(OS_POSIX)
433 base::SplitString(wrapper, ' ', &wrapper_and_args);
434 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end());
435 #endif
436 } 395 }
437 396
438 #if defined(OS_WIN) 397 #if defined(OS_WIN)
439 void CommandLine::ParseFromString(const std::wstring& command_line) { 398 void CommandLine::ParseFromString(const std::wstring& command_line) {
440 TrimWhitespace(command_line, TRIM_ALL, &command_line_string_); 399 std::wstring command_line_string;
441 400 TrimWhitespace(command_line, TRIM_ALL, &command_line_string);
442 if (command_line_string_.empty()) 401 if (command_line_string.empty())
443 return; 402 return;
444 403
445 int num_args = 0; 404 int num_args = 0;
446 wchar_t** args = NULL; 405 wchar_t** args = NULL;
406 args = ::CommandLineToArgvW(command_line_string.c_str(), &num_args);
447 407
448 args = CommandLineToArgvW(command_line_string_.c_str(), &num_args); 408 CHECK(args);
449 409 InitFromArgv(num_args, args);
450 // Populate program_ with the trimmed version of the first arg. 410 LocalFree(args);
451 TrimWhitespace(args[0], TRIM_ALL, &program_);
452
453 bool parse_switches = true;
454 for (int i = 1; i < num_args; ++i) {
455 std::wstring arg;
456 TrimWhitespace(args[i], TRIM_ALL, &arg);
457
458 if (!parse_switches) {
459 args_.push_back(arg);
460 continue;
461 }
462
463 if (arg == kSwitchTerminator) {
464 parse_switches = false;
465 continue;
466 }
467
468 std::string switch_string;
469 std::wstring switch_value;
470 if (IsSwitch(arg, &switch_string, &switch_value)) {
471 switches_[switch_string] = switch_value;
472 } else {
473 args_.push_back(arg);
474 }
475 }
476
477 if (args)
478 LocalFree(args);
479 } 411 }
480 #endif 412 #endif
481
482 CommandLine::CommandLine() {
483 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698