OLD | NEW |
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 | 8 |
9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/singleton.h" | 12 #include "base/singleton.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/sys_string_conversions.h" | 15 #include "base/sys_string_conversions.h" |
16 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
17 #include "build/build_config.h" | 17 #include "build/build_config.h" |
18 | 18 |
19 #if defined(OS_WIN) | 19 #if defined(OS_WIN) |
20 #include <windows.h> | 20 #include <windows.h> |
21 #include <shellapi.h> | 21 #include <shellapi.h> |
22 #elif defined(OS_POSIX) | 22 #elif defined(OS_POSIX) |
23 #include <limits.h> | 23 #include <limits.h> |
24 #include <stdlib.h> | 24 #include <stdlib.h> |
25 #include <unistd.h> | 25 #include <unistd.h> |
26 #endif | 26 #endif |
27 | 27 |
28 CommandLine* CommandLine::current_process_commandline_ = NULL; | 28 CommandLine* CommandLine::current_process_commandline_ = NULL; |
29 | 29 |
30 // Since we use a lazy match, make sure that longer versions (like L"--") | 30 namespace { |
31 // are listed before shorter versions (like L"-") of similar prefixes. | 31 typedef CommandLine::StringType::value_type CharType; |
| 32 |
| 33 const CharType kSwitchTerminator[] = FILE_PATH_LITERAL("--"); |
| 34 const CharType kSwitchValueSeparator[] = FILE_PATH_LITERAL("="); |
| 35 // Since we use a lazy match, make sure that longer versions (like "--") are |
| 36 // listed before shorter versions (like "-") of similar prefixes. |
32 #if defined(OS_WIN) | 37 #if defined(OS_WIN) |
33 const wchar_t* const kSwitchPrefixes[] = {L"--", L"-", L"/"}; | 38 const CharType* const kSwitchPrefixes[] = {L"--", L"-", L"/"}; |
34 const wchar_t kSwitchTerminator[] = L"--"; | |
35 const wchar_t kSwitchValueSeparator[] = L"="; | |
36 #elif defined(OS_POSIX) | 39 #elif defined(OS_POSIX) |
37 // Unixes don't use slash as a switch. | 40 // Unixes don't use slash as a switch. |
38 const char* const kSwitchPrefixes[] = {"--", "-"}; | 41 const CharType* const kSwitchPrefixes[] = {"--", "-"}; |
39 const char kSwitchTerminator[] = "--"; | |
40 const char kSwitchValueSeparator[] = "="; | |
41 #endif | 42 #endif |
42 | 43 |
43 #if defined(OS_WIN) | 44 #if defined(OS_WIN) |
44 namespace { | 45 // Lowercase a string for case-insensitivity of switches. |
45 // Lowercase a string. This is used to lowercase switch names. | 46 // Is this desirable? It exists for backwards compatibility on Windows. |
46 // Is this what we really want? It seems crazy to me. I've left it in | 47 void Lowercase(std::string* arg) { |
47 // for backwards compatibility on Windows. | 48 transform(arg->begin(), arg->end(), arg->begin(), tolower); |
48 void Lowercase(std::string* parameter) { | |
49 transform(parameter->begin(), parameter->end(), parameter->begin(), | |
50 tolower); | |
51 } | 49 } |
52 | 50 |
53 // Quote a string if necessary, such that CommandLineToArgvW() will | 51 // Quote a string if necessary, such that CommandLineToArgvW() will always |
54 // always process it as a single argument. | 52 // process it as a single argument. |
55 std::wstring WindowsStyleQuote(const std::wstring& arg) { | 53 std::wstring WindowsStyleQuote(const std::wstring& arg) { |
56 // We follow the quoting rules of CommandLineToArgvW. | 54 // We follow the quoting rules of CommandLineToArgvW. |
57 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx | 55 // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx |
58 if (arg.find_first_of(L" \\\"") == std::wstring::npos) { | 56 if (arg.find_first_of(L" \\\"") == std::wstring::npos) { |
59 // No quoting necessary. | 57 // No quoting necessary. |
60 return arg; | 58 return arg; |
61 } | 59 } |
62 | 60 |
63 std::wstring out; | 61 std::wstring out; |
64 out.push_back(L'"'); | 62 out.push_back(L'"'); |
(...skipping 21 matching lines...) Expand all Loading... |
86 out.push_back('\\'); | 84 out.push_back('\\'); |
87 out.push_back('"'); | 85 out.push_back('"'); |
88 } else { | 86 } else { |
89 out.push_back(arg[i]); | 87 out.push_back(arg[i]); |
90 } | 88 } |
91 } | 89 } |
92 out.push_back('"'); | 90 out.push_back('"'); |
93 | 91 |
94 return out; | 92 return out; |
95 } | 93 } |
96 } // namespace | |
97 #endif | 94 #endif |
98 | 95 |
99 CommandLine::~CommandLine() { | 96 // Returns true and fills in |switch_string| and |switch_value| if |
| 97 // |parameter_string| represents a switch. |
| 98 bool IsSwitch(const CommandLine::StringType& parameter_string, |
| 99 std::string* switch_string, |
| 100 CommandLine::StringType* switch_value) { |
| 101 switch_string->clear(); |
| 102 switch_value->clear(); |
| 103 |
| 104 for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) { |
| 105 CommandLine::StringType prefix(kSwitchPrefixes[i]); |
| 106 if (parameter_string.find(prefix) != 0) |
| 107 continue; |
| 108 |
| 109 const size_t switch_start = prefix.length(); |
| 110 const size_t equals_position = parameter_string.find( |
| 111 kSwitchValueSeparator, switch_start); |
| 112 CommandLine::StringType switch_native; |
| 113 if (equals_position == CommandLine::StringType::npos) { |
| 114 switch_native = parameter_string.substr(switch_start); |
| 115 } else { |
| 116 switch_native = parameter_string.substr( |
| 117 switch_start, equals_position - switch_start); |
| 118 *switch_value = parameter_string.substr(equals_position + 1); |
| 119 } |
| 120 #if defined(OS_WIN) |
| 121 *switch_string = WideToASCII(switch_native); |
| 122 Lowercase(switch_string); |
| 123 #else |
| 124 *switch_string = switch_native; |
| 125 #endif |
| 126 |
| 127 return true; |
| 128 } |
| 129 |
| 130 return false; |
| 131 } |
| 132 |
| 133 } // namespace |
| 134 |
| 135 CommandLine::CommandLine(NoProgram no_program) { |
| 136 #if defined(OS_POSIX) |
| 137 // Push an empty argument, because we always assume argv_[0] is a program. |
| 138 argv_.push_back(""); |
| 139 #endif |
| 140 } |
| 141 |
| 142 CommandLine::CommandLine(const FilePath& program) { |
| 143 #if defined(OS_WIN) |
| 144 if (!program.empty()) { |
| 145 program_ = program.value(); |
| 146 // TODO(evanm): proper quoting here. |
| 147 command_line_string_ = L'"' + program.value() + L'"'; |
| 148 } |
| 149 #elif defined(OS_POSIX) |
| 150 argv_.push_back(program.value()); |
| 151 #endif |
| 152 } |
| 153 |
| 154 #if defined(OS_POSIX) |
| 155 CommandLine::CommandLine(int argc, const char* const* argv) { |
| 156 InitFromArgv(argc, argv); |
| 157 } |
| 158 |
| 159 CommandLine::CommandLine(const StringVector& argv) { |
| 160 InitFromArgv(argv); |
| 161 } |
| 162 #endif // OS_POSIX |
| 163 |
| 164 // static |
| 165 void CommandLine::Init(int argc, const char* const* argv) { |
| 166 delete current_process_commandline_; |
| 167 current_process_commandline_ = new CommandLine; |
| 168 #if defined(OS_WIN) |
| 169 current_process_commandline_->ParseFromString(::GetCommandLineW()); |
| 170 #elif defined(OS_POSIX) |
| 171 current_process_commandline_->InitFromArgv(argc, argv); |
| 172 #endif |
| 173 } |
| 174 |
| 175 // static |
| 176 void CommandLine::Reset() { |
| 177 DCHECK(current_process_commandline_); |
| 178 delete current_process_commandline_; |
| 179 current_process_commandline_ = NULL; |
| 180 } |
| 181 |
| 182 // static |
| 183 CommandLine* CommandLine::ForCurrentProcess() { |
| 184 DCHECK(current_process_commandline_); |
| 185 return current_process_commandline_; |
100 } | 186 } |
101 | 187 |
102 #if defined(OS_WIN) | 188 #if defined(OS_WIN) |
103 CommandLine::CommandLine(NoProgram no_program) { | |
104 } | |
105 | |
106 void CommandLine::ParseFromString(const std::wstring& command_line) { | |
107 TrimWhitespace(command_line, TRIM_ALL, &command_line_string_); | |
108 | |
109 if (command_line_string_.empty()) | |
110 return; | |
111 | |
112 int num_args = 0; | |
113 wchar_t** args = NULL; | |
114 | |
115 args = CommandLineToArgvW(command_line_string_.c_str(), &num_args); | |
116 | |
117 // Populate program_ with the trimmed version of the first arg. | |
118 TrimWhitespace(args[0], TRIM_ALL, &program_); | |
119 | |
120 bool parse_switches = true; | |
121 for (int i = 1; i < num_args; ++i) { | |
122 std::wstring arg; | |
123 TrimWhitespace(args[i], TRIM_ALL, &arg); | |
124 | |
125 if (!parse_switches) { | |
126 args_.push_back(arg); | |
127 continue; | |
128 } | |
129 | |
130 if (arg == kSwitchTerminator) { | |
131 parse_switches = false; | |
132 continue; | |
133 } | |
134 | |
135 std::string switch_string; | |
136 std::wstring switch_value; | |
137 if (IsSwitch(arg, &switch_string, &switch_value)) { | |
138 switches_[switch_string] = switch_value; | |
139 } else { | |
140 args_.push_back(arg); | |
141 } | |
142 } | |
143 | |
144 if (args) | |
145 LocalFree(args); | |
146 } | |
147 | |
148 // static | 189 // static |
149 CommandLine CommandLine::FromString(const std::wstring& command_line) { | 190 CommandLine CommandLine::FromString(const std::wstring& command_line) { |
150 CommandLine cmd; | 191 CommandLine cmd; |
151 cmd.ParseFromString(command_line); | 192 cmd.ParseFromString(command_line); |
152 return cmd; | 193 return cmd; |
153 } | 194 } |
| 195 #endif // OS_WIN |
154 | 196 |
155 CommandLine::CommandLine(const FilePath& program) { | 197 #if defined(OS_POSIX) |
156 if (!program.empty()) { | |
157 program_ = program.value(); | |
158 // TODO(evanm): proper quoting here. | |
159 command_line_string_ = L'"' + program.value() + L'"'; | |
160 } | |
161 } | |
162 | |
163 #elif defined(OS_POSIX) | |
164 CommandLine::CommandLine(NoProgram no_program) { | |
165 // Push an empty argument, because we always assume argv_[0] is a program. | |
166 argv_.push_back(""); | |
167 } | |
168 | |
169 CommandLine::CommandLine(int argc, const char* const* argv) { | |
170 InitFromArgv(argc, argv); | |
171 } | |
172 | |
173 CommandLine::CommandLine(const std::vector<std::string>& argv) { | |
174 InitFromArgv(argv); | |
175 } | |
176 | |
177 void CommandLine::InitFromArgv(int argc, const char* const* argv) { | 198 void CommandLine::InitFromArgv(int argc, const char* const* argv) { |
178 for (int i = 0; i < argc; ++i) | 199 for (int i = 0; i < argc; ++i) |
179 argv_.push_back(argv[i]); | 200 argv_.push_back(argv[i]); |
180 InitFromArgv(argv_); | 201 InitFromArgv(argv_); |
181 } | 202 } |
182 | 203 |
183 void CommandLine::InitFromArgv(const std::vector<std::string>& argv) { | 204 void CommandLine::InitFromArgv(const StringVector& argv) { |
184 argv_ = argv; | 205 argv_ = argv; |
185 bool parse_switches = true; | 206 bool parse_switches = true; |
186 for (size_t i = 1; i < argv_.size(); ++i) { | 207 for (size_t i = 1; i < argv_.size(); ++i) { |
187 const std::string& arg = argv_[i]; | 208 const std::string& arg = argv_[i]; |
188 | 209 |
189 if (!parse_switches) { | 210 if (!parse_switches) { |
190 args_.push_back(arg); | 211 args_.push_back(arg); |
191 continue; | 212 continue; |
192 } | 213 } |
193 | 214 |
194 if (arg == kSwitchTerminator) { | 215 if (arg == kSwitchTerminator) { |
195 parse_switches = false; | 216 parse_switches = false; |
196 continue; | 217 continue; |
197 } | 218 } |
198 | 219 |
199 std::string switch_string; | 220 std::string switch_string; |
200 std::string switch_value; | 221 StringType switch_value; |
201 if (IsSwitch(arg, &switch_string, &switch_value)) { | 222 if (IsSwitch(arg, &switch_string, &switch_value)) { |
202 switches_[switch_string] = switch_value; | 223 switches_[switch_string] = switch_value; |
203 } else { | 224 } else { |
204 args_.push_back(arg); | 225 args_.push_back(arg); |
205 } | 226 } |
206 } | 227 } |
207 } | 228 } |
| 229 #endif // OS_POSIX |
208 | 230 |
209 CommandLine::CommandLine(const FilePath& program) { | 231 CommandLine::StringType CommandLine::command_line_string() const { |
210 argv_.push_back(program.value()); | |
211 } | |
212 | |
213 #endif | |
214 | |
215 // static | |
216 bool CommandLine::IsSwitch(const StringType& parameter_string, | |
217 std::string* switch_string, | |
218 StringType* switch_value) { | |
219 switch_string->clear(); | |
220 switch_value->clear(); | |
221 | |
222 for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) { | |
223 StringType prefix(kSwitchPrefixes[i]); | |
224 if (parameter_string.find(prefix) != 0) | |
225 continue; | |
226 | |
227 const size_t switch_start = prefix.length(); | |
228 const size_t equals_position = parameter_string.find( | |
229 kSwitchValueSeparator, switch_start); | |
230 StringType switch_native; | |
231 if (equals_position == StringType::npos) { | |
232 switch_native = parameter_string.substr(switch_start); | |
233 } else { | |
234 switch_native = parameter_string.substr( | |
235 switch_start, equals_position - switch_start); | |
236 *switch_value = parameter_string.substr(equals_position + 1); | |
237 } | |
238 #if defined(OS_WIN) | 232 #if defined(OS_WIN) |
239 *switch_string = WideToASCII(switch_native); | 233 return command_line_string_; |
240 Lowercase(switch_string); | |
241 #else | |
242 *switch_string = switch_native; | |
243 #endif | |
244 | |
245 return true; | |
246 } | |
247 | |
248 return false; | |
249 } | |
250 | |
251 // static | |
252 void CommandLine::Init(int argc, const char* const* argv) { | |
253 delete current_process_commandline_; | |
254 current_process_commandline_ = new CommandLine; | |
255 #if defined(OS_WIN) | |
256 current_process_commandline_->ParseFromString(::GetCommandLineW()); | |
257 #elif defined(OS_POSIX) | 234 #elif defined(OS_POSIX) |
258 current_process_commandline_->InitFromArgv(argc, argv); | 235 return JoinString(argv_, ' '); |
259 #endif | 236 #endif |
260 } | 237 } |
261 | 238 |
262 void CommandLine::Reset() { | 239 FilePath CommandLine::GetProgram() const { |
263 DCHECK(current_process_commandline_ != NULL); | 240 #if defined(OS_WIN) |
264 delete current_process_commandline_; | 241 return FilePath(program_); |
265 current_process_commandline_ = NULL; | 242 #else |
266 } | 243 DCHECK_GT(argv_.size(), 0U); |
267 | 244 return FilePath(argv_[0]); |
268 // static | 245 #endif |
269 CommandLine* CommandLine::ForCurrentProcess() { | |
270 DCHECK(current_process_commandline_); | |
271 return current_process_commandline_; | |
272 } | 246 } |
273 | 247 |
274 bool CommandLine::HasSwitch(const std::string& switch_string) const { | 248 bool CommandLine::HasSwitch(const std::string& switch_string) const { |
275 std::string lowercased_switch(switch_string); | 249 std::string lowercased_switch(switch_string); |
276 #if defined(OS_WIN) | 250 #if defined(OS_WIN) |
277 Lowercase(&lowercased_switch); | 251 Lowercase(&lowercased_switch); |
278 #endif | 252 #endif |
279 return switches_.find(lowercased_switch) != switches_.end(); | 253 return switches_.find(lowercased_switch) != switches_.end(); |
280 } | 254 } |
281 | 255 |
(...skipping 16 matching lines...) Expand all Loading... |
298 return FilePath(GetSwitchValueNative(switch_string)); | 272 return FilePath(GetSwitchValueNative(switch_string)); |
299 } | 273 } |
300 | 274 |
301 CommandLine::StringType CommandLine::GetSwitchValueNative( | 275 CommandLine::StringType CommandLine::GetSwitchValueNative( |
302 const std::string& switch_string) const { | 276 const std::string& switch_string) const { |
303 std::string lowercased_switch(switch_string); | 277 std::string lowercased_switch(switch_string); |
304 #if defined(OS_WIN) | 278 #if defined(OS_WIN) |
305 Lowercase(&lowercased_switch); | 279 Lowercase(&lowercased_switch); |
306 #endif | 280 #endif |
307 | 281 |
308 std::map<std::string, StringType>::const_iterator result = | 282 SwitchMap::const_iterator result = switches_.find(lowercased_switch); |
309 switches_.find(lowercased_switch); | |
310 | 283 |
311 if (result == switches_.end()) { | 284 if (result == switches_.end()) { |
312 return CommandLine::StringType(); | 285 return CommandLine::StringType(); |
313 } else { | 286 } else { |
314 return result->second; | 287 return result->second; |
315 } | 288 } |
316 } | 289 } |
317 | 290 |
318 FilePath CommandLine::GetProgram() const { | 291 size_t CommandLine::GetSwitchCount() const { |
| 292 return switches_.size(); |
| 293 } |
| 294 |
| 295 void CommandLine::AppendSwitch(const std::string& switch_string) { |
319 #if defined(OS_WIN) | 296 #if defined(OS_WIN) |
320 return FilePath(program_); | 297 command_line_string_.append(L" "); |
321 #else | 298 command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string)); |
322 DCHECK_GT(argv_.size(), 0U); | 299 switches_[switch_string] = L""; |
323 return FilePath(argv_[0]); | 300 #elif defined(OS_POSIX) |
| 301 argv_.push_back(kSwitchPrefixes[0] + switch_string); |
| 302 switches_[switch_string] = ""; |
324 #endif | 303 #endif |
325 } | 304 } |
326 | 305 |
327 #if defined(OS_POSIX) | 306 void CommandLine::AppendSwitchPath(const std::string& switch_string, |
328 std::string CommandLine::command_line_string() const { | 307 const FilePath& path) { |
329 return JoinString(argv_, ' '); | 308 AppendSwitchNative(switch_string, path.value()); |
330 } | |
331 #endif | |
332 | |
333 #if defined(OS_WIN) | |
334 void CommandLine::AppendSwitch(const std::string& switch_string) { | |
335 command_line_string_.append(L" "); | |
336 command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string)); | |
337 switches_[switch_string] = L""; | |
338 } | 309 } |
339 | 310 |
340 void CommandLine::AppendSwitchNative(const std::string& switch_string, | 311 void CommandLine::AppendSwitchNative(const std::string& switch_string, |
341 const std::wstring& value) { | 312 const CommandLine::StringType& value) { |
342 std::wstring combined_switch_string = | 313 #if defined(OS_WIN) |
| 314 StringType combined_switch_string = |
343 kSwitchPrefixes[0] + ASCIIToWide(switch_string); | 315 kSwitchPrefixes[0] + ASCIIToWide(switch_string); |
344 if (!value.empty()) | 316 if (!value.empty()) |
345 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value); | 317 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value); |
346 | 318 |
347 command_line_string_.append(L" "); | 319 command_line_string_.append(L" "); |
348 command_line_string_.append(combined_switch_string); | 320 command_line_string_.append(combined_switch_string); |
349 | 321 |
350 switches_[switch_string] = value; | 322 switches_[switch_string] = value; |
| 323 #elif defined(OS_POSIX) |
| 324 StringType combined_switch_string = kSwitchPrefixes[0] + switch_string; |
| 325 if (!value.empty()) |
| 326 combined_switch_string += kSwitchValueSeparator + value; |
| 327 argv_.push_back(combined_switch_string); |
| 328 switches_[switch_string] = value; |
| 329 #endif |
351 } | 330 } |
352 | 331 |
353 void CommandLine::AppendSwitchASCII(const std::string& switch_string, | 332 void CommandLine::AppendSwitchASCII(const std::string& switch_string, |
354 const std::string& value_string) { | 333 const std::string& value_string) { |
| 334 #if defined(OS_WIN) |
355 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); | 335 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); |
| 336 #elif defined(OS_POSIX) |
| 337 AppendSwitchNative(switch_string, value_string); |
| 338 #endif |
| 339 } |
| 340 |
| 341 void CommandLine::AppendSwitches(const CommandLine& other) { |
| 342 SwitchMap::const_iterator i; |
| 343 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) |
| 344 AppendSwitchNative(i->first, i->second); |
| 345 } |
| 346 |
| 347 void CommandLine::CopySwitchesFrom(const CommandLine& source, |
| 348 const char* const switches[], |
| 349 size_t count) { |
| 350 for (size_t i = 0; i < count; ++i) { |
| 351 if (source.HasSwitch(switches[i])) { |
| 352 StringType value = source.GetSwitchValueNative(switches[i]); |
| 353 AppendSwitchNative(switches[i], value); |
| 354 } |
| 355 } |
356 } | 356 } |
357 | 357 |
358 void CommandLine::AppendArg(const std::string& value) { | 358 void CommandLine::AppendArg(const std::string& value) { |
| 359 #if defined(OS_WIN) |
359 DCHECK(IsStringUTF8(value)); | 360 DCHECK(IsStringUTF8(value)); |
360 AppendArgNative(UTF8ToWide(value)); | 361 AppendArgNative(UTF8ToWide(value)); |
| 362 #elif defined(OS_POSIX) |
| 363 AppendArgNative(value); |
| 364 #endif |
361 } | 365 } |
362 | 366 |
363 void CommandLine::AppendArgNative(const std::wstring& value) { | 367 void CommandLine::AppendArgPath(const FilePath& path) { |
| 368 AppendArgNative(path.value()); |
| 369 } |
| 370 |
| 371 void CommandLine::AppendArgNative(const CommandLine::StringType& value) { |
| 372 #if defined(OS_WIN) |
364 command_line_string_.append(L" "); | 373 command_line_string_.append(L" "); |
365 command_line_string_.append(WindowsStyleQuote(value)); | 374 command_line_string_.append(WindowsStyleQuote(value)); |
366 args_.push_back(value); | 375 args_.push_back(value); |
| 376 #elif defined(OS_POSIX) |
| 377 DCHECK(IsStringUTF8(value)); |
| 378 argv_.push_back(value); |
| 379 #endif |
| 380 } |
| 381 |
| 382 void CommandLine::AppendArgs(const CommandLine& other) { |
| 383 if(other.args_.size() <= 0) |
| 384 return; |
| 385 #if defined(OS_WIN) |
| 386 command_line_string_.append(L" --"); |
| 387 #endif // OS_WIN |
| 388 StringVector::const_iterator i; |
| 389 for (i = other.args_.begin(); i != other.args_.end(); ++i) |
| 390 AppendArgNative(*i); |
367 } | 391 } |
368 | 392 |
369 void CommandLine::AppendArguments(const CommandLine& other, | 393 void CommandLine::AppendArguments(const CommandLine& other, |
370 bool include_program) { | 394 bool include_program) { |
| 395 #if defined(OS_WIN) |
371 // Verify include_program is used correctly. | 396 // Verify include_program is used correctly. |
372 DCHECK(!include_program || !other.GetProgram().empty()); | 397 DCHECK(!include_program || !other.GetProgram().empty()); |
373 if (include_program) | 398 if (include_program) |
374 program_ = other.program_; | 399 program_ = other.program_; |
375 | 400 |
376 if (!command_line_string_.empty()) | 401 if (!command_line_string_.empty()) |
377 command_line_string_ += L' '; | 402 command_line_string_ += L' '; |
378 | 403 |
379 command_line_string_ += other.command_line_string_; | 404 command_line_string_ += other.command_line_string_; |
380 | |
381 std::map<std::string, StringType>::const_iterator i; | |
382 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) | |
383 switches_[i->first] = i->second; | |
384 } | |
385 | |
386 void CommandLine::PrependWrapper(const std::wstring& wrapper) { | |
387 if (wrapper.empty()) | |
388 return; | |
389 // The wrapper may have embedded arguments (like "gdb --args"). In this case, | |
390 // we don't pretend to do anything fancy, we just split on spaces. | |
391 std::vector<std::wstring> wrapper_and_args; | |
392 base::SplitString(wrapper, ' ', &wrapper_and_args); | |
393 program_ = wrapper_and_args[0]; | |
394 command_line_string_ = wrapper + L" " + command_line_string_; | |
395 } | |
396 | |
397 #elif defined(OS_POSIX) | 405 #elif defined(OS_POSIX) |
398 void CommandLine::AppendSwitch(const std::string& switch_string) { | |
399 argv_.push_back(kSwitchPrefixes[0] + switch_string); | |
400 switches_[switch_string] = ""; | |
401 } | |
402 | |
403 void CommandLine::AppendSwitchNative(const std::string& switch_string, | |
404 const std::string& value) { | |
405 std::string combined_switch_string = kSwitchPrefixes[0] + switch_string; | |
406 if (!value.empty()) | |
407 combined_switch_string += kSwitchValueSeparator + value; | |
408 argv_.push_back(combined_switch_string); | |
409 switches_[switch_string] = value; | |
410 } | |
411 | |
412 void CommandLine::AppendSwitchASCII(const std::string& switch_string, | |
413 const std::string& value_string) { | |
414 AppendSwitchNative(switch_string, value_string); | |
415 } | |
416 | |
417 void CommandLine::AppendArg(const std::string& value) { | |
418 AppendArgNative(value); | |
419 } | |
420 | |
421 void CommandLine::AppendArgNative(const std::string& value) { | |
422 DCHECK(IsStringUTF8(value)); | |
423 argv_.push_back(value); | |
424 } | |
425 | |
426 void CommandLine::AppendArguments(const CommandLine& other, | |
427 bool include_program) { | |
428 // Verify include_program is used correctly. | 406 // Verify include_program is used correctly. |
429 // Logic could be shorter but this is clearer. | 407 // Logic could be shorter but this is clearer. |
430 DCHECK_EQ(include_program, !other.GetProgram().empty()); | 408 DCHECK_EQ(include_program, !other.GetProgram().empty()); |
431 | 409 |
432 if (include_program) | 410 if (include_program) |
433 argv_[0] = other.argv_[0]; | 411 argv_[0] = other.argv_[0]; |
434 | 412 |
435 // Skip the first arg when copying since it's the program but push all | 413 // Skip the first arg when copying since it's the program but push all |
436 // arguments to our arg vector. | 414 // arguments to our arg vector. |
437 for (size_t i = 1; i < other.argv_.size(); ++i) | 415 for (size_t i = 1; i < other.argv_.size(); ++i) |
438 argv_.push_back(other.argv_[i]); | 416 argv_.push_back(other.argv_[i]); |
| 417 #endif |
439 | 418 |
440 std::map<std::string, StringType>::const_iterator i; | 419 SwitchMap::const_iterator i; |
441 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) | 420 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) |
442 switches_[i->first] = i->second; | 421 switches_[i->first] = i->second; |
443 } | 422 } |
444 | 423 |
445 void CommandLine::PrependWrapper(const std::string& wrapper) { | 424 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) { |
446 // The wrapper may have embedded arguments (like "gdb --args"). In this case, | 425 // The wrapper may have embedded arguments (like "gdb --args"). In this case, |
447 // we don't pretend to do anything fancy, we just split on spaces. | 426 // we don't pretend to do anything fancy, we just split on spaces. |
448 std::vector<std::string> wrapper_and_args; | 427 if (wrapper.empty()) |
| 428 return; |
| 429 StringVector wrapper_and_args; |
| 430 #if defined(OS_WIN) |
| 431 base::SplitString(wrapper, ' ', &wrapper_and_args); |
| 432 program_ = wrapper_and_args[0]; |
| 433 command_line_string_ = wrapper + L" " + command_line_string_; |
| 434 #elif defined(OS_POSIX) |
449 base::SplitString(wrapper, ' ', &wrapper_and_args); | 435 base::SplitString(wrapper, ' ', &wrapper_and_args); |
450 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end()); | 436 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end()); |
| 437 #endif |
451 } | 438 } |
452 | 439 |
453 #endif | 440 #if defined(OS_WIN) |
| 441 void CommandLine::ParseFromString(const std::wstring& command_line) { |
| 442 TrimWhitespace(command_line, TRIM_ALL, &command_line_string_); |
454 | 443 |
455 void CommandLine::AppendSwitchPath(const std::string& switch_string, | 444 if (command_line_string_.empty()) |
456 const FilePath& path) { | |
457 AppendSwitchNative(switch_string, path.value()); | |
458 } | |
459 | |
460 void CommandLine::AppendSwitches(const CommandLine& other) { | |
461 std::map<std::string, StringType>::const_iterator i; | |
462 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) | |
463 AppendSwitchNative(i->first, i->second); | |
464 } | |
465 | |
466 void CommandLine::AppendArgPath(const FilePath& path) { | |
467 AppendArgNative(path.value()); | |
468 } | |
469 | |
470 void CommandLine::AppendArgs(const CommandLine& other) { | |
471 if(other.args_.size() <= 0) | |
472 return; | 445 return; |
473 | 446 |
474 #if defined(OS_WIN) | 447 int num_args = 0; |
475 command_line_string_.append(L" --"); | 448 wchar_t** args = NULL; |
476 #endif // OS_WIN | |
477 std::vector<StringType>::const_iterator i; | |
478 for (i = other.args_.begin(); i != other.args_.end(); ++i) | |
479 AppendArgNative(*i); | |
480 } | |
481 | 449 |
482 void CommandLine::CopySwitchesFrom(const CommandLine& source, | 450 args = CommandLineToArgvW(command_line_string_.c_str(), &num_args); |
483 const char* const switches[], | 451 |
484 size_t count) { | 452 // Populate program_ with the trimmed version of the first arg. |
485 for (size_t i = 0; i < count; ++i) { | 453 TrimWhitespace(args[0], TRIM_ALL, &program_); |
486 if (source.HasSwitch(switches[i])) { | 454 |
487 StringType value = source.GetSwitchValueNative(switches[i]); | 455 bool parse_switches = true; |
488 AppendSwitchNative(switches[i], value); | 456 for (int i = 1; i < num_args; ++i) { |
| 457 std::wstring arg; |
| 458 TrimWhitespace(args[i], TRIM_ALL, &arg); |
| 459 |
| 460 if (!parse_switches) { |
| 461 args_.push_back(arg); |
| 462 continue; |
| 463 } |
| 464 |
| 465 if (arg == kSwitchTerminator) { |
| 466 parse_switches = false; |
| 467 continue; |
| 468 } |
| 469 |
| 470 std::string switch_string; |
| 471 std::wstring switch_value; |
| 472 if (IsSwitch(arg, &switch_string, &switch_value)) { |
| 473 switches_[switch_string] = switch_value; |
| 474 } else { |
| 475 args_.push_back(arg); |
489 } | 476 } |
490 } | 477 } |
| 478 |
| 479 if (args) |
| 480 LocalFree(args); |
491 } | 481 } |
492 | 482 #endif |
493 // private | |
494 CommandLine::CommandLine() { | |
495 } | |
496 | |
497 // static | |
498 CommandLine* CommandLine::ForCurrentProcessMutable() { | |
499 DCHECK(current_process_commandline_); | |
500 return current_process_commandline_; | |
501 } | |
OLD | NEW |