13f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// This class works with command lines: building and parsing.
6dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// Switches can optionally have a value attached using an equals sign, as in
7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// "-switch=value". Arguments that aren't prefixed with a switch prefix are
8dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// saved as extra arguments. An argument of "--" will terminate switch parsing,
9dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// causing everything after to be considered as extra arguments.
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// There is a singleton read-only CommandLine that represents the command line
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen// that the current process was started with.  It must be initialized in main().
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifndef BASE_COMMAND_LINE_H_
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#define BASE_COMMAND_LINE_H_
163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#pragma once
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <stddef.h>
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <map>
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <string>
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <vector>
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/base_api.h"
243f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "build/build_config.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickclass FilePath;
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass BASE_API CommandLine {
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
303f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#if defined(OS_WIN)
31dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // The native command line string type.
323f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  typedef std::wstring StringType;
333f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#elif defined(OS_POSIX)
343f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  typedef std::string StringType;
353f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#endif
363f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
37dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  typedef std::vector<StringType> StringVector;
383f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  // The type of map for parsed-out switch key and values.
393f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  typedef std::map<std::string, StringType> SwitchMap;
403f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
41dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // A constructor for CommandLines that only carry switches and arguments.
42731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  enum NoProgram { NO_PROGRAM };
43731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  explicit CommandLine(NoProgram no_program);
443f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
45dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Construct a new command line with |program| as argv[0].
463f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  explicit CommandLine(const FilePath& program);
473f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
483f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#if defined(OS_POSIX)
493f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen  CommandLine(int argc, const char* const* argv);
50dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  explicit CommandLine(const StringVector& argv);
513f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#endif
523f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ~CommandLine();
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
55dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Initialize the current process CommandLine singleton. On Windows, ignores
56dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // its arguments (we instead parse GetCommandLineW() directly) because we
57dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // don't trust the CRT's parsing of the command line, but it still must be
58dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // called to set up the command line.
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void Init(int argc, const char* const* argv);
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Destroys the current process CommandLine singleton. This is necessary if
62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // you want to reset the base library to its initial state (for example, in an
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // outer library that needs to be able to terminate, and be re-initialized).
64dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // If Init is called only once, as in main(), Reset() is not necessary.
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static void Reset();
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Get the singleton CommandLine representing the current process's
68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // command line. Note: returned value is mutable, but not thread safe;
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // only mutate if you know what you're doing!
703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  static CommandLine* ForCurrentProcess();
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
72dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
73dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  static CommandLine FromString(const std::wstring& command_line);
74dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
75dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
76dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_POSIX)
77dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Initialize from an argv vector.
78dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void InitFromArgv(int argc, const char* const* argv);
79dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void InitFromArgv(const StringVector& argv);
80dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
82dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Returns the represented command line string.
83dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // CAUTION! This should be avoided because quoting behavior is unclear.
84dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  StringType command_line_string() const;
85dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
86dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_POSIX)
87dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Returns the original command line string as a vector of strings.
88dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const StringVector& argv() const { return argv_; }
89dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
90dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
91dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Returns the program part of the command line string (the first item).
92dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  FilePath GetProgram() const;
93dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Returns true if this command line contains the given switch.
95dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // (Switch names are case-insensitive).
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool HasSwitch(const std::string& switch_string) const;
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
98dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Returns the value associated with the given switch. If the switch has no
99dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // value or isn't present, this method returns the empty string.
1003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  std::string GetSwitchValueASCII(const std::string& switch_string) const;
1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  FilePath GetSwitchValuePath(const std::string& switch_string) const;
1023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  StringType GetSwitchValueNative(const std::string& switch_string) const;
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Get the number of switches in this process.
105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // TODO(msw): Remove unnecessary API.
106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  size_t GetSwitchCount() const;
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Get a copy of all switches, along with their values.
109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const SwitchMap& GetSwitches() const { return switches_; }
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
111dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Append a switch [with optional value] to the command line.
112dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // CAUTION! Appending a switch after the "--" switch terminator is futile!
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void AppendSwitch(const std::string& switch_string);
1143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void AppendSwitchPath(const std::string& switch_string, const FilePath& path);
1153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void AppendSwitchNative(const std::string& switch_string,
1163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                          const StringType& value);
1173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void AppendSwitchASCII(const std::string& switch_string,
1183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                         const std::string& value);
119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void AppendSwitches(const CommandLine& other);
120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Copy a set of switches (and any values) from another command line.
122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Commonly used when launching a subprocess.
123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void CopySwitchesFrom(const CommandLine& source, const char* const switches[],
124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen                        size_t count);
125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Get the remaining arguments to the command.
127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  const StringVector& args() const { return args_; }
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Append an argument to the command line. Note that the argument is quoted
130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // properly such that it is interpreted as one argument to the target command.
131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // AppendArg is primarily for ASCII; non-ASCII input is interpreted as UTF-8.
1323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void AppendArg(const std::string& value);
1333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void AppendArgPath(const FilePath& value);
1343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void AppendArgNative(const StringType& value);
135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void AppendArgs(const CommandLine& other);
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Append the arguments from another command line to this one.
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If |include_program| is true, include |other|'s program as well.
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void AppendArguments(const CommandLine& other,
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                       bool include_program);
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Insert a command before the current command.
143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Common for debuggers, like "valgrind" or "gdb --args".
1443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  void PrependWrapper(const StringType& wrapper);
1453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#if defined(OS_WIN)
147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Initialize by parsing the given command line string.
148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // The program name is assumed to be the first item in the string.
149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  void ParseFromString(const std::wstring& command_line);
150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#endif
1513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Disallow public default construction; a program name must be specified.
154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CommandLine();
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // The singleton CommandLine representing the current process's command line.
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static CommandLine* current_process_commandline_;
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We store a platform-native version of the command line, used when building
160dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // up a new command line to be executed. This ifdef delimits that code.
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // The quoted, space-separated command line string.
163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  StringType command_line_string_;
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The name of the program.
165dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  StringType program_;
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#elif defined(OS_POSIX)
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The argv array, with the program name in argv_[0].
168dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  StringVector argv_;
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
171dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Parsed-out switch keys and values.
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  SwitchMap switches_;
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Non-switch command line arguments.
175dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  StringVector args_;
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
177dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // Allow the copy constructor. A common pattern is to copy the current
178dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  // process's command line and then add some flags to it. For example:
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   CommandLine cl(*CommandLine::ForCurrentProcess());
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //   cl.AppendSwitch(...);
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif  // BASE_COMMAND_LINE_H_
184