15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This class works with command lines: building and parsing.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Arguments with prefixes ('--', '-', and on Windows, '/') are switches.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Switches will precede all other arguments without switch prefixes.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Switches can optionally have values, delimited by '=', e.g., "-switch=value".
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An argument of "--" will terminate switch parsing during initialization,
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// interpreting subsequent tokens as non-switch arguments, regardless of prefix.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// There is a singleton read-only CommandLine that represents the command line
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that the current process was started with.  It must be initialized in main().
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef BASE_COMMAND_LINE_H_
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define BASE_COMMAND_LINE_H_
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stddef.h>
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base_export.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FilePath;
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT CommandLine {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The native command line string type.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::wstring StringType;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::string StringType;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef StringType::value_type CharType;
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::vector<StringType> StringVector;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<std::string, StringType> SwitchMap;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A constructor for CommandLines that only carry switches and arguments.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum NoProgram { NO_PROGRAM };
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit CommandLine(NoProgram no_program);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a new command line with |program| as argv[0].
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit CommandLine(const base::FilePath& program);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct a new command line from an argument list.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine(int argc, const CharType* const* argv);
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit CommandLine(const StringVector& argv);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~CommandLine();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize the current process CommandLine singleton. On Windows, ignores
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // its arguments (we instead parse GetCommandLineW() directly) because we
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // don't trust the CRT's parsing of the command line, but it still must be
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // called to set up the command line. Returns false if initialization has
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already occurred, and true otherwise. Only the caller receiving a 'true'
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // return value should take responsibility for calling Reset.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static bool Init(int argc, const char* const* argv);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroys the current process CommandLine singleton. This is necessary if
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // you want to reset the base library to its initial state (for example, in an
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // outer library that needs to be able to terminate, and be re-initialized).
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If Init is called only once, as in main(), Reset() is not necessary.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Reset();
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the singleton CommandLine representing the current process's
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // command line. Note: returned value is mutable, but not thread safe;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only mutate if you know what you're doing!
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static CommandLine* ForCurrentProcess();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Returns true if the CommandLine has been initialized for the given process.
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  static bool InitializedForCurrentProcess();
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static CommandLine FromString(const std::wstring& command_line);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize from an argv vector.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitFromArgv(int argc, const CharType* const* argv);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitFromArgv(const StringVector& argv);
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Constructs and returns the represented command line string.
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CAUTION! This should be avoided on POSIX because quoting behavior is
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unclear.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringType GetCommandLineString() const;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Constructs and returns the represented arguments string.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CAUTION! This should be avoided on POSIX because quoting behavior is
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unclear.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringType GetArgumentsString() const;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the original command line string as a vector of strings.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const StringVector& argv() const { return argv_; }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get and Set the program part of the command line string (the first item).
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath GetProgram() const;
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetProgram(const base::FilePath& program);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns true if this command line contains the given switch.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (Switch names are case-insensitive).
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool HasSwitch(const std::string& switch_string) const;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the value associated with the given switch. If the switch has no
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // value or isn't present, this method returns the empty string.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string GetSwitchValueASCII(const std::string& switch_string) const;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath GetSwitchValuePath(const std::string& switch_string) const;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringType GetSwitchValueNative(const std::string& switch_string) const;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get a copy of all switches, along with their values.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const SwitchMap& GetSwitches() const { return switches_; }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Append a switch [with optional value] to the command line.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: Switches will precede arguments regardless of appending order.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AppendSwitch(const std::string& switch_string);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AppendSwitchPath(const std::string& switch_string,
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        const base::FilePath& path);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AppendSwitchNative(const std::string& switch_string,
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const StringType& value);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AppendSwitchASCII(const std::string& switch_string,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const std::string& value);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy a set of switches (and any values) from another command line.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commonly used when launching a subprocess.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CopySwitchesFrom(const CommandLine& source,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const char* const switches[],
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        size_t count);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get the remaining arguments to the command.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringVector GetArgs() const;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Append an argument to the command line. Note that the argument is quoted
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // properly such that it is interpreted as one argument to the target command.
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AppendArg is primarily for ASCII; non-ASCII input is interpreted as UTF-8.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: Switches will precede arguments regardless of appending order.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AppendArg(const std::string& value);
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AppendArgPath(const base::FilePath& value);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AppendArgNative(const StringType& value);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Append the switches and arguments from another command line to this one.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If |include_program| is true, include |other|'s program as well.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void AppendArguments(const CommandLine& other, bool include_program);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Insert a command before the current command.
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Common for debuggers, like "valgrind" or "gdb --args".
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PrependWrapper(const StringType& wrapper);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize by parsing the given command line string.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The program name is assumed to be the first item in the string.
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ParseFromString(const std::wstring& command_line);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disallow default constructor; a program name must be explicitly specified.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CommandLine();
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Allow the copy constructor. A common pattern is to copy of the current
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // process's command line and then add some flags to it. For example:
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   CommandLine cl(*CommandLine::ForCurrentProcess());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   cl.AppendSwitch(...);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The singleton CommandLine representing the current process's command line.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static CommandLine* current_process_commandline_;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The argv array: { program, [(--|-|/)switch[=value]]*, [--], [argument]* }
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringVector argv_;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parsed-out switch keys and values.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SwitchMap switches_;
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The index after the program and switches, any arguments start here.
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t begin_args_;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // BASE_COMMAND_LINE_H_
179