1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/command_line.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,392 @@ 1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.5 +// Use of this source code is governed by a BSD-style license that can be 1.6 +// found in the LICENSE file. 1.7 + 1.8 +#include "base/command_line.h" 1.9 + 1.10 +#if defined(OS_WIN) 1.11 +#include <windows.h> 1.12 +#include <shellapi.h> 1.13 +#endif 1.14 + 1.15 +#include <algorithm> 1.16 + 1.17 +#include "base/logging.h" 1.18 +#include "base/singleton.h" 1.19 +#include "base/string_piece.h" 1.20 +#include "base/string_util.h" 1.21 +#include "base/sys_string_conversions.h" 1.22 + 1.23 +CommandLine* CommandLine::current_process_commandline_ = NULL; 1.24 + 1.25 +// Since we use a lazy match, make sure that longer versions (like L"--") 1.26 +// are listed before shorter versions (like L"-") of similar prefixes. 1.27 +#if defined(OS_WIN) 1.28 +const wchar_t* const kSwitchPrefixes[] = {L"--", L"-", L"/"}; 1.29 +const wchar_t kSwitchTerminator[] = L"--"; 1.30 +const wchar_t kSwitchValueSeparator[] = L"="; 1.31 +#elif defined(OS_POSIX) 1.32 +// Unixes don't use slash as a switch. 1.33 +const char* const kSwitchPrefixes[] = {"--", "-"}; 1.34 +const char kSwitchTerminator[] = "--"; 1.35 +const char kSwitchValueSeparator[] = "="; 1.36 +#endif 1.37 + 1.38 +#if defined(OS_WIN) 1.39 +// Lowercase a string. This is used to lowercase switch names. 1.40 +// Is this what we really want? It seems crazy to me. I've left it in 1.41 +// for backwards compatibility on Windows. 1.42 +static void Lowercase(std::wstring* parameter) { 1.43 + transform(parameter->begin(), parameter->end(), parameter->begin(), 1.44 + tolower); 1.45 +} 1.46 +#endif 1.47 + 1.48 +#if defined(OS_WIN) 1.49 +void CommandLine::ParseFromString(const std::wstring& command_line) { 1.50 + TrimWhitespace(command_line, TRIM_ALL, &command_line_string_); 1.51 + 1.52 + if (command_line_string_.empty()) 1.53 + return; 1.54 + 1.55 + int num_args = 0; 1.56 + wchar_t** args = NULL; 1.57 + 1.58 + args = CommandLineToArgvW(command_line_string_.c_str(), &num_args); 1.59 + 1.60 + // Populate program_ with the trimmed version of the first arg. 1.61 + TrimWhitespace(args[0], TRIM_ALL, &program_); 1.62 + 1.63 + bool parse_switches = true; 1.64 + for (int i = 1; i < num_args; ++i) { 1.65 + std::wstring arg; 1.66 + TrimWhitespace(args[i], TRIM_ALL, &arg); 1.67 + 1.68 + if (!parse_switches) { 1.69 + loose_values_.push_back(arg); 1.70 + continue; 1.71 + } 1.72 + 1.73 + if (arg == kSwitchTerminator) { 1.74 + parse_switches = false; 1.75 + continue; 1.76 + } 1.77 + 1.78 + std::string switch_string; 1.79 + std::wstring switch_value; 1.80 + if (IsSwitch(arg, &switch_string, &switch_value)) { 1.81 + switches_[switch_string] = switch_value; 1.82 + } else { 1.83 + loose_values_.push_back(arg); 1.84 + } 1.85 + } 1.86 + 1.87 + if (args) 1.88 + LocalFree(args); 1.89 +} 1.90 +CommandLine::CommandLine(const std::wstring& program) { 1.91 + if (!program.empty()) { 1.92 + program_ = program; 1.93 + command_line_string_ = L'"' + program + L'"'; 1.94 + } 1.95 +} 1.96 +#elif defined(OS_POSIX) 1.97 +CommandLine::CommandLine(int argc, const char* const* argv) { 1.98 + for (int i = 0; i < argc; ++i) 1.99 + argv_.push_back(argv[i]); 1.100 + InitFromArgv(); 1.101 +} 1.102 +CommandLine::CommandLine(const std::vector<std::string>& argv) { 1.103 + argv_ = argv; 1.104 + InitFromArgv(); 1.105 +} 1.106 + 1.107 +void CommandLine::InitFromArgv() { 1.108 + bool parse_switches = true; 1.109 + for (size_t i = 1; i < argv_.size(); ++i) { 1.110 + const std::string& arg = argv_[i]; 1.111 + 1.112 + if (!parse_switches) { 1.113 + loose_values_.push_back(arg); 1.114 + continue; 1.115 + } 1.116 + 1.117 + if (arg == kSwitchTerminator) { 1.118 + parse_switches = false; 1.119 + continue; 1.120 + } 1.121 + 1.122 + std::string switch_string; 1.123 + std::string switch_value; 1.124 + if (IsSwitch(arg, &switch_string, &switch_value)) { 1.125 + switches_[switch_string] = switch_value; 1.126 + } else { 1.127 + loose_values_.push_back(arg); 1.128 + } 1.129 + } 1.130 +} 1.131 + 1.132 +CommandLine::CommandLine(const std::wstring& program) { 1.133 + argv_.push_back(WideToASCII(program)); 1.134 +} 1.135 +#endif 1.136 + 1.137 +// static 1.138 +bool CommandLine::IsSwitch(const StringType& parameter_string, 1.139 + std::string* switch_string, 1.140 + StringType* switch_value) { 1.141 + switch_string->clear(); 1.142 + switch_value->clear(); 1.143 + 1.144 + for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) { 1.145 + StringType prefix(kSwitchPrefixes[i]); 1.146 + if (parameter_string.find(prefix) != 0) 1.147 + continue; 1.148 + 1.149 + const size_t switch_start = prefix.length(); 1.150 + const size_t equals_position = parameter_string.find( 1.151 + kSwitchValueSeparator, switch_start); 1.152 + StringType switch_native; 1.153 + if (equals_position == StringType::npos) { 1.154 + switch_native = parameter_string.substr(switch_start); 1.155 + } else { 1.156 + switch_native = parameter_string.substr( 1.157 + switch_start, equals_position - switch_start); 1.158 + *switch_value = parameter_string.substr(equals_position + 1); 1.159 + } 1.160 +#if defined(OS_WIN) 1.161 + Lowercase(&switch_native); 1.162 + *switch_string = WideToASCII(switch_native); 1.163 +#else 1.164 + *switch_string = switch_native; 1.165 +#endif 1.166 + 1.167 + return true; 1.168 + } 1.169 + 1.170 + return false; 1.171 +} 1.172 + 1.173 +// static 1.174 +void CommandLine::Init(int argc, const char* const* argv) { 1.175 + DCHECK(current_process_commandline_ == NULL); 1.176 +#if defined(OS_WIN) 1.177 + current_process_commandline_ = new CommandLine; 1.178 + current_process_commandline_->ParseFromString(::GetCommandLineW()); 1.179 +#elif defined(OS_POSIX) 1.180 + current_process_commandline_ = new CommandLine(argc, argv); 1.181 +#endif 1.182 +} 1.183 + 1.184 +void CommandLine::Terminate() { 1.185 + DCHECK(current_process_commandline_ != NULL); 1.186 + delete current_process_commandline_; 1.187 + current_process_commandline_ = NULL; 1.188 +} 1.189 + 1.190 +bool CommandLine::HasSwitch(const std::wstring& switch_string) const { 1.191 + std::wstring lowercased_switch(switch_string); 1.192 +#if defined(OS_WIN) 1.193 + Lowercase(&lowercased_switch); 1.194 +#endif 1.195 + return switches_.find(WideToASCII(lowercased_switch)) != switches_.end(); 1.196 +} 1.197 + 1.198 +std::wstring CommandLine::GetSwitchValue( 1.199 + const std::wstring& switch_string) const { 1.200 + std::wstring lowercased_switch(switch_string); 1.201 +#if defined(OS_WIN) 1.202 + Lowercase(&lowercased_switch); 1.203 +#endif 1.204 + 1.205 + std::map<std::string, StringType>::const_iterator result = 1.206 + switches_.find(WideToASCII(lowercased_switch)); 1.207 + 1.208 + if (result == switches_.end()) { 1.209 + return L""; 1.210 + } else { 1.211 +#if defined(OS_WIN) 1.212 + return result->second; 1.213 +#else 1.214 + return ASCIIToWide(result->second); 1.215 +#endif 1.216 + } 1.217 +} 1.218 + 1.219 +#if defined(OS_WIN) 1.220 +std::vector<std::wstring> CommandLine::GetLooseValues() const { 1.221 + return loose_values_; 1.222 +} 1.223 +std::wstring CommandLine::program() const { 1.224 + return program_; 1.225 +} 1.226 +#else 1.227 +std::vector<std::wstring> CommandLine::GetLooseValues() const { 1.228 + std::vector<std::wstring> values; 1.229 + for (size_t i = 0; i < loose_values_.size(); ++i) 1.230 + values.push_back(ASCIIToWide(loose_values_[i])); 1.231 + return values; 1.232 +} 1.233 +std::wstring CommandLine::program() const { 1.234 + DCHECK(argv_.size() > 0); 1.235 + return ASCIIToWide(argv_[0]); 1.236 +} 1.237 +#endif 1.238 + 1.239 + 1.240 +// static 1.241 +std::wstring CommandLine::PrefixedSwitchString( 1.242 + const std::wstring& switch_string) { 1.243 + return StringPrintf(L"%ls%ls", 1.244 + kSwitchPrefixes[0], 1.245 + switch_string.c_str()); 1.246 +} 1.247 + 1.248 +// static 1.249 +std::wstring CommandLine::PrefixedSwitchStringWithValue( 1.250 + const std::wstring& switch_string, const std::wstring& value_string) { 1.251 + if (value_string.empty()) { 1.252 + return PrefixedSwitchString(switch_string); 1.253 + } 1.254 + 1.255 + return StringPrintf(L"%ls%ls%ls%ls", 1.256 + kSwitchPrefixes[0], 1.257 + switch_string.c_str(), 1.258 + kSwitchValueSeparator, 1.259 + value_string.c_str()); 1.260 +} 1.261 + 1.262 +#if defined(OS_WIN) 1.263 +void CommandLine::AppendSwitch(const std::wstring& switch_string) { 1.264 + std::wstring prefixed_switch_string = PrefixedSwitchString(switch_string); 1.265 + command_line_string_.append(L" "); 1.266 + command_line_string_.append(prefixed_switch_string); 1.267 + switches_[WideToASCII(switch_string)] = L""; 1.268 +} 1.269 + 1.270 +// Quote a string if necessary, such that CommandLineToArgvW() will 1.271 +// always process it as a single argument. 1.272 +static std::wstring WindowsStyleQuote(const std::wstring& arg) { 1.273 + // We follow the quoting rules of CommandLineToArgvW. 1.274 + // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx 1.275 + if (arg.find_first_of(L" \\\"\t") == std::wstring::npos) { 1.276 + // No quoting necessary. 1.277 + return arg; 1.278 + } 1.279 + 1.280 + std::wstring out; 1.281 + out.push_back(L'"'); 1.282 + for (size_t i = 0; i < arg.size(); ++i) { 1.283 + if (arg[i] == '\\') { 1.284 + // Find the extent of this run of backslashes. 1.285 + size_t start = i, end = start + 1; 1.286 + for (; end < arg.size() && arg[end] == '\\'; ++end) 1.287 + /* empty */; 1.288 + size_t backslash_count = end - start; 1.289 + 1.290 + // Backslashes are escapes only if the run is followed by a double quote. 1.291 + // Since we also will end the string with a double quote, we escape for 1.292 + // either a double quote or the end of the string. 1.293 + if (end == arg.size() || arg[end] == '"') { 1.294 + // To quote, we need to output 2x as many backslashes. 1.295 + backslash_count *= 2; 1.296 + } 1.297 + for (size_t j = 0; j < backslash_count; ++j) 1.298 + out.push_back('\\'); 1.299 + 1.300 + // Advance i to one before the end to balance i++ in loop. 1.301 + i = end - 1; 1.302 + } else if (arg[i] == '"') { 1.303 + out.push_back('\\'); 1.304 + out.push_back('"'); 1.305 + } else { 1.306 + out.push_back(arg[i]); 1.307 + } 1.308 + } 1.309 + out.push_back('"'); 1.310 + 1.311 + return out; 1.312 +} 1.313 + 1.314 +void CommandLine::AppendSwitchWithValue(const std::wstring& switch_string, 1.315 + const std::wstring& value_string) { 1.316 + std::wstring quoted_value_string = WindowsStyleQuote(value_string); 1.317 + std::wstring combined_switch_string = 1.318 + PrefixedSwitchStringWithValue(switch_string, quoted_value_string); 1.319 + 1.320 + command_line_string_.append(L" "); 1.321 + command_line_string_.append(combined_switch_string); 1.322 + 1.323 + switches_[WideToASCII(switch_string)] = value_string; 1.324 +} 1.325 + 1.326 +void CommandLine::AppendLooseValue(const std::wstring& value) { 1.327 + command_line_string_.append(L" "); 1.328 + command_line_string_.append(WindowsStyleQuote(value)); 1.329 +} 1.330 + 1.331 +void CommandLine::AppendArguments(const CommandLine& other, 1.332 + bool include_program) { 1.333 + // Verify include_program is used correctly. 1.334 + // Logic could be shorter but this is clearer. 1.335 + DCHECK(include_program ? !other.program().empty() : other.program().empty()); 1.336 + command_line_string_ += L" " + other.command_line_string_; 1.337 + std::map<std::string, StringType>::const_iterator i; 1.338 + for (i = other.switches_.begin(); i != other.switches_.end(); ++i) 1.339 + switches_[i->first] = i->second; 1.340 +} 1.341 + 1.342 +void CommandLine::PrependWrapper(const std::wstring& wrapper) { 1.343 + // The wrapper may have embedded arguments (like "gdb --args"). In this case, 1.344 + // we don't pretend to do anything fancy, we just split on spaces. 1.345 + std::vector<std::wstring> wrapper_and_args; 1.346 + SplitString(wrapper, ' ', &wrapper_and_args); 1.347 + program_ = wrapper_and_args[0]; 1.348 + command_line_string_ = wrapper + L" " + command_line_string_; 1.349 +} 1.350 + 1.351 +#elif defined(OS_POSIX) 1.352 +void CommandLine::AppendSwitch(const std::wstring& switch_string) { 1.353 + std::string ascii_switch = WideToASCII(switch_string); 1.354 + argv_.push_back(kSwitchPrefixes[0] + ascii_switch); 1.355 + switches_[ascii_switch] = ""; 1.356 +} 1.357 + 1.358 +void CommandLine::AppendSwitchWithValue(const std::wstring& switch_string, 1.359 + const std::wstring& value_string) { 1.360 + std::string ascii_switch = WideToASCII(switch_string); 1.361 + std::string ascii_value = WideToASCII(value_string); 1.362 + 1.363 + argv_.push_back(kSwitchPrefixes[0] + ascii_switch + 1.364 + kSwitchValueSeparator + ascii_value); 1.365 + switches_[ascii_switch] = ascii_value; 1.366 +} 1.367 + 1.368 +void CommandLine::AppendLooseValue(const std::wstring& value) { 1.369 + argv_.push_back(WideToASCII(value)); 1.370 +} 1.371 + 1.372 +void CommandLine::AppendArguments(const CommandLine& other, 1.373 + bool include_program) { 1.374 + // Verify include_program is used correctly. 1.375 + // Logic could be shorter but this is clearer. 1.376 + DCHECK(include_program ? !other.program().empty() : other.program().empty()); 1.377 + 1.378 + size_t first_arg = include_program ? 0 : 1; 1.379 + for (size_t i = first_arg; i < other.argv_.size(); ++i) 1.380 + argv_.push_back(other.argv_[i]); 1.381 + std::map<std::string, StringType>::const_iterator i; 1.382 + for (i = other.switches_.begin(); i != other.switches_.end(); ++i) 1.383 + switches_[i->first] = i->second; 1.384 +} 1.385 + 1.386 +void CommandLine::PrependWrapper(const std::wstring& wrapper_wide) { 1.387 + // The wrapper may have embedded arguments (like "gdb --args"). In this case, 1.388 + // we don't pretend to do anything fancy, we just split on spaces. 1.389 + const std::string wrapper = WideToASCII(wrapper_wide); 1.390 + std::vector<std::string> wrapper_and_args; 1.391 + SplitString(wrapper, ' ', &wrapper_and_args); 1.392 + argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end()); 1.393 +} 1.394 + 1.395 +#endif