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

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: Nix program_path_, add and update 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
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)
grt (UTC plus 2) 2011/05/13 19:16:14 style: add a space after "if"
msw 2011/05/13 20:28:02 Done.
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;
grt (UTC plus 2) 2011/05/13 19:16:14 readability: parens around arg != kSwitchTerminato
msw 2011/05/13 20:28:02 Done.
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)
239 return FilePath(program_);
240 #else
241 DCHECK_GT(argv_.size(), 0U);
242 return FilePath(argv_[0]); 240 return FilePath(argv_[0]);
243 #endif 241 }
242
243 void CommandLine::SetProgram(const FilePath& program) {
244 TrimWhitespace(program.value(), TRIM_ALL, &argv_[0]);
244 } 245 }
245 246
246 bool CommandLine::HasSwitch(const std::string& switch_string) const { 247 bool CommandLine::HasSwitch(const std::string& switch_string) const {
247 std::string lowercased_switch(switch_string);
248 #if defined(OS_WIN) 248 #if defined(OS_WIN)
grt (UTC plus 2) 2011/05/13 19:16:14 It seems like some of these conditional compilatio
msw 2011/05/13 20:28:02 Done, reincarnated Lowercase as LowerASCIIOnWindow
249 Lowercase(&lowercased_switch); 249 return switches_.find(StringToLowerASCII(switch_string)) != switches_.end();
250 #elif defined(OS_POSIX)
251 return switches_.find(switch_string) != switches_.end();
250 #endif 252 #endif
251 return switches_.find(lowercased_switch) != switches_.end();
252 } 253 }
253 254
254 std::string CommandLine::GetSwitchValueASCII( 255 std::string CommandLine::GetSwitchValueASCII(
255 const std::string& switch_string) const { 256 const std::string& switch_string) const {
256 CommandLine::StringType value = GetSwitchValueNative(switch_string); 257 StringType value = GetSwitchValueNative(switch_string);
257 if (!IsStringASCII(value)) { 258 if (!IsStringASCII(value)) {
258 LOG(WARNING) << "Value of --" << switch_string << " must be ASCII."; 259 LOG(WARNING) << "Value of switch (" << switch_string << ") must be ASCII.";
259 return ""; 260 return "";
260 } 261 }
261 #if defined(OS_WIN) 262 #if defined(OS_WIN)
262 return WideToASCII(value); 263 return WideToASCII(value);
263 #else 264 #else
264 return value; 265 return value;
265 #endif 266 #endif
266 } 267 }
267 268
268 FilePath CommandLine::GetSwitchValuePath( 269 FilePath CommandLine::GetSwitchValuePath(
269 const std::string& switch_string) const { 270 const std::string& switch_string) const {
270 return FilePath(GetSwitchValueNative(switch_string)); 271 return FilePath(GetSwitchValueNative(switch_string));
271 } 272 }
272 273
273 CommandLine::StringType CommandLine::GetSwitchValueNative( 274 CommandLine::StringType CommandLine::GetSwitchValueNative(
274 const std::string& switch_string) const { 275 const std::string& switch_string) const {
275 std::string lowercased_switch(switch_string); 276 SwitchMap::const_iterator result = switches_.end();
276 #if defined(OS_WIN) 277 #if defined(OS_WIN)
277 Lowercase(&lowercased_switch); 278 result = switches_.find(StringToLowerASCII(switch_string));
279 #elif defined(OS_POSIX)
280 result = switches_.find(switch_string);
278 #endif 281 #endif
279 282 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 } 283 }
288 284
289 size_t CommandLine::GetSwitchCount() const { 285 size_t CommandLine::GetSwitchCount() const {
290 return switches_.size(); 286 return switches_.size();
291 } 287 }
292 288
293 void CommandLine::AppendSwitch(const std::string& switch_string) { 289 void CommandLine::AppendSwitch(const std::string& switch_string) {
294 #if defined(OS_WIN) 290 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 } 291 }
303 292
304 void CommandLine::AppendSwitchPath(const std::string& switch_string, 293 void CommandLine::AppendSwitchPath(const std::string& switch_string,
305 const FilePath& path) { 294 const FilePath& path) {
306 AppendSwitchNative(switch_string, path.value()); 295 AppendSwitchNative(switch_string, path.value());
307 } 296 }
308 297
309 void CommandLine::AppendSwitchNative(const std::string& switch_string, 298 void CommandLine::AppendSwitchNative(const std::string& switch_string,
310 const CommandLine::StringType& value) { 299 const CommandLine::StringType& value) {
311 #if defined(OS_WIN) 300 #if defined(OS_WIN)
312 StringType combined_switch_string = 301 std::string switch_key(StringToLowerASCII(switch_string));
313 kSwitchPrefixes[0] + ASCIIToWide(switch_string); 302 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) 303 #elif defined(OS_POSIX)
322 StringType combined_switch_string = kSwitchPrefixes[0] + switch_string; 304 std::string switch_key(switch_string);
305 StringType combined_switch_string(switch_string);
306 #endif
307 size_t prefix_length = GetSwitchPrefixLength(combined_switch_string);
308 switches_[switch_key.substr(prefix_length)] = value;
309 // Preserve existing switch prefixes in |argv_|; only append one if necessary.
310 if (prefix_length == 0)
311 combined_switch_string = kSwitchPrefixes[0] + combined_switch_string;
323 if (!value.empty()) 312 if (!value.empty())
324 combined_switch_string += kSwitchValueSeparator + value; 313 combined_switch_string += kSwitchValueSeparator + value;
325 argv_.push_back(combined_switch_string); 314 // Append the switch and update the switches/arguments divider |begin_args_|.
326 switches_[switch_string] = value; 315 argv_.insert(argv_.begin() + begin_args_++, combined_switch_string);
327 #endif
328 } 316 }
329 317
330 void CommandLine::AppendSwitchASCII(const std::string& switch_string, 318 void CommandLine::AppendSwitchASCII(const std::string& switch_string,
331 const std::string& value_string) { 319 const std::string& value_string) {
332 #if defined(OS_WIN) 320 #if defined(OS_WIN)
333 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); 321 AppendSwitchNative(switch_string, ASCIIToWide(value_string));
334 #elif defined(OS_POSIX) 322 #elif defined(OS_POSIX)
335 AppendSwitchNative(switch_string, value_string); 323 AppendSwitchNative(switch_string, value_string);
336 #endif 324 #endif
337 } 325 }
338 326
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, 327 void CommandLine::CopySwitchesFrom(const CommandLine& source,
346 const char* const switches[], 328 const char* const switches[],
347 size_t count) { 329 size_t count) {
348 for (size_t i = 0; i < count; ++i) { 330 for (size_t i = 0; i < count; ++i)
grt (UTC plus 2) 2011/05/13 19:16:14 need braces here
msw 2011/05/13 20:28:02 Done.
349 if (source.HasSwitch(switches[i])) { 331 if (source.HasSwitch(switches[i]))
350 StringType value = source.GetSwitchValueNative(switches[i]); 332 AppendSwitchNative(switches[i], source.GetSwitchValueNative(switches[i]));
351 AppendSwitchNative(switches[i], value); 333 }
352 } 334
353 } 335 CommandLine::StringVector CommandLine::args() const {
336 // Gather all arguments after the last switch (may include kSwitchTerminator).
337 StringVector args(argv_.begin() + begin_args_, argv_.end());
338 // Erase only the first kSwitchTerminator (maybe "--" is a legitimate page?)
339 StringVector::iterator switch_terminator =
340 std::find(args.begin(), args.end(), kSwitchTerminator);
341 if (switch_terminator != args.end())
342 args.erase(switch_terminator);
343 return args;
354 } 344 }
355 345
356 void CommandLine::AppendArg(const std::string& value) { 346 void CommandLine::AppendArg(const std::string& value) {
357 #if defined(OS_WIN) 347 #if defined(OS_WIN)
358 DCHECK(IsStringUTF8(value)); 348 DCHECK(IsStringUTF8(value));
359 AppendArgNative(UTF8ToWide(value)); 349 AppendArgNative(UTF8ToWide(value));
360 #elif defined(OS_POSIX) 350 #elif defined(OS_POSIX)
361 AppendArgNative(value); 351 AppendArgNative(value);
362 #endif 352 #endif
363 } 353 }
364 354
365 void CommandLine::AppendArgPath(const FilePath& path) { 355 void CommandLine::AppendArgPath(const FilePath& path) {
366 AppendArgNative(path.value()); 356 AppendArgNative(path.value());
367 } 357 }
368 358
369 void CommandLine::AppendArgNative(const CommandLine::StringType& value) { 359 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); 360 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 } 361 }
390 362
391 void CommandLine::AppendArguments(const CommandLine& other, 363 void CommandLine::AppendArguments(const CommandLine& other,
392 bool include_program) { 364 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) 365 if (include_program)
397 program_ = other.program_; 366 SetProgram(other.GetProgram());
398 367 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 } 368 }
421 369
422 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) { 370 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) {
371 if (wrapper.empty())
372 return;
423 // The wrapper may have embedded arguments (like "gdb --args"). In this case, 373 // 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. 374 // we don't pretend to do anything fancy, we just split on spaces.
425 if (wrapper.empty()) 375 StringVector wrapper_argv;
426 return; 376 base::SplitString(wrapper, FILE_PATH_LITERAL(' '), &wrapper_argv);
427 StringVector wrapper_and_args; 377 // Prepend the wrapper and update the switches/arguments |begin_args_|.
428 #if defined(OS_WIN) 378 argv_.insert(argv_.begin(), wrapper_argv.begin(), wrapper_argv.end());
429 base::SplitString(wrapper, ' ', &wrapper_and_args); 379 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 } 380 }
437 381
438 #if defined(OS_WIN) 382 #if defined(OS_WIN)
439 void CommandLine::ParseFromString(const std::wstring& command_line) { 383 void CommandLine::ParseFromString(const std::wstring& command_line) {
440 TrimWhitespace(command_line, TRIM_ALL, &command_line_string_); 384 std::wstring command_line_string;
441 385 TrimWhitespace(command_line, TRIM_ALL, &command_line_string);
442 if (command_line_string_.empty()) 386 if (command_line_string.empty())
443 return; 387 return;
444 388
445 int num_args = 0; 389 int num_args = 0;
446 wchar_t** args = NULL; 390 wchar_t** args = NULL;
391 args = ::CommandLineToArgvW(command_line_string.c_str(), &num_args);
447 392
448 args = CommandLineToArgvW(command_line_string_.c_str(), &num_args); 393 CHECK(args);
grt (UTC plus 2) 2011/05/13 19:16:14 Please use the following (or something similar) so
msw 2011/05/13 20:28:02 Done.
449 394 InitFromArgv(num_args, args);
450 // Populate program_ with the trimmed version of the first arg. 395 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 } 396 }
480 #endif 397 #endif
481
482 CommandLine::CommandLine() {
483 }
OLDNEW
« base/command_line.h ('K') | « base/command_line.h ('k') | base/command_line_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698