ipc/chromium/src/base/command_line.cc

changeset 0
6474c204b198
     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

mercurial