ipc/chromium/src/base/command_line.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     5 #include "base/command_line.h"
     7 #if defined(OS_WIN)
     8 #include <windows.h>
     9 #include <shellapi.h>
    10 #endif
    12 #include <algorithm>
    14 #include "base/logging.h"
    15 #include "base/singleton.h"
    16 #include "base/string_piece.h"
    17 #include "base/string_util.h"
    18 #include "base/sys_string_conversions.h"
    20 CommandLine* CommandLine::current_process_commandline_ = NULL;
    22 // Since we use a lazy match, make sure that longer versions (like L"--")
    23 // are listed before shorter versions (like L"-") of similar prefixes.
    24 #if defined(OS_WIN)
    25 const wchar_t* const kSwitchPrefixes[] = {L"--", L"-", L"/"};
    26 const wchar_t kSwitchTerminator[] = L"--";
    27 const wchar_t kSwitchValueSeparator[] = L"=";
    28 #elif defined(OS_POSIX)
    29 // Unixes don't use slash as a switch.
    30 const char* const kSwitchPrefixes[] = {"--", "-"};
    31 const char kSwitchTerminator[] = "--";
    32 const char kSwitchValueSeparator[] = "=";
    33 #endif
    35 #if defined(OS_WIN)
    36 // Lowercase a string.  This is used to lowercase switch names.
    37 // Is this what we really want?  It seems crazy to me.  I've left it in
    38 // for backwards compatibility on Windows.
    39 static void Lowercase(std::wstring* parameter) {
    40   transform(parameter->begin(), parameter->end(), parameter->begin(),
    41             tolower);
    42 }
    43 #endif
    45 #if defined(OS_WIN)
    46 void CommandLine::ParseFromString(const std::wstring& command_line) {
    47   TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);
    49   if (command_line_string_.empty())
    50     return;
    52   int num_args = 0;
    53   wchar_t** args = NULL;
    55   args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);
    57   // Populate program_ with the trimmed version of the first arg.
    58   TrimWhitespace(args[0], TRIM_ALL, &program_);
    60   bool parse_switches = true;
    61   for (int i = 1; i < num_args; ++i) {
    62     std::wstring arg;
    63     TrimWhitespace(args[i], TRIM_ALL, &arg);
    65     if (!parse_switches) {
    66       loose_values_.push_back(arg);
    67       continue;
    68     }
    70     if (arg == kSwitchTerminator) {
    71       parse_switches = false;
    72       continue;
    73     }
    75     std::string switch_string;
    76     std::wstring switch_value;
    77     if (IsSwitch(arg, &switch_string, &switch_value)) {
    78       switches_[switch_string] = switch_value;
    79     } else {
    80       loose_values_.push_back(arg);
    81     }
    82   }
    84   if (args)
    85     LocalFree(args);
    86 }
    87 CommandLine::CommandLine(const std::wstring& program) {
    88   if (!program.empty()) {
    89     program_ = program;
    90     command_line_string_ = L'"' + program + L'"';
    91   }
    92 }
    93 #elif defined(OS_POSIX)
    94 CommandLine::CommandLine(int argc, const char* const* argv) {
    95   for (int i = 0; i < argc; ++i)
    96     argv_.push_back(argv[i]);
    97   InitFromArgv();
    98 }
    99 CommandLine::CommandLine(const std::vector<std::string>& argv) {
   100   argv_ = argv;
   101   InitFromArgv();
   102 }
   104 void CommandLine::InitFromArgv() {
   105   bool parse_switches = true;
   106   for (size_t i = 1; i < argv_.size(); ++i) {
   107     const std::string& arg = argv_[i];
   109     if (!parse_switches) {
   110       loose_values_.push_back(arg);
   111       continue;
   112     }
   114     if (arg == kSwitchTerminator) {
   115       parse_switches = false;
   116       continue;
   117     }
   119     std::string switch_string;
   120     std::string switch_value;
   121     if (IsSwitch(arg, &switch_string, &switch_value)) {
   122       switches_[switch_string] = switch_value;
   123     } else {
   124       loose_values_.push_back(arg);
   125     }
   126   }
   127 }
   129 CommandLine::CommandLine(const std::wstring& program) {
   130   argv_.push_back(WideToASCII(program));
   131 }
   132 #endif
   134 // static
   135 bool CommandLine::IsSwitch(const StringType& parameter_string,
   136                            std::string* switch_string,
   137                            StringType* switch_value) {
   138   switch_string->clear();
   139   switch_value->clear();
   141   for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
   142     StringType prefix(kSwitchPrefixes[i]);
   143     if (parameter_string.find(prefix) != 0)
   144       continue;
   146     const size_t switch_start = prefix.length();
   147     const size_t equals_position = parameter_string.find(
   148         kSwitchValueSeparator, switch_start);
   149     StringType switch_native;
   150     if (equals_position == StringType::npos) {
   151       switch_native = parameter_string.substr(switch_start);
   152     } else {
   153       switch_native = parameter_string.substr(
   154           switch_start, equals_position - switch_start);
   155       *switch_value = parameter_string.substr(equals_position + 1);
   156     }
   157 #if defined(OS_WIN)
   158     Lowercase(&switch_native);
   159     *switch_string = WideToASCII(switch_native);
   160 #else
   161     *switch_string = switch_native;
   162 #endif
   164     return true;
   165   }
   167   return false;
   168 }
   170 // static
   171 void CommandLine::Init(int argc, const char* const* argv) {
   172   DCHECK(current_process_commandline_ == NULL);
   173 #if defined(OS_WIN)
   174   current_process_commandline_ = new CommandLine;
   175   current_process_commandline_->ParseFromString(::GetCommandLineW());
   176 #elif defined(OS_POSIX)
   177   current_process_commandline_ = new CommandLine(argc, argv);
   178 #endif
   179 }
   181 void CommandLine::Terminate() {
   182   DCHECK(current_process_commandline_ != NULL);
   183   delete current_process_commandline_;
   184   current_process_commandline_ = NULL;
   185 }
   187 bool CommandLine::HasSwitch(const std::wstring& switch_string) const {
   188   std::wstring lowercased_switch(switch_string);
   189 #if defined(OS_WIN)
   190   Lowercase(&lowercased_switch);
   191 #endif
   192   return switches_.find(WideToASCII(lowercased_switch)) != switches_.end();
   193 }
   195 std::wstring CommandLine::GetSwitchValue(
   196     const std::wstring& switch_string) const {
   197   std::wstring lowercased_switch(switch_string);
   198 #if defined(OS_WIN)
   199   Lowercase(&lowercased_switch);
   200 #endif
   202   std::map<std::string, StringType>::const_iterator result =
   203       switches_.find(WideToASCII(lowercased_switch));
   205   if (result == switches_.end()) {
   206     return L"";
   207   } else {
   208 #if defined(OS_WIN)
   209     return result->second;
   210 #else
   211     return ASCIIToWide(result->second);
   212 #endif
   213   }
   214 }
   216 #if defined(OS_WIN)
   217 std::vector<std::wstring> CommandLine::GetLooseValues() const {
   218   return loose_values_;
   219 }
   220 std::wstring CommandLine::program() const {
   221   return program_;
   222 }
   223 #else
   224 std::vector<std::wstring> CommandLine::GetLooseValues() const {
   225   std::vector<std::wstring> values;
   226   for (size_t i = 0; i < loose_values_.size(); ++i)
   227     values.push_back(ASCIIToWide(loose_values_[i]));
   228   return values;
   229 }
   230 std::wstring CommandLine::program() const {
   231   DCHECK(argv_.size() > 0);
   232   return ASCIIToWide(argv_[0]);
   233 }
   234 #endif
   237 // static
   238 std::wstring CommandLine::PrefixedSwitchString(
   239     const std::wstring& switch_string) {
   240   return StringPrintf(L"%ls%ls",
   241                       kSwitchPrefixes[0],
   242                       switch_string.c_str());
   243 }
   245 // static
   246 std::wstring CommandLine::PrefixedSwitchStringWithValue(
   247     const std::wstring& switch_string, const std::wstring& value_string) {
   248   if (value_string.empty()) {
   249     return PrefixedSwitchString(switch_string);
   250   }
   252   return StringPrintf(L"%ls%ls%ls%ls",
   253                       kSwitchPrefixes[0],
   254                       switch_string.c_str(),
   255                       kSwitchValueSeparator,
   256                       value_string.c_str());
   257 }
   259 #if defined(OS_WIN)
   260 void CommandLine::AppendSwitch(const std::wstring& switch_string) {
   261   std::wstring prefixed_switch_string = PrefixedSwitchString(switch_string);
   262   command_line_string_.append(L" ");
   263   command_line_string_.append(prefixed_switch_string);
   264   switches_[WideToASCII(switch_string)] = L"";
   265 }
   267 // Quote a string if necessary, such that CommandLineToArgvW() will
   268 // always process it as a single argument.
   269 static std::wstring WindowsStyleQuote(const std::wstring& arg) {
   270   // We follow the quoting rules of CommandLineToArgvW.
   271   // http://msdn.microsoft.com/en-us/library/17w5ykft.aspx
   272   if (arg.find_first_of(L" \\\"\t") == std::wstring::npos) {
   273     // No quoting necessary.
   274     return arg;
   275   }
   277   std::wstring out;
   278   out.push_back(L'"');
   279   for (size_t i = 0; i < arg.size(); ++i) {
   280     if (arg[i] == '\\') {
   281       // Find the extent of this run of backslashes.
   282       size_t start = i, end = start + 1;
   283       for (; end < arg.size() && arg[end] == '\\'; ++end)
   284         /* empty */;
   285       size_t backslash_count = end - start;
   287       // Backslashes are escapes only if the run is followed by a double quote.
   288       // Since we also will end the string with a double quote, we escape for
   289       // either a double quote or the end of the string.
   290       if (end == arg.size() || arg[end] == '"') {
   291         // To quote, we need to output 2x as many backslashes.
   292         backslash_count *= 2;
   293       }
   294       for (size_t j = 0; j < backslash_count; ++j)
   295         out.push_back('\\');
   297       // Advance i to one before the end to balance i++ in loop.
   298       i = end - 1;
   299     } else if (arg[i] == '"') {
   300       out.push_back('\\');
   301       out.push_back('"');
   302     } else {
   303       out.push_back(arg[i]);
   304     }
   305   }
   306   out.push_back('"');
   308   return out;
   309 }
   311 void CommandLine::AppendSwitchWithValue(const std::wstring& switch_string,
   312                                         const std::wstring& value_string) {
   313   std::wstring quoted_value_string = WindowsStyleQuote(value_string);
   314   std::wstring combined_switch_string =
   315     PrefixedSwitchStringWithValue(switch_string, quoted_value_string);
   317   command_line_string_.append(L" ");
   318   command_line_string_.append(combined_switch_string);
   320   switches_[WideToASCII(switch_string)] = value_string;
   321 }
   323 void CommandLine::AppendLooseValue(const std::wstring& value) {
   324   command_line_string_.append(L" ");
   325   command_line_string_.append(WindowsStyleQuote(value));
   326 }
   328 void CommandLine::AppendArguments(const CommandLine& other,
   329                                   bool include_program) {
   330   // Verify include_program is used correctly.
   331   // Logic could be shorter but this is clearer.
   332   DCHECK(include_program ? !other.program().empty() : other.program().empty());
   333   command_line_string_ += L" " + other.command_line_string_;
   334   std::map<std::string, StringType>::const_iterator i;
   335   for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
   336     switches_[i->first] = i->second;
   337 }
   339 void CommandLine::PrependWrapper(const std::wstring& wrapper) {
   340   // The wrapper may have embedded arguments (like "gdb --args"). In this case,
   341   // we don't pretend to do anything fancy, we just split on spaces.
   342   std::vector<std::wstring> wrapper_and_args;
   343   SplitString(wrapper, ' ', &wrapper_and_args);
   344   program_ = wrapper_and_args[0];
   345   command_line_string_ = wrapper + L" " + command_line_string_;
   346 }
   348 #elif defined(OS_POSIX)
   349 void CommandLine::AppendSwitch(const std::wstring& switch_string) {
   350   std::string ascii_switch = WideToASCII(switch_string);
   351   argv_.push_back(kSwitchPrefixes[0] + ascii_switch);
   352   switches_[ascii_switch] = "";
   353 }
   355 void CommandLine::AppendSwitchWithValue(const std::wstring& switch_string,
   356                                         const std::wstring& value_string) {
   357   std::string ascii_switch = WideToASCII(switch_string);
   358   std::string ascii_value = WideToASCII(value_string);
   360   argv_.push_back(kSwitchPrefixes[0] + ascii_switch +
   361                   kSwitchValueSeparator + ascii_value);
   362   switches_[ascii_switch] = ascii_value;
   363 }
   365 void CommandLine::AppendLooseValue(const std::wstring& value) {
   366   argv_.push_back(WideToASCII(value));
   367 }
   369 void CommandLine::AppendArguments(const CommandLine& other,
   370                                   bool include_program) {
   371   // Verify include_program is used correctly.
   372   // Logic could be shorter but this is clearer.
   373   DCHECK(include_program ? !other.program().empty() : other.program().empty());
   375   size_t first_arg = include_program ? 0 : 1;
   376   for (size_t i = first_arg; i < other.argv_.size(); ++i)
   377     argv_.push_back(other.argv_[i]);
   378   std::map<std::string, StringType>::const_iterator i;
   379   for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
   380     switches_[i->first] = i->second;
   381 }
   383 void CommandLine::PrependWrapper(const std::wstring& wrapper_wide) {
   384   // The wrapper may have embedded arguments (like "gdb --args"). In this case,
   385   // we don't pretend to do anything fancy, we just split on spaces.
   386   const std::string wrapper = WideToASCII(wrapper_wide);
   387   std::vector<std::string> wrapper_and_args;
   388   SplitString(wrapper, ' ', &wrapper_and_args);
   389   argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end());
   390 }
   392 #endif

mercurial