| 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 CommandLine::StringType WindowsStyleQuote(const CommandLine::StringType& 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" \\\"") == CommandLine::StringType::npos) { |
| 59 // No quoting necessary. | 57 // No quoting necessary. |
| 60 return arg; | 58 return arg; |
| 61 } | 59 } |
| 62 | 60 |
| 63 std::wstring out; | 61 CommandLine::StringType out; |
| 64 out.push_back(L'"'); | 62 out.push_back(L'"'); |
| 65 for (size_t i = 0; i < arg.size(); ++i) { | 63 for (size_t i = 0; i < arg.size(); ++i) { |
| 66 if (arg[i] == '\\') { | 64 if (arg[i] == '\\') { |
| 67 // Find the extent of this run of backslashes. | 65 // Find the extent of this run of backslashes. |
| 68 size_t start = i, end = start + 1; | 66 size_t start = i, end = start + 1; |
| 69 for (; end < arg.size() && arg[end] == '\\'; ++end) | 67 for (; end < arg.size() && arg[end] == '\\'; ++end) |
| 70 /* empty */; | 68 /* empty */; |
| 71 size_t backslash_count = end - start; | 69 size_t backslash_count = end - start; |
| 72 | 70 |
| 73 // Backslashes are escapes only if the run is followed by a double quote. | 71 // Backslashes are escapes only if the run is followed by a double quote. |
| (...skipping 12 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; |
| 100 } | 131 } |
| 101 | 132 |
| 102 #if defined(OS_WIN) | 133 } // namespace |
| 134 |
| 103 CommandLine::CommandLine(NoProgram no_program) { | 135 CommandLine::CommandLine(NoProgram no_program) { |
| 104 } | 136 #if defined(OS_POSIX) |
| 105 | 137 // Push an empty argument, because we always assume argv_[0] is a program. |
| 106 void CommandLine::ParseFromString(const std::wstring& command_line) { | 138 argv_.push_back(""); |
| 107 TrimWhitespace(command_line, TRIM_ALL, &command_line_string_); | 139 #endif |
| 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 | |
| 149 CommandLine CommandLine::FromString(const std::wstring& command_line) { | |
| 150 CommandLine cmd; | |
| 151 cmd.ParseFromString(command_line); | |
| 152 return cmd; | |
| 153 } | 140 } |
| 154 | 141 |
| 155 CommandLine::CommandLine(const FilePath& program) { | 142 CommandLine::CommandLine(const FilePath& program) { |
| 143 #if defined(OS_WIN) |
| 156 if (!program.empty()) { | 144 if (!program.empty()) { |
| 157 program_ = program.value(); | 145 program_ = program.value(); |
| 158 // TODO(evanm): proper quoting here. | 146 // TODO(evanm): proper quoting here. |
| 159 command_line_string_ = L'"' + program.value() + L'"'; | 147 command_line_string_ = L'"' + program.value() + L'"'; |
| 160 } | 148 } |
| 149 #elif defined(OS_POSIX) |
| 150 argv_.push_back(program.value()); |
| 151 #endif |
| 161 } | 152 } |
| 162 | 153 |
| 163 #elif defined(OS_POSIX) | 154 #if 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) { | 155 CommandLine::CommandLine(int argc, const char* const* argv) { |
| 170 InitFromArgv(argc, argv); | 156 InitFromArgv(argc, argv); |
| 171 } | 157 } |
| 172 | 158 |
| 173 CommandLine::CommandLine(const std::vector<std::string>& argv) { | 159 CommandLine::CommandLine(const StringVector& argv) { |
| 174 InitFromArgv(argv); | 160 InitFromArgv(argv); |
| 175 } | 161 } |
| 162 #endif // OS_POSIX |
| 176 | 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_; |
| 186 } |
| 187 |
| 188 #if defined(OS_WIN) |
| 189 // static |
| 190 CommandLine CommandLine::FromString( |
| 191 const CommandLine::StringType& command_line) { |
| 192 CommandLine cmd; |
| 193 cmd.ParseFromString(command_line); |
| 194 return cmd; |
| 195 } |
| 196 #endif // OS_WIN |
| 197 |
| 198 #if defined(OS_POSIX) |
| 177 void CommandLine::InitFromArgv(int argc, const char* const* argv) { | 199 void CommandLine::InitFromArgv(int argc, const char* const* argv) { |
| 178 for (int i = 0; i < argc; ++i) | 200 for (int i = 0; i < argc; ++i) |
| 179 argv_.push_back(argv[i]); | 201 argv_.push_back(argv[i]); |
| 180 InitFromArgv(argv_); | 202 InitFromArgv(argv_); |
| 181 } | 203 } |
| 182 | 204 |
| 183 void CommandLine::InitFromArgv(const std::vector<std::string>& argv) { | 205 void CommandLine::InitFromArgv(const StringVector& argv) { |
| 184 argv_ = argv; | 206 argv_ = argv; |
| 185 bool parse_switches = true; | 207 bool parse_switches = true; |
| 186 for (size_t i = 1; i < argv_.size(); ++i) { | 208 for (size_t i = 1; i < argv_.size(); ++i) { |
| 187 const std::string& arg = argv_[i]; | 209 const std::string& arg = argv_[i]; |
| 188 | 210 |
| 189 if (!parse_switches) { | 211 if (!parse_switches) { |
| 190 args_.push_back(arg); | 212 args_.push_back(arg); |
| 191 continue; | 213 continue; |
| 192 } | 214 } |
| 193 | 215 |
| 194 if (arg == kSwitchTerminator) { | 216 if (arg == kSwitchTerminator) { |
| 195 parse_switches = false; | 217 parse_switches = false; |
| 196 continue; | 218 continue; |
| 197 } | 219 } |
| 198 | 220 |
| 199 std::string switch_string; | 221 std::string switch_string; |
| 200 std::string switch_value; | 222 StringType switch_value; |
| 201 if (IsSwitch(arg, &switch_string, &switch_value)) { | 223 if (IsSwitch(arg, &switch_string, &switch_value)) { |
| 202 switches_[switch_string] = switch_value; | 224 switches_[switch_string] = switch_value; |
| 203 } else { | 225 } else { |
| 204 args_.push_back(arg); | 226 args_.push_back(arg); |
| 205 } | 227 } |
| 206 } | 228 } |
| 207 } | 229 } |
| 230 #endif // OS_POSIX |
| 208 | 231 |
| 209 CommandLine::CommandLine(const FilePath& program) { | 232 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) | 233 #if defined(OS_WIN) |
| 239 *switch_string = WideToASCII(switch_native); | 234 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) | 235 #elif defined(OS_POSIX) |
| 258 current_process_commandline_->InitFromArgv(argc, argv); | 236 return JoinString(argv_, ' '); |
| 259 #endif | 237 #endif |
| 260 } | 238 } |
| 261 | 239 |
| 262 void CommandLine::Reset() { | 240 FilePath CommandLine::GetProgram() const { |
| 263 DCHECK(current_process_commandline_ != NULL); | 241 #if defined(OS_WIN) |
| 264 delete current_process_commandline_; | 242 return FilePath(program_); |
| 265 current_process_commandline_ = NULL; | 243 #else |
| 266 } | 244 DCHECK_GT(argv_.size(), 0U); |
| 267 | 245 return FilePath(argv_[0]); |
| 268 // static | 246 #endif |
| 269 CommandLine* CommandLine::ForCurrentProcess() { | |
| 270 DCHECK(current_process_commandline_); | |
| 271 return current_process_commandline_; | |
| 272 } | 247 } |
| 273 | 248 |
| 274 bool CommandLine::HasSwitch(const std::string& switch_string) const { | 249 bool CommandLine::HasSwitch(const std::string& switch_string) const { |
| 275 std::string lowercased_switch(switch_string); | 250 std::string lowercased_switch(switch_string); |
| 276 #if defined(OS_WIN) | 251 #if defined(OS_WIN) |
| 277 Lowercase(&lowercased_switch); | 252 Lowercase(&lowercased_switch); |
| 278 #endif | 253 #endif |
| 279 return switches_.find(lowercased_switch) != switches_.end(); | 254 return switches_.find(lowercased_switch) != switches_.end(); |
| 280 } | 255 } |
| 281 | 256 |
| (...skipping 16 matching lines...) Expand all Loading... |
| 298 return FilePath(GetSwitchValueNative(switch_string)); | 273 return FilePath(GetSwitchValueNative(switch_string)); |
| 299 } | 274 } |
| 300 | 275 |
| 301 CommandLine::StringType CommandLine::GetSwitchValueNative( | 276 CommandLine::StringType CommandLine::GetSwitchValueNative( |
| 302 const std::string& switch_string) const { | 277 const std::string& switch_string) const { |
| 303 std::string lowercased_switch(switch_string); | 278 std::string lowercased_switch(switch_string); |
| 304 #if defined(OS_WIN) | 279 #if defined(OS_WIN) |
| 305 Lowercase(&lowercased_switch); | 280 Lowercase(&lowercased_switch); |
| 306 #endif | 281 #endif |
| 307 | 282 |
| 308 std::map<std::string, StringType>::const_iterator result = | 283 SwitchMap::const_iterator result = switches_.find(lowercased_switch); |
| 309 switches_.find(lowercased_switch); | |
| 310 | 284 |
| 311 if (result == switches_.end()) { | 285 if (result == switches_.end()) { |
| 312 return CommandLine::StringType(); | 286 return CommandLine::StringType(); |
| 313 } else { | 287 } else { |
| 314 return result->second; | 288 return result->second; |
| 315 } | 289 } |
| 316 } | 290 } |
| 317 | 291 |
| 318 FilePath CommandLine::GetProgram() const { | 292 size_t CommandLine::GetSwitchCount() const { |
| 293 return switches_.size(); |
| 294 } |
| 295 |
| 296 void CommandLine::AppendSwitch(const std::string& switch_string) { |
| 319 #if defined(OS_WIN) | 297 #if defined(OS_WIN) |
| 320 return FilePath(program_); | 298 command_line_string_.append(L" "); |
| 321 #else | 299 command_line_string_.append(kSwitchPrefixes[0] + ASCIIToWide(switch_string)); |
| 322 DCHECK_GT(argv_.size(), 0U); | 300 switches_[switch_string] = L""; |
| 323 return FilePath(argv_[0]); | 301 #elif defined(OS_POSIX) |
| 302 argv_.push_back(kSwitchPrefixes[0] + switch_string); |
| 303 switches_[switch_string] = ""; |
| 324 #endif | 304 #endif |
| 325 } | 305 } |
| 326 | 306 |
| 327 #if defined(OS_POSIX) | 307 void CommandLine::AppendSwitchPath(const std::string& switch_string, |
| 328 std::string CommandLine::command_line_string() const { | 308 const FilePath& path) { |
| 329 return JoinString(argv_, ' '); | 309 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 } | 310 } |
| 339 | 311 |
| 340 void CommandLine::AppendSwitchNative(const std::string& switch_string, | 312 void CommandLine::AppendSwitchNative(const std::string& switch_string, |
| 341 const std::wstring& value) { | 313 const CommandLine::StringType& value) { |
| 342 std::wstring combined_switch_string = | 314 #if defined(OS_WIN) |
| 315 StringType combined_switch_string = |
| 343 kSwitchPrefixes[0] + ASCIIToWide(switch_string); | 316 kSwitchPrefixes[0] + ASCIIToWide(switch_string); |
| 344 if (!value.empty()) | 317 if (!value.empty()) |
| 345 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value); | 318 combined_switch_string += kSwitchValueSeparator + WindowsStyleQuote(value); |
| 346 | 319 |
| 347 command_line_string_.append(L" "); | 320 command_line_string_.append(L" "); |
| 348 command_line_string_.append(combined_switch_string); | 321 command_line_string_.append(combined_switch_string); |
| 349 | 322 |
| 350 switches_[switch_string] = value; | 323 switches_[switch_string] = value; |
| 324 #elif defined(OS_POSIX) |
| 325 StringType combined_switch_string = kSwitchPrefixes[0] + switch_string; |
| 326 if (!value.empty()) |
| 327 combined_switch_string += kSwitchValueSeparator + value; |
| 328 argv_.push_back(combined_switch_string); |
| 329 switches_[switch_string] = value; |
| 330 #endif |
| 351 } | 331 } |
| 352 | 332 |
| 353 void CommandLine::AppendSwitchASCII(const std::string& switch_string, | 333 void CommandLine::AppendSwitchASCII(const std::string& switch_string, |
| 354 const std::string& value_string) { | 334 const std::string& value_string) { |
| 335 #if defined(OS_WIN) |
| 355 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); | 336 AppendSwitchNative(switch_string, ASCIIToWide(value_string)); |
| 337 #elif defined(OS_POSIX) |
| 338 AppendSwitchNative(switch_string, value_string); |
| 339 #endif |
| 340 } |
| 341 |
| 342 void CommandLine::AppendSwitches(const CommandLine& other) { |
| 343 SwitchMap::const_iterator i; |
| 344 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) |
| 345 AppendSwitchNative(i->first, i->second); |
| 346 } |
| 347 |
| 348 void CommandLine::CopySwitchesFrom(const CommandLine& source, |
| 349 const char* const switches[], |
| 350 size_t count) { |
| 351 for (size_t i = 0; i < count; ++i) { |
| 352 if (source.HasSwitch(switches[i])) { |
| 353 StringType value = source.GetSwitchValueNative(switches[i]); |
| 354 AppendSwitchNative(switches[i], value); |
| 355 } |
| 356 } |
| 356 } | 357 } |
| 357 | 358 |
| 358 void CommandLine::AppendArg(const std::string& value) { | 359 void CommandLine::AppendArg(const std::string& value) { |
| 360 #if defined(OS_WIN) |
| 359 DCHECK(IsStringUTF8(value)); | 361 DCHECK(IsStringUTF8(value)); |
| 360 AppendArgNative(UTF8ToWide(value)); | 362 AppendArgNative(UTF8ToWide(value)); |
| 363 #elif defined(OS_POSIX) |
| 364 AppendArgNative(value); |
| 365 #endif |
| 361 } | 366 } |
| 362 | 367 |
| 363 void CommandLine::AppendArgNative(const std::wstring& value) { | 368 void CommandLine::AppendArgPath(const FilePath& path) { |
| 369 AppendArgNative(path.value()); |
| 370 } |
| 371 |
| 372 void CommandLine::AppendArgNative(const CommandLine::StringType& value) { |
| 373 #if defined(OS_WIN) |
| 364 command_line_string_.append(L" "); | 374 command_line_string_.append(L" "); |
| 365 command_line_string_.append(WindowsStyleQuote(value)); | 375 command_line_string_.append(WindowsStyleQuote(value)); |
| 366 args_.push_back(value); | 376 args_.push_back(value); |
| 377 #elif defined(OS_POSIX) |
| 378 DCHECK(IsStringUTF8(value)); |
| 379 argv_.push_back(value); |
| 380 #endif |
| 381 } |
| 382 |
| 383 void CommandLine::AppendArgs(const CommandLine& other) { |
| 384 if(other.args_.size() <= 0) |
| 385 return; |
| 386 #if defined(OS_WIN) |
| 387 command_line_string_.append(L" --"); |
| 388 #endif // OS_WIN |
| 389 StringVector::const_iterator i; |
| 390 for (i = other.args_.begin(); i != other.args_.end(); ++i) |
| 391 AppendArgNative(*i); |
| 367 } | 392 } |
| 368 | 393 |
| 369 void CommandLine::AppendArguments(const CommandLine& other, | 394 void CommandLine::AppendArguments(const CommandLine& other, |
| 370 bool include_program) { | 395 bool include_program) { |
| 396 #if defined(OS_WIN) |
| 371 // Verify include_program is used correctly. | 397 // Verify include_program is used correctly. |
| 372 DCHECK(!include_program || !other.GetProgram().empty()); | 398 DCHECK(!include_program || !other.GetProgram().empty()); |
| 373 if (include_program) | 399 if (include_program) |
| 374 program_ = other.program_; | 400 program_ = other.program_; |
| 375 | 401 |
| 376 if (!command_line_string_.empty()) | 402 if (!command_line_string_.empty()) |
| 377 command_line_string_ += L' '; | 403 command_line_string_ += L' '; |
| 378 | 404 |
| 379 command_line_string_ += other.command_line_string_; | 405 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) | 406 #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. | 407 // Verify include_program is used correctly. |
| 429 // Logic could be shorter but this is clearer. | 408 // Logic could be shorter but this is clearer. |
| 430 DCHECK_EQ(include_program, !other.GetProgram().empty()); | 409 DCHECK_EQ(include_program, !other.GetProgram().empty()); |
| 431 | 410 |
| 432 if (include_program) | 411 if (include_program) |
| 433 argv_[0] = other.argv_[0]; | 412 argv_[0] = other.argv_[0]; |
| 434 | 413 |
| 435 // Skip the first arg when copying since it's the program but push all | 414 // Skip the first arg when copying since it's the program but push all |
| 436 // arguments to our arg vector. | 415 // arguments to our arg vector. |
| 437 for (size_t i = 1; i < other.argv_.size(); ++i) | 416 for (size_t i = 1; i < other.argv_.size(); ++i) |
| 438 argv_.push_back(other.argv_[i]); | 417 argv_.push_back(other.argv_[i]); |
| 418 #endif |
| 439 | 419 |
| 440 std::map<std::string, StringType>::const_iterator i; | 420 SwitchMap::const_iterator i; |
| 441 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) | 421 for (i = other.switches_.begin(); i != other.switches_.end(); ++i) |
| 442 switches_[i->first] = i->second; | 422 switches_[i->first] = i->second; |
| 443 } | 423 } |
| 444 | 424 |
| 445 void CommandLine::PrependWrapper(const std::string& wrapper) { | 425 void CommandLine::PrependWrapper(const CommandLine::StringType& wrapper) { |
| 446 // The wrapper may have embedded arguments (like "gdb --args"). In this case, | 426 // 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. | 427 // we don't pretend to do anything fancy, we just split on spaces. |
| 448 std::vector<std::string> wrapper_and_args; | 428 if (wrapper.empty()) |
| 429 return; |
| 430 StringVector wrapper_and_args; |
| 431 #if defined(OS_WIN) |
| 432 base::SplitString(wrapper, ' ', &wrapper_and_args); |
| 433 program_ = wrapper_and_args[0]; |
| 434 command_line_string_ = wrapper + L" " + command_line_string_; |
| 435 #elif defined(OS_POSIX) |
| 449 base::SplitString(wrapper, ' ', &wrapper_and_args); | 436 base::SplitString(wrapper, ' ', &wrapper_and_args); |
| 450 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end()); | 437 argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end()); |
| 438 #endif |
| 451 } | 439 } |
| 452 | 440 |
| 453 #endif | 441 #if defined(OS_WIN) |
| 442 void CommandLine::ParseFromString(const CommandLine::StringType& command_line) { |
| 443 TrimWhitespace(command_line, TRIM_ALL, &command_line_string_); |
| 454 | 444 |
| 455 void CommandLine::AppendSwitchPath(const std::string& switch_string, | 445 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; | 446 return; |
| 473 | 447 |
| 474 #if defined(OS_WIN) | 448 int num_args = 0; |
| 475 command_line_string_.append(L" --"); | 449 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 | 450 |
| 482 void CommandLine::CopySwitchesFrom(const CommandLine& source, | 451 args = CommandLineToArgvW(command_line_string_.c_str(), &num_args); |
| 483 const char* const switches[], | 452 |
| 484 size_t count) { | 453 // Populate program_ with the trimmed version of the first arg. |
| 485 for (size_t i = 0; i < count; ++i) { | 454 TrimWhitespace(args[0], TRIM_ALL, &program_); |
| 486 if (source.HasSwitch(switches[i])) { | 455 |
| 487 StringType value = source.GetSwitchValueNative(switches[i]); | 456 bool parse_switches = true; |
| 488 AppendSwitchNative(switches[i], value); | 457 for (int i = 1; i < num_args; ++i) { |
| 458 StringType arg; |
| 459 TrimWhitespace(args[i], TRIM_ALL, &arg); |
| 460 |
| 461 if (!parse_switches) { |
| 462 args_.push_back(arg); |
| 463 continue; |
| 464 } |
| 465 |
| 466 if (arg == kSwitchTerminator) { |
| 467 parse_switches = false; |
| 468 continue; |
| 469 } |
| 470 |
| 471 std::string switch_string; |
| 472 StringType switch_value; |
| 473 if (IsSwitch(arg, &switch_string, &switch_value)) { |
| 474 switches_[switch_string] = switch_value; |
| 475 } else { |
| 476 args_.push_back(arg); |
| 489 } | 477 } |
| 490 } | 478 } |
| 479 |
| 480 if (args) |
| 481 LocalFree(args); |
| 491 } | 482 } |
| 492 | 483 #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 |