• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 // This class works with command lines: building and parsing.
6 // Switches can optionally have a value attached using an equals sign,
7 // as in "-switch=value".  Arguments that aren't prefixed with a
8 // switch prefix are considered "loose parameters".  Switch names are
9 // case-insensitive.  An argument of "--" will terminate switch
10 // parsing, causing everything after to be considered as loose
11 // parameters.
12 
13 // There is a singleton read-only CommandLine that represents the command
14 // line that the current process was started with.  It must be initialized
15 // in main() (or whatever the platform's equivalent function is).
16 
17 #ifndef BASE_COMMAND_LINE_H_
18 #define BASE_COMMAND_LINE_H_
19 
20 #include "build/build_config.h"
21 
22 #include <map>
23 #include <string>
24 #include <vector>
25 
26 #include "base/basictypes.h"
27 #include "base/file_path.h"
28 #include "base/logging.h"
29 #include "base/string_util.h"
30 
31 class InProcessBrowserTest;
32 
33 class CommandLine {
34  public:
35   // A constructor for CommandLines that are used only to carry arguments.
36   enum ArgumentsOnly { ARGUMENTS_ONLY };
37   explicit CommandLine(ArgumentsOnly args_only);
38 
39 #if defined(OS_WIN)
40   // Initialize by parsing the given command-line string.
41   // The program name is assumed to be the first item in the string.
42   void ParseFromString(const std::wstring& command_line);
FromString(const std::wstring & command_line)43   static CommandLine FromString(const std::wstring& command_line) {
44     CommandLine cmd;
45     cmd.ParseFromString(command_line);
46     return cmd;
47   }
48 #elif defined(OS_POSIX)
49   // Initialize from an argv vector.
50   void InitFromArgv(int argc, const char* const* argv);
51   void InitFromArgv(const std::vector<std::string>& argv);
52 
CommandLine(int argc,const char * const * argv)53   CommandLine(int argc, const char* const* argv) {
54     InitFromArgv(argc, argv);
55   }
CommandLine(const std::vector<std::string> & argv)56   explicit CommandLine(const std::vector<std::string>& argv) {
57     InitFromArgv(argv);
58   }
59 #endif
60 
61   // Construct a new, empty command line.
62   // |program| is the name of the program to run (aka argv[0]).
63   explicit CommandLine(const FilePath& program);
64 
65   // Initialize the current process CommandLine singleton.  On Windows,
66   // ignores its arguments (we instead parse GetCommandLineW()
67   // directly) because we don't trust the CRT's parsing of the command
68   // line, but it still must be called to set up the command line.
69   static void Init(int argc, const char* const* argv);
70 
71 #if defined(OS_POSIX) && !defined(OS_MACOSX)
72   // Sets the current process' arguments that show in "ps" etc. to those
73   // in |current_process_commandline_|. Used by the zygote host so that
74   // renderers show up with --type=renderer.
75   static void SetProcTitle();
76 #endif
77 
78   // Destroys the current process CommandLine singleton. This is necessary if
79   // you want to reset the base library to its initial state (for example in an
80   // outer library that needs to be able to terminate, and be re-initialized).
81   // If Init is called only once, e.g. in main(), calling Reset() is not
82   // necessary.
83   static void Reset();
84   // The same function snuck into this class under two different names;
85   // this one remains for backwards compat with the older o3d build.
Terminate()86   static void Terminate() { Reset(); }
87 
88   // Get the singleton CommandLine representing the current process's
89   // command line.  Note: returned value is mutable, but not thread safe;
90   // only mutate if you know what you're doing!
ForCurrentProcess()91   static CommandLine* ForCurrentProcess() {
92     DCHECK(current_process_commandline_);
93     return current_process_commandline_;
94   }
95 
96   // Returns true if this command line contains the given switch.
97   // (Switch names are case-insensitive.)
98   bool HasSwitch(const std::string& switch_string) const;
99 
100   // Deprecated version of the above.
HasSwitch(const std::wstring & switch_string)101   bool HasSwitch(const std::wstring& switch_string) const {
102     return HasSwitch(WideToASCII(switch_string));
103   }
104 
105   // Returns the value associated with the given switch.  If the
106   // switch has no value or isn't present, this method returns
107   // the empty string.
108   // TODO(evanm): move these into command_line.cpp once we've fixed the
109   // wstringness.
GetSwitchValueASCII(const std::string & switch_string)110   std::string GetSwitchValueASCII(const std::string& switch_string) const {
111     return WideToASCII(GetSwitchValue(switch_string));
112   }
GetSwitchValuePath(const std::string & switch_string)113   FilePath GetSwitchValuePath(const std::string& switch_string) const {
114     return FilePath::FromWStringHack(GetSwitchValue(switch_string));
115   }
116 
117   // Deprecated versions of the above.
118   std::wstring GetSwitchValue(const std::string& switch_string) const;
GetSwitchValue(const std::wstring & switch_string)119   std::wstring GetSwitchValue(const std::wstring& switch_string) const {
120     return GetSwitchValue(WideToASCII(switch_string));
121   }
122 
123   // Get the number of switches in this process.
GetSwitchCount()124   size_t GetSwitchCount() const { return switches_.size(); }
125 
126   // Get the remaining arguments to the command.
127   // WARNING: this is incorrect on POSIX; we must do string conversions.
128   std::vector<std::wstring> GetLooseValues() const;
129 
130 #if defined(OS_WIN)
131   // Returns the original command line string.
command_line_string()132   const std::wstring& command_line_string() const {
133     return command_line_string_;
134   }
135 #elif defined(OS_POSIX)
136   // Returns the original command line string as a vector of strings.
argv()137   const std::vector<std::string>& argv() const {
138     return argv_;
139   }
140 #endif
141 
142   // Returns the program part of the command line string (the first item).
GetProgram()143   FilePath GetProgram() const {
144     return FilePath::FromWStringHack(program());
145   }
146 
147   // Returns the program part of the command line string (the first item).
148   // Deprecated version of the above.
149   std::wstring program() const;
150 
151   // Return a copy of the string prefixed with a switch prefix.
152   // Used internally.
153   static std::wstring PrefixedSwitchString(const std::string& switch_string);
154 
155   // Return a copy of the string prefixed with a switch prefix,
156   // and appended with the given value. Used internally.
157   static std::wstring PrefixedSwitchStringWithValue(
158                         const std::string& switch_string,
159                         const std::wstring& value_string);
160 
161   // Appends the given switch string (preceded by a space and a switch
162   // prefix) to the given string.
163   void AppendSwitch(const std::string& switch_string);
164 
165   // Appends the given switch string (preceded by a space and a switch
166   // prefix) to the given string, with the given value attached.
167   void AppendSwitchWithValue(const std::string& switch_string,
168                              const std::wstring& value_string);
AppendSwitchWithValue(const std::string & switch_string,const std::string & value_string)169   void AppendSwitchWithValue(const std::string& switch_string,
170                              const std::string& value_string) {
171     AppendSwitchWithValue(switch_string, ASCIIToWide(value_string));
172   }
173 
174   // Append a loose value to the command line.
175   void AppendLooseValue(const std::wstring& value);
176 
177   // Append the arguments from another command line to this one.
178   // If |include_program| is true, include |other|'s program as well.
179   void AppendArguments(const CommandLine& other,
180                        bool include_program);
181 
182   // On POSIX systems it's common to run processes via a wrapper (like
183   // "valgrind" or "gdb --args").
184   void PrependWrapper(const std::wstring& wrapper);
185 
186  private:
187   friend class InProcessBrowserTest;
188 
CommandLine()189   CommandLine() {}
190 
191   // Used by InProcessBrowserTest.
ForCurrentProcessMutable()192   static CommandLine* ForCurrentProcessMutable() {
193     DCHECK(current_process_commandline_);
194     return current_process_commandline_;
195   }
196 
197   // The singleton CommandLine instance representing the current process's
198   // command line.
199   static CommandLine* current_process_commandline_;
200 
201   // We store a platform-native version of the command line, used when building
202   // up a new command line to be executed.  This ifdef delimits that code.
203 
204 #if defined(OS_WIN)
205   // The quoted, space-separated command-line string.
206   std::wstring command_line_string_;
207 
208   // The name of the program.
209   std::wstring program_;
210 
211   // The type of native command line arguments.
212   typedef std::wstring StringType;
213 
214 #elif defined(OS_POSIX)
215   // The argv array, with the program name in argv_[0].
216   std::vector<std::string> argv_;
217 
218   // The type of native command line arguments.
219   typedef std::string StringType;
220 #endif
221 
222   // Returns true and fills in |switch_string| and |switch_value|
223   // if |parameter_string| represents a switch.
224   static bool IsSwitch(const StringType& parameter_string,
225                        std::string* switch_string,
226                        StringType* switch_value);
227 
228   // Parsed-out values.
229   std::map<std::string, StringType> switches_;
230 
231   // Non-switch command-line arguments.
232   std::vector<StringType> loose_values_;
233 
234   // We allow copy constructors, because a common pattern is to grab a
235   // copy of the current process's command line and then add some
236   // flags to it.  E.g.:
237   //   CommandLine cl(*CommandLine::ForCurrentProcess());
238   //   cl.AppendSwitch(...);
239 };
240 
241 #endif  // BASE_COMMAND_LINE_H_
242