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

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 additional comments, additional refactoring. 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
39 #if defined(OS_WIN) 37 size_t GetSwitchPrefixLength(const CommandLine::StringType& string) {
40 // Lowercase a string for case-insensitivity of switches. 38 for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
41 // Is this desirable? It exists for backwards compatibility on Windows. 39 CommandLine::StringType prefix(kSwitchPrefixes[i]);
42 void Lowercase(std::string* arg) { 40 if (string.find(prefix) == 0)
43 transform(arg->begin(), arg->end(), arg->begin(), tolower); 41 return prefix.length();
42 }
43 return 0;
44 } 44 }
45 45
46 // Quote a string if necessary, such that CommandLineToArgvW() will always 46 // Fills in |switch_string| and |switch_value| if |string| is a switch.
47 // process it as a single argument. 47 // This will preserve the input switch prefix in the output |switch_string|.
48 std::wstring WindowsStyleQuote(const std::wstring& arg) { 48 bool IsSwitch(const CommandLine::StringType& string,
49 CommandLine::StringType* switch_string,
50 CommandLine::StringType* switch_value) {
51 switch_string->clear();
52 switch_value->clear();
53 if (GetSwitchPrefixLength(string) == 0)
54 return false;
55
56 const size_t equals_position = string.find(kSwitchValueSeparator);
57 *switch_string = string.substr(0, equals_position);
58 if(equals_position != CommandLine::StringType::npos)
59 *switch_value = string.substr(equals_position + 1);
60 return true;
61 }
62
63 // Append switches and arguments, keeping switches before arguments.
64 void AppendSwitchesAndArguments(CommandLine& command_line,
65 const CommandLine::StringVector& argv) {
66 bool parse_switches = true;
67 for (size_t i = 1; i < argv.size(); ++i) {
68 CommandLine::StringType arg = argv[i];
69 TrimWhitespace(arg, TRIM_ALL, &arg);
70
71 CommandLine::StringType switch_string;
72 CommandLine::StringType switch_value;
73 parse_switches &= arg != kSwitchTerminator;
74 if (parse_switches && IsSwitch(arg, &switch_string, &switch_value)) {
75 #if defined(OS_WIN)
76 command_line.AppendSwitchNative(WideToASCII(switch_string), switch_value);
77 #elif defined(OS_POSIX)
78 command_line.AppendSwitchNative(switch_string, switch_value);
79 #endif
80 } else {
81 command_line.AppendArgNative(arg);
82 }
83 }
84 }
85
86 #if defined(OS_WIN)
87 // Quote a string as necessary for CommandLineToArgvW compatiblity *on Windows*.
88 std::wstring QuoteForCommandLineToArgvW(const std::wstring& arg) {
49 // We follow the quoting rules of CommandLineToArgvW. 89 // We follow the quoting rules of CommandLineToArgvW.
50 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx 90 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
51 if (arg.find_first_of(L" \\\"") == std::wstring::npos) { 91 if (arg.find_first_of(L" \\\"") == std::wstring::npos) {
52 // No quoting necessary. 92 // No quoting necessary.
53 return arg; 93 return arg;
54 } 94 }
55 95
56 std::wstring out; 96 std::wstring out;
57 out.push_back(L'"'); 97 out.push_back(L'"');
58 for (size_t i = 0; i < arg.size(); ++i) { 98 for (size_t i = 0; i < arg.size(); ++i) {
(...skipping 22 matching lines...) Expand all
81 } else { 121 } else {
82 out.push_back(arg[i]); 122 out.push_back(arg[i]);
83 } 123 }
84 } 124 }
85 out.push_back('"'); 125 out.push_back('"');
86 126
87 return out; 127 return out;
88 } 128 }
89 #endif 129 #endif
90 130
91 // Returns true and fills in |switch_string| and |switch_value| if 131 } // namespace
92 // |parameter_string| represents a switch.
93 bool IsSwitch(const CommandLine::StringType& parameter_string,
94 std::string* switch_string,
95 CommandLine::StringType* switch_value) {
96 switch_string->clear();
97 switch_value->clear();
98 132
99 for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) { 133 CommandLine::CommandLine(NoProgram no_program)
100 CommandLine::StringType prefix(kSwitchPrefixes[i]); 134 : argv_(1),
101 if (parameter_string.find(prefix) != 0) 135 begin_args_(1) {
102 continue;
103
104 const size_t switch_start = prefix.length();
105 const size_t equals_position = parameter_string.find(
106 kSwitchValueSeparator, switch_start);
107 CommandLine::StringType switch_native;
108 if (equals_position == CommandLine::StringType::npos) {
109 switch_native = parameter_string.substr(switch_start);
110 } else {
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
122 return true;
123 }
124
125 return false;
126 } 136 }
127 137
128 } // namespace 138 CommandLine::CommandLine(const FilePath& program)
129 139 : argv_(1),
130 CommandLine::CommandLine(NoProgram no_program) { 140 begin_args_(1) {
131 #if defined(OS_POSIX) 141 SetProgram(program);
132 // Push an empty argument, because we always assume argv_[0] is a program.
133 argv_.push_back("");
134 #endif
135 } 142 }
136 143
137 CommandLine::CommandLine(const FilePath& program) { 144 CommandLine::CommandLine(int argc, const CommandLine::CharType* const* argv)
138 #if defined(OS_WIN) 145 : argv_(1),
139 if (!program.empty()) { 146 begin_args_(1) {
140 program_ = program.value();
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 }
148
149 #if defined(OS_POSIX)
150 CommandLine::CommandLine(int argc, const char* const* argv) {
151 InitFromArgv(argc, argv); 147 InitFromArgv(argc, argv);
152 } 148 }
153 149
154 CommandLine::CommandLine(const StringVector& argv) { 150 CommandLine::CommandLine(const StringVector& argv)
151 : argv_(1),
152 begin_args_(1) {
155 InitFromArgv(argv); 153 InitFromArgv(argv);
156 } 154 }
157 #endif // OS_POSIX
158 155
159 CommandLine::~CommandLine() { 156 CommandLine::~CommandLine() {
160 } 157 }
161 158
162 // static 159 // static
163 void CommandLine::Init(int argc, const char* const* argv) { 160 void CommandLine::Init(int argc, const char* const* argv) {
164 delete current_process_commandline_; 161 delete current_process_commandline_;
165 current_process_commandline_ = new CommandLine; 162 current_process_commandline_ = new CommandLine(NO_PROGRAM);
166 #if defined(OS_WIN) 163 #if defined(OS_WIN)
167 current_process_commandline_->ParseFromString(::GetCommandLineW()); 164 current_process_commandline_->ParseFromString(::GetCommandLineW());
168 #elif defined(OS_POSIX) 165 #elif defined(OS_POSIX)
169 current_process_commandline_->InitFromArgv(argc, argv); 166 current_process_commandline_->InitFromArgv(argc, argv);
170 #endif 167 #endif
171 } 168 }
172 169
173 // static 170 // static
174 void CommandLine::Reset() { 171 void CommandLine::Reset() {
175 DCHECK(current_process_commandline_); 172 DCHECK(current_process_commandline_);
176 delete current_process_commandline_; 173 delete current_process_commandline_;
177 current_process_commandline_ = NULL; 174 current_process_commandline_ = NULL;
178 } 175 }
179 176
180 // static 177 // static
181 CommandLine* CommandLine::ForCurrentProcess() { 178 CommandLine* CommandLine::ForCurrentProcess() {
182 DCHECK(current_process_commandline_); 179 DCHECK(current_process_commandline_);
183 return current_process_commandline_; 180 return current_process_commandline_;
184 } 181 }
185 182
186 #if defined(OS_WIN) 183 #if defined(OS_WIN)
187 // static 184 // static
188 CommandLine CommandLine::FromString(const std::wstring& command_line) { 185 CommandLine CommandLine::FromString(const std::wstring& command_line) {
189 CommandLine cmd; 186 CommandLine cmd(NO_PROGRAM);
190 cmd.ParseFromString(command_line); 187 cmd.ParseFromString(command_line);
191 return cmd; 188 return cmd;
192 } 189 }
193 #endif // OS_WIN 190 #endif
194 191
195 #if defined(OS_POSIX) 192 void CommandLine::InitFromArgv(int argc,
196 void CommandLine::InitFromArgv(int argc, const char* const* argv) { 193 const CommandLine::CharType* const* argv) {
194 StringVector new_argv;
197 for (int i = 0; i < argc; ++i) 195 for (int i = 0; i < argc; ++i)
198 argv_.push_back(argv[i]); 196 new_argv.push_back(argv[i]);
199 InitFromArgv(argv_); 197 InitFromArgv(new_argv);
200 } 198 }
201 199
202 void CommandLine::InitFromArgv(const StringVector& argv) { 200 void CommandLine::InitFromArgv(const StringVector& argv) {
203 argv_ = argv; 201 argv_ = StringVector(1);
202 begin_args_ = 1;
203 SetProgram(argv.empty() ? FilePath() : FilePath(argv[0]));
204 AppendSwitchesAndArguments(*this, argv);
205 }
206
207 CommandLine::StringType CommandLine::command_line_string() const {
208 StringType string(argv_[0]);
209 #if defined(OS_WIN)
210 string = QuoteForCommandLineToArgvW(string);
211 #endif
212 // Append switches and arguments.
204 bool parse_switches = true; 213 bool parse_switches = true;
205 for (size_t i = 1; i < argv_.size(); ++i) { 214 for (size_t i = 1; i < argv_.size(); ++i) {
206 const std::string& arg = argv_[i]; 215 CommandLine::StringType arg = argv_[i];
207 216 CommandLine::StringType switch_string;
208 if (!parse_switches) { 217 CommandLine::StringType switch_value;
209 args_.push_back(arg); 218 parse_switches &= arg != kSwitchTerminator;
210 continue; 219 string.append(StringType(FILE_PATH_LITERAL(" ")));
220 if (parse_switches && IsSwitch(arg, &switch_string, &switch_value)) {
221 string.append(switch_string);
222 if (!switch_value.empty()) {
223 #if defined(OS_WIN)
224 switch_value = QuoteForCommandLineToArgvW(switch_value);
225 #endif
226 string.append(kSwitchValueSeparator + switch_value);
227 }
211 } 228 }
212 229 else {
213 if (arg == kSwitchTerminator) { 230 #if defined(OS_WIN)
214 parse_switches = false; 231 arg = QuoteForCommandLineToArgvW(arg);
215 continue; 232 #endif
216 } 233 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 } 234 }
225 } 235 }
226 } 236 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 } 237 }
236 238
237 FilePath CommandLine::GetProgram() const { 239 FilePath CommandLine::GetProgram() const {
238 #if defined(OS_WIN) 240 return FilePath(program_string_);
239 return FilePath(program_); 241 }
240 #else 242
241 DCHECK_GT(argv_.size(), 0U); 243 void CommandLine::SetProgram(const FilePath& program) {
242 return FilePath(argv_[0]); 244 program_string_ = program.value();
243 #endif 245 TrimWhitespace(program_string_, TRIM_ALL, &program_string_);
246 argv_[0] = program_string_;
244 } 247 }
245 248
246 bool CommandLine::HasSwitch(const std::string& switch_string) const { 249 bool CommandLine::HasSwitch(const std::string& switch_string) const {
247 std::string lowercased_switch(switch_string);
248 #if defined(OS_WIN) 250 #if defined(OS_WIN)
249 Lowercase(&lowercased_switch); 251 return switches_.find(StringToLowerASCII(switch_string)) != switches_.end();
252 #elif defined(OS_POSIX)
253 return switches_.find(switch_string) != switches_.end();
250 #endif 254 #endif
251 return switches_.find(lowercased_switch) != switches_.end();
252 } 255 }
253 256
254 std::string CommandLine::GetSwitchValueASCII( 257 std::string CommandLine::GetSwitchValueASCII(
255 const std::string& switch_string) const { 258 const std::string& switch_string) const {
256 CommandLine::StringType value = GetSwitchValueNative(switch_string); 259 StringType value = GetSwitchValueNative(switch_string);
257 if (!IsStringASCII(value)) { 260 if (!IsStringASCII(value)) {
258 LOG(WARNING) << "Value of --" << switch_string << " must be ASCII."; 261 LOG(WARNING) << "Value of switch (" << switch_string << ") must be ASCII.";
259 return ""; 262 return "";
260 } 263 }
261 #if defined(OS_WIN) 264 #if defined(OS_WIN)
262 return WideToASCII(value); 265 return WideToASCII(value);
263 #else 266 #else
264 return value; 267 return value;
265 #endif 268 #endif
266 } 269 }
267 270
268 FilePath CommandLine::GetSwitchValuePath( 271 FilePath CommandLine::GetSwitchValuePath(
269 const std::string& switch_string) const { 272 const std::string& switch_string) const {
270 return FilePath(GetSwitchValueNative(switch_string)); 273 return FilePath(GetSwitchValueNative(switch_string));
271 } 274 }
272 275
273 CommandLine::StringType CommandLine::GetSwitchValueNative( 276 CommandLine::StringType CommandLine::GetSwitchValueNative(
274 const std::string& switch_string) const { 277 const std::string& switch_string) const {
275 std::string lowercased_switch(switch_string); 278 SwitchMap::const_iterator result = switches_.end();
276 #if defined(OS_WIN) 279 #if defined(OS_WIN)
277 Lowercase(&lowercased_switch); 280 result = switches_.find(StringToLowerASCII(switch_string));
281 #elif defined(OS_POSIX)
282 result = switches_.find(switch_string);
278 #endif 283 #endif
279 284 return result == switches_.end() ? StringType() : result->second;
280 SwitchMap::const_iterator result = switches_.find(lowercased_switch);
281
282 if (result == switches_.end()) {
283 return CommandLine::StringType();
284 } else {
285 return result->second;
286 }
287 } 285 }
288 286
289 size_t CommandLine::GetSwitchCount() const { 287 size_t CommandLine::GetSwitchCount() const {
290 return switches_.size(); 288 return switches_.size();
291 } 289 }
292 290
293 void CommandLine::AppendSwitch(const std::string& switch_string) { 291 void CommandLine::AppendSwitch(const std::string& switch_string) {
294 #if defined(OS_WIN) 292 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 } 293 }
303 294
304 void CommandLine::AppendSwitchPath(const std::string& switch_string, 295 void CommandLine::AppendSwitchPath(const std::string& switch_string,
305 const FilePath& path) { 296 const FilePath& path) {
306 AppendSwitchNative(switch_string, path.value()); 297 AppendSwitchNative(switch_string, path.value());
307 } 298 }
308 299
309 void CommandLine::AppendSwitchNative(const std::string& switch_string, 300 void CommandLine::AppendSwitchNative(const std::string& switch_string,
310 const CommandLine::StringType& value) { 301 const CommandLine::StringType& value) {
311 #if defined(OS_WIN) 302 #if defined(OS_WIN)
312 StringType combined_switch_string = 303 std::string switch_key(StringToLowerASCII(switch_string));
313 kSwitchPrefixes[0] + ASCIIToWide(switch_string); 304 StringType combined_switch_string(ASCIIToWide(switch_key));
314 if (!value.empty())
315 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value);
316
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) 305 #elif defined(OS_POSIX)
322 StringType combined_switch_string = kSwitchPrefixes[0] + switch_string; 306 std::string switch_key(switch_string);
307 StringType combined_switch_string(switch_string);
308 #endif
309 size_t prefix_length = GetSwitchPrefixLength(combined_switch_string);
310 switches_[switch_key.substr(prefix_length)] = value;
311 // Preserve existing switch prefixes in |argv_|; only append one if necessary.
312 if (prefix_length == 0)
313 combined_switch_string = kSwitchPrefixes[0] + combined_switch_string;
323 if (!value.empty()) 314 if (!value.empty())
324 combined_switch_string += kSwitchValueSeparator + value; 315 combined_switch_string += kSwitchValueSeparator + value;
325 argv_.push_back(combined_switch_string); 316 // Append the switch and update the switches/arguments divider |begin_args_|.
326 switches_[switch_string] = value; 317 argv_.insert(argv_.begin() + begin_args_++, combined_switch_string);
327 #endif
328 } 318 }
329 319
330 void CommandLine::AppendSwitchASCII(const std::string& switch_string, 320 void CommandLine::AppendSwitchASCII(const std::string& switch_string,
331 const std::string& value_string) { 321 const std::string& value_string) {
332 #if defined(OS_WIN) 322 #if defined(OS_WIN)
333 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); 323 AppendSwitchNative(switch_string, ASCIIToWide(value_string));
334 #elif defined(OS_POSIX) 324 #elif defined(OS_POSIX)
335 AppendSwitchNative(switch_string, value_string); 325 AppendSwitchNative(switch_string, value_string);
336 #endif 326 #endif
337 } 327 }
338 328
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 }
344
345 void CommandLine::CopySwitchesFrom(const CommandLine& source, 329 void CommandLine::CopySwitchesFrom(const CommandLine& source,
346 const char* const switches[], 330 const char* const switches[],
347 size_t count) { 331 size_t count) {
348 for (size_t i = 0; i < count; ++i) { 332 for (size_t i = 0; i < count; ++i)
349 if (source.HasSwitch(switches[i])) { 333 if (source.HasSwitch(switches[i]))
350 StringType value = source.GetSwitchValueNative(switches[i]); 334 AppendSwitchNative(switches[i], source.GetSwitchValueNative(switches[i]));
351 AppendSwitchNative(switches[i], value); 335 }
352 } 336
353 } 337 CommandLine::StringVector CommandLine::args() const {
338 // Gather all arguments after the last switch (may include kSwitchTerminator).
339 StringVector args(argv_.begin() + begin_args_, argv_.end());
340 // Erase only the first kSwitchTerminator (maybe "--" is a legitimate page?)
341 StringVector::iterator switch_terminator =
342 std::find(args.begin(), args.end(), kSwitchTerminator);
343 if (switch_terminator != args.end())
344 args.erase(switch_terminator);
345 return args;
354 } 346 }
355 347
356 void CommandLine::AppendArg(const std::string& value) { 348 void CommandLine::AppendArg(const std::string& value) {
357 #if defined(OS_WIN) 349 #if defined(OS_WIN)
358 DCHECK(IsStringUTF8(value)); 350 DCHECK(IsStringUTF8(value));
359 AppendArgNative(UTF8ToWide(value)); 351 AppendArgNative(UTF8ToWide(value));
360 #elif defined(OS_POSIX) 352 #elif defined(OS_POSIX)
361 AppendArgNative(value); 353 AppendArgNative(value);
362 #endif 354 #endif
363 } 355 }
364 356
365 void CommandLine::AppendArgPath(const FilePath& path) { 357 void CommandLine::AppendArgPath(const FilePath& path) {
366 AppendArgNative(path.value()); 358 AppendArgNative(path.value());
367 } 359 }
368 360
369 void CommandLine::AppendArgNative(const CommandLine::StringType& value) { 361 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); 362 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 } 363 }
390 364
391 void CommandLine::AppendArguments(const CommandLine& other, 365 void CommandLine::AppendArguments(const CommandLine& other,
392 bool include_program) { 366 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) 367 if (include_program)
397 program_ = other.program_; 368 SetProgram(other.GetProgram());
398 369 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 } 370 }
421 371
422 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) { 372 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) {
373 if (wrapper.empty())
374 return;
423 // The wrapper may have embedded arguments (like "gdb --args"). In this case, 375 // 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. 376 // we don't pretend to do anything fancy, we just split on spaces.
425 if (wrapper.empty()) 377 StringVector wrapper_argv;
426 return; 378 base::SplitString(wrapper, FILE_PATH_LITERAL(' '), &wrapper_argv);
427 StringVector wrapper_and_args; 379 // Prepend the wrapper and update the switches/arguments |begin_args_|.
428 #if defined(OS_WIN) 380 argv_.insert(argv_.begin(), wrapper_argv.begin(), wrapper_argv.end());
429 base::SplitString(wrapper, ' ', &wrapper_and_args); 381 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 } 382 }
437 383
438 #if defined(OS_WIN) 384 #if defined(OS_WIN)
439 void CommandLine::ParseFromString(const std::wstring& command_line) { 385 void CommandLine::ParseFromString(const std::wstring& command_line) {
440 TrimWhitespace(command_line, TRIM_ALL, &command_line_string_); 386 std::wstring command_line_string;
441 387 TrimWhitespace(command_line, TRIM_ALL, &command_line_string);
442 if (command_line_string_.empty()) 388 if (command_line_string.empty())
443 return; 389 return;
444 390
445 int num_args = 0; 391 int num_args = 0;
446 wchar_t** args = NULL; 392 wchar_t** args = NULL;
393 args = ::CommandLineToArgvW(command_line_string.c_str(), &num_args);
447 394
448 args = CommandLineToArgvW(command_line_string_.c_str(), &num_args); 395 CHECK(args);
449 396 InitFromArgv(num_args, args);
450 // Populate program_ with the trimmed version of the first arg. 397 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 } 398 }
480 #endif 399 #endif
481
482 CommandLine::CommandLine() {
483 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698