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

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

Powered by Google App Engine
This is Rietveld 408576698