LCOV - code coverage report
Current view: directory - ipc/chromium/src/base - command_line.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 108 49 45.4 %
Date: 2012-06-02 Functions: 18 7 38.9 %

       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.
       4                 : 
       5                 : #include "base/command_line.h"
       6                 : 
       7                 : #if defined(OS_WIN)
       8                 : #include <windows.h>
       9                 : #include <shellapi.h>
      10                 : #endif
      11                 : 
      12                 : #include <algorithm>
      13                 : 
      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"
      19                 : 
      20                 : CommandLine* CommandLine::current_process_commandline_ = NULL;
      21                 : 
      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
      34                 : 
      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
      44                 : 
      45                 : #if defined(OS_WIN)
      46                 : void CommandLine::ParseFromString(const std::wstring& command_line) {
      47                 :   TrimWhitespace(command_line, TRIM_ALL, &command_line_string_);
      48                 : 
      49                 :   if (command_line_string_.empty())
      50                 :     return;
      51                 : 
      52                 :   int num_args = 0;
      53                 :   wchar_t** args = NULL;
      54                 : 
      55                 :   args = CommandLineToArgvW(command_line_string_.c_str(), &num_args);
      56                 : 
      57                 :   // Populate program_ with the trimmed version of the first arg.
      58                 :   TrimWhitespace(args[0], TRIM_ALL, &program_);
      59                 : 
      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);
      64                 : 
      65                 :     if (!parse_switches) {
      66                 :       loose_values_.push_back(arg);
      67                 :       continue;
      68                 :     }
      69                 : 
      70                 :     if (arg == kSwitchTerminator) {
      71                 :       parse_switches = false;
      72                 :       continue;
      73                 :     }
      74                 : 
      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                 :   }
      83                 : 
      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            1443 : CommandLine::CommandLine(int argc, const char* const* argv) {
      95            2955 :   for (int i = 0; i < argc; ++i)
      96            1512 :     argv_.push_back(argv[i]);
      97            1443 :   InitFromArgv();
      98            1443 : }
      99               0 : CommandLine::CommandLine(const std::vector<std::string>& argv) {
     100               0 :   argv_ = argv;
     101               0 :   InitFromArgv();
     102               0 : }
     103                 : 
     104            1443 : void CommandLine::InitFromArgv() {
     105            1443 :   bool parse_switches = true;
     106            1512 :   for (size_t i = 1; i < argv_.size(); ++i) {
     107              69 :     const std::string& arg = argv_[i];
     108                 : 
     109              69 :     if (!parse_switches) {
     110               0 :       loose_values_.push_back(arg);
     111               0 :       continue;
     112                 :     }
     113                 : 
     114              69 :     if (arg == kSwitchTerminator) {
     115               0 :       parse_switches = false;
     116               0 :       continue;
     117                 :     }
     118                 : 
     119             138 :     std::string switch_string;
     120             138 :     std::string switch_value;
     121              69 :     if (IsSwitch(arg, &switch_string, &switch_value)) {
     122              25 :       switches_[switch_string] = switch_value;
     123                 :     } else {
     124              44 :       loose_values_.push_back(arg);
     125                 :     }
     126                 :   }
     127            1443 : }
     128                 : 
     129               0 : CommandLine::CommandLine(const std::wstring& program) {
     130               0 :   argv_.push_back(WideToASCII(program));
     131               0 : }
     132                 : #endif
     133                 : 
     134                 : // static
     135              69 : bool CommandLine::IsSwitch(const StringType& parameter_string,
     136                 :                            std::string* switch_string,
     137                 :                            StringType* switch_value) {
     138              69 :   switch_string->clear();
     139              69 :   switch_value->clear();
     140                 : 
     141             182 :   for (size_t i = 0; i < arraysize(kSwitchPrefixes); ++i) {
     142             276 :     StringType prefix(kSwitchPrefixes[i]);
     143             138 :     if (parameter_string.find(prefix) != 0)
     144             113 :       continue;
     145                 : 
     146              25 :     const size_t switch_start = prefix.length();
     147                 :     const size_t equals_position = parameter_string.find(
     148              25 :         kSwitchValueSeparator, switch_start);
     149              50 :     StringType switch_native;
     150              25 :     if (equals_position == StringType::npos) {
     151              25 :       switch_native = parameter_string.substr(switch_start);
     152                 :     } else {
     153                 :       switch_native = parameter_string.substr(
     154               0 :           switch_start, equals_position - switch_start);
     155               0 :       *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              25 :     *switch_string = switch_native;
     162                 : #endif
     163                 : 
     164              25 :     return true;
     165                 :   }
     166                 : 
     167              44 :   return false;
     168                 : }
     169                 : 
     170                 : // static
     171            1443 : void CommandLine::Init(int argc, const char* const* argv) {
     172            1443 :   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            1443 :   current_process_commandline_ = new CommandLine(argc, argv);
     178                 : #endif
     179            1443 : }
     180                 : 
     181            1419 : void CommandLine::Terminate() {
     182            1419 :   DCHECK(current_process_commandline_ != NULL);
     183            1419 :   delete current_process_commandline_;
     184            1419 :   current_process_commandline_ = NULL;
     185            1419 : }
     186                 : 
     187               1 : bool CommandLine::HasSwitch(const std::wstring& switch_string) const {
     188               2 :   std::wstring lowercased_switch(switch_string);
     189                 : #if defined(OS_WIN)
     190                 :   Lowercase(&lowercased_switch);
     191                 : #endif
     192               1 :   return switches_.find(WideToASCII(lowercased_switch)) != switches_.end();
     193                 : }
     194                 : 
     195               1 : std::wstring CommandLine::GetSwitchValue(
     196                 :     const std::wstring& switch_string) const {
     197               2 :   std::wstring lowercased_switch(switch_string);
     198                 : #if defined(OS_WIN)
     199                 :   Lowercase(&lowercased_switch);
     200                 : #endif
     201                 : 
     202                 :   std::map<std::string, StringType>::const_iterator result =
     203               1 :       switches_.find(WideToASCII(lowercased_switch));
     204                 : 
     205               1 :   if (result == switches_.end()) {
     206               1 :     return L"";
     207                 :   } else {
     208                 : #if defined(OS_WIN)
     209                 :     return result->second;
     210                 : #else
     211               0 :     return ASCIIToWide(result->second);
     212                 : #endif
     213                 :   }
     214                 : }
     215                 : 
     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               0 : std::vector<std::wstring> CommandLine::GetLooseValues() const {
     225               0 :   std::vector<std::wstring> values;
     226               0 :   for (size_t i = 0; i < loose_values_.size(); ++i)
     227               0 :     values.push_back(ASCIIToWide(loose_values_[i]));
     228                 :   return values;
     229                 : }
     230               0 : std::wstring CommandLine::program() const {
     231               0 :   DCHECK(argv_.size() > 0);
     232               0 :   return ASCIIToWide(argv_[0]);
     233                 : }
     234                 : #endif
     235                 : 
     236                 : 
     237                 : // static
     238               0 : std::wstring CommandLine::PrefixedSwitchString(
     239                 :     const std::wstring& switch_string) {
     240                 :   return StringPrintf(L"%ls%ls",
     241               0 :                       kSwitchPrefixes[0],
     242               0 :                       switch_string.c_str());
     243                 : }
     244                 : 
     245                 : // static
     246               0 : std::wstring CommandLine::PrefixedSwitchStringWithValue(
     247                 :     const std::wstring& switch_string, const std::wstring& value_string) {
     248               0 :   if (value_string.empty()) {
     249               0 :     return PrefixedSwitchString(switch_string);
     250                 :   }
     251                 : 
     252                 :   return StringPrintf(L"%ls%ls%ls%ls",
     253               0 :                       kSwitchPrefixes[0],
     254                 :                       switch_string.c_str(),
     255                 :                       kSwitchValueSeparator,
     256               0 :                       value_string.c_str());
     257                 : }
     258                 : 
     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                 : }
     266                 : 
     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                 :   }
     276                 : 
     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;
     286                 : 
     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('\\');
     296                 : 
     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('"');
     307                 : 
     308                 :   return out;
     309                 : }
     310                 : 
     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);
     316                 : 
     317                 :   command_line_string_.append(L" ");
     318                 :   command_line_string_.append(combined_switch_string);
     319                 : 
     320                 :   switches_[WideToASCII(switch_string)] = value_string;
     321                 : }
     322                 : 
     323                 : void CommandLine::AppendLooseValue(const std::wstring& value) {
     324                 :   command_line_string_.append(L" ");
     325                 :   command_line_string_.append(WindowsStyleQuote(value));
     326                 : }
     327                 : 
     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                 : }
     338                 : 
     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                 : }
     347                 : 
     348                 : #elif defined(OS_POSIX)
     349               0 : void CommandLine::AppendSwitch(const std::wstring& switch_string) {
     350               0 :   std::string ascii_switch = WideToASCII(switch_string);
     351               0 :   argv_.push_back(kSwitchPrefixes[0] + ascii_switch);
     352               0 :   switches_[ascii_switch] = "";
     353               0 : }
     354                 : 
     355               0 : void CommandLine::AppendSwitchWithValue(const std::wstring& switch_string,
     356                 :                                         const std::wstring& value_string) {
     357               0 :   std::string ascii_switch = WideToASCII(switch_string);
     358               0 :   std::string ascii_value = WideToASCII(value_string);
     359                 : 
     360               0 :   argv_.push_back(kSwitchPrefixes[0] + ascii_switch +
     361               0 :                   kSwitchValueSeparator + ascii_value);
     362               0 :   switches_[ascii_switch] = ascii_value;
     363               0 : }
     364                 : 
     365               0 : void CommandLine::AppendLooseValue(const std::wstring& value) {
     366               0 :   argv_.push_back(WideToASCII(value));
     367               0 : }
     368                 : 
     369               0 : 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               0 :   DCHECK(include_program ? !other.program().empty() : other.program().empty());
     374                 : 
     375               0 :   size_t first_arg = include_program ? 0 : 1;
     376               0 :   for (size_t i = first_arg; i < other.argv_.size(); ++i)
     377               0 :     argv_.push_back(other.argv_[i]);
     378               0 :   std::map<std::string, StringType>::const_iterator i;
     379               0 :   for (i = other.switches_.begin(); i != other.switches_.end(); ++i)
     380               0 :     switches_[i->first] = i->second;
     381               0 : }
     382                 : 
     383               0 : 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               0 :   const std::string wrapper = WideToASCII(wrapper_wide);
     387               0 :   std::vector<std::string> wrapper_and_args;
     388               0 :   SplitString(wrapper, ' ', &wrapper_and_args);
     389               0 :   argv_.insert(argv_.begin(), wrapper_and_args.begin(), wrapper_and_args.end());
     390               0 : }
     391                 : 
     392                 : #endif

Generated by: LCOV version 1.7