• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- Args.h --------------------------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLDB_UTILITY_ARGS_H
10 #define LLDB_UTILITY_ARGS_H
11 
12 #include "lldb/Utility/Environment.h"
13 #include "lldb/lldb-private-types.h"
14 #include "lldb/lldb-types.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/YAMLTraits.h"
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 namespace lldb_private {
23 
24 /// \class Args Args.h "lldb/Utility/Args.h"
25 /// A command line argument class.
26 ///
27 /// The Args class is designed to be fed a command line. The command line is
28 /// copied into an internal buffer and then split up into arguments. Arguments
29 /// are space delimited if there are no quotes (single, double, or backtick
30 /// quotes) surrounding the argument. Spaces can be escaped using a \
31 /// character to avoid having to surround an argument that contains a space
32 /// with quotes.
33 class Args {
34 public:
35   struct ArgEntry {
36   private:
37     friend class Args;
38     friend struct llvm::yaml::MappingTraits<Args>;
39     friend struct llvm::yaml::MappingTraits<Args::ArgEntry>;
40 
41     std::unique_ptr<char[]> ptr;
42     char quote;
43 
44     char *data() { return ptr.get(); }
45 
46   public:
47     ArgEntry() = default;
48     ArgEntry(llvm::StringRef str, char quote);
49 
50     llvm::StringRef ref() const { return c_str(); }
51     const char *c_str() const { return ptr.get(); }
52 
53     /// Returns true if this argument was quoted in any way.
54     bool IsQuoted() const { return quote != '\0'; }
55     char GetQuoteChar() const { return quote; }
56   };
57 
58   /// Construct with an option command string.
59   ///
60   /// \param[in] command
61   ///     A NULL terminated command that will be copied and split up
62   ///     into arguments.
63   ///
64   /// \see Args::SetCommandString(llvm::StringRef)
65   Args(llvm::StringRef command = llvm::StringRef());
66 
67   Args(const Args &rhs);
68   explicit Args(const StringList &list);
69   explicit Args(llvm::ArrayRef<llvm::StringRef> args);
70 
71   Args &operator=(const Args &rhs);
72 
73   /// Destructor.
74   ~Args();
75 
76   explicit Args(const Environment &env) : Args() {
77     SetArguments(const_cast<const char **>(env.getEnvp().get()));
78   }
79 
80   explicit operator Environment() const { return GetConstArgumentVector(); }
81 
82   /// Dump all entries to the stream \a s using label \a label_name.
83   ///
84   /// If label_name is nullptr, the dump operation is skipped.
85   ///
86   /// \param[in] s
87   ///     The stream to which to dump all arguments in the argument
88   ///     vector.
89   /// \param[in] label_name
90   ///     The label_name to use as the label printed for each
91   ///     entry of the args like so:
92   ///       {label_name}[{index}]={value}
93   void Dump(Stream &s, const char *label_name = "argv") const;
94 
95   /// Sets the command string contained by this object.
96   ///
97   /// The command string will be copied and split up into arguments that can
98   /// be accessed via the accessor functions.
99   ///
100   /// \param[in] command
101   ///     A command StringRef that will be copied and split up
102   ///     into arguments.
103   ///
104   /// \see Args::GetArgumentCount() const
105   /// \see Args::GetArgumentAtIndex (size_t) const @see
106   /// Args::GetArgumentVector () \see Args::Shift () \see Args::Unshift (const
107   /// char *)
108   void SetCommandString(llvm::StringRef command);
109 
110   bool GetCommandString(std::string &command) const;
111 
112   bool GetQuotedCommandString(std::string &command) const;
113 
114   /// Gets the number of arguments left in this command object.
115   ///
116   /// \return
117   ///     The number or arguments in this object.
118   size_t GetArgumentCount() const;
119   bool empty() const { return GetArgumentCount() == 0; }
120 
121   /// Gets the NULL terminated C string argument pointer for the argument at
122   /// index \a idx.
123   ///
124   /// \return
125   ///     The NULL terminated C string argument pointer if \a idx is a
126   ///     valid argument index, NULL otherwise.
127   const char *GetArgumentAtIndex(size_t idx) const;
128 
129   llvm::ArrayRef<ArgEntry> entries() const { return m_entries; }
130 
131   using const_iterator = std::vector<ArgEntry>::const_iterator;
132 
133   const_iterator begin() const { return m_entries.begin(); }
134   const_iterator end() const { return m_entries.end(); }
135 
136   size_t size() const { return GetArgumentCount(); }
137   const ArgEntry &operator[](size_t n) const { return m_entries[n]; }
138 
139   /// Gets the argument vector.
140   ///
141   /// The value returned by this function can be used by any function that
142   /// takes and vector. The return value is just like \a argv in the standard
143   /// C entry point function:
144   ///     \code
145   ///         int main (int argc, const char **argv);
146   ///     \endcode
147   ///
148   /// \return
149   ///     An array of NULL terminated C string argument pointers that
150   ///     also has a terminating NULL C string pointer
151   char **GetArgumentVector();
152 
153   /// Gets the argument vector.
154   ///
155   /// The value returned by this function can be used by any function that
156   /// takes and vector. The return value is just like \a argv in the standard
157   /// C entry point function:
158   ///     \code
159   ///         int main (int argc, const char **argv);
160   ///     \endcode
161   ///
162   /// \return
163   ///     An array of NULL terminate C string argument pointers that
164   ///     also has a terminating NULL C string pointer
165   const char **GetConstArgumentVector() const;
166 
167   /// Gets the argument as an ArrayRef. Note that the return value does *not*
168   /// have a nullptr const char * at the end, as the size of the list is
169   /// embedded in the ArrayRef object.
170   llvm::ArrayRef<const char *> GetArgumentArrayRef() const {
171     return llvm::makeArrayRef(m_argv).drop_back();
172   }
173 
174   /// Appends a new argument to the end of the list argument list.
175   ///
176   /// \param[in] arg_str
177   ///     The new argument.
178   ///
179   /// \param[in] quote_char
180   ///     If the argument was originally quoted, put in the quote char here.
181   void AppendArgument(llvm::StringRef arg_str, char quote_char = '\0');
182 
183   void AppendArguments(const Args &rhs);
184 
185   void AppendArguments(const char **argv);
186 
187   /// Insert the argument value at index \a idx to \a arg_str.
188   ///
189   /// \param[in] idx
190   ///     The index of where to insert the argument.
191   ///
192   /// \param[in] arg_str
193   ///     The new argument.
194   ///
195   /// \param[in] quote_char
196   ///     If the argument was originally quoted, put in the quote char here.
197   void InsertArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
198                              char quote_char = '\0');
199 
200   /// Replaces the argument value at index \a idx to \a arg_str if \a idx is
201   /// a valid argument index.
202   ///
203   /// \param[in] idx
204   ///     The index of the argument that will have its value replaced.
205   ///
206   /// \param[in] arg_str
207   ///     The new argument.
208   ///
209   /// \param[in] quote_char
210   ///     If the argument was originally quoted, put in the quote char here.
211   void ReplaceArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
212                               char quote_char = '\0');
213 
214   /// Deletes the argument value at index
215   /// if \a idx is a valid argument index.
216   ///
217   /// \param[in] idx
218   ///     The index of the argument that will have its value replaced.
219   ///
220   void DeleteArgumentAtIndex(size_t idx);
221 
222   /// Sets the argument vector value, optionally copying all arguments into an
223   /// internal buffer.
224   ///
225   /// Sets the arguments to match those found in \a argv. All argument strings
226   /// will be copied into an internal buffers.
227   //
228   //  FIXME: Handle the quote character somehow.
229   void SetArguments(size_t argc, const char **argv);
230 
231   void SetArguments(const char **argv);
232 
233   /// Shifts the first argument C string value of the array off the argument
234   /// array.
235   ///
236   /// The string value will be freed, so a copy of the string should be made
237   /// by calling Args::GetArgumentAtIndex (size_t) const first and copying the
238   /// returned value before calling Args::Shift().
239   ///
240   /// \see Args::GetArgumentAtIndex (size_t) const
241   void Shift();
242 
243   /// Inserts a class owned copy of \a arg_str at the beginning of the
244   /// argument vector.
245   ///
246   /// A copy \a arg_str will be made.
247   ///
248   /// \param[in] arg_str
249   ///     The argument to push on the front of the argument stack.
250   ///
251   /// \param[in] quote_char
252   ///     If the argument was originally quoted, put in the quote char here.
253   void Unshift(llvm::StringRef arg_str, char quote_char = '\0');
254 
255   // Clear the arguments.
256   //
257   // For re-setting or blanking out the list of arguments.
258   void Clear();
259 
260   static lldb::Encoding
261   StringToEncoding(llvm::StringRef s,
262                    lldb::Encoding fail_value = lldb::eEncodingInvalid);
263 
264   static uint32_t StringToGenericRegister(llvm::StringRef s);
265 
266   static std::string GetShellSafeArgument(const FileSpec &shell,
267                                           llvm::StringRef unsafe_arg);
268 
269   // EncodeEscapeSequences will change the textual representation of common
270   // escape sequences like "\n" (two characters) into a single '\n'. It does
271   // this for all of the supported escaped sequences and for the \0ooo (octal)
272   // and \xXX (hex). The resulting "dst" string will contain the character
273   // versions of all supported escape sequences. The common supported escape
274   // sequences are: "\a", "\b", "\f", "\n", "\r", "\t", "\v", "\'", "\"", "\\".
275 
276   static void EncodeEscapeSequences(const char *src, std::string &dst);
277 
278   // ExpandEscapeSequences will change a string of possibly non-printable
279   // characters and expand them into text. So '\n' will turn into two
280   // characters like "\n" which is suitable for human reading. When a character
281   // is not printable and isn't one of the common in escape sequences listed in
282   // the help for EncodeEscapeSequences, then it will be encoded as octal.
283   // Printable characters are left alone.
284   static void ExpandEscapedCharacters(const char *src, std::string &dst);
285 
286   static std::string EscapeLLDBCommandArgument(const std::string &arg,
287                                                char quote_char);
288 
289 private:
290   friend struct llvm::yaml::MappingTraits<Args>;
291 
292   std::vector<ArgEntry> m_entries;
293   std::vector<char *> m_argv;
294 };
295 
296 /// \class OptionsWithRaw Args.h "lldb/Utility/Args.h"
297 /// A pair of an option list with a 'raw' string as a suffix.
298 ///
299 /// This class works similar to Args, but handles the case where we have a
300 /// trailing string that shouldn't be interpreted as a list of arguments but
301 /// preserved as is. It is also only useful for handling command line options
302 /// (e.g. '-foo bar -i0') that start with a dash.
303 ///
304 /// The leading option list is optional. If the first non-space character
305 /// in the string starts with a dash, and the string contains an argument
306 /// that is an unquoted double dash (' -- '), then everything up to the double
307 /// dash is parsed as a list of arguments. Everything after the double dash
308 /// is interpreted as the raw suffix string. Note that the space behind the
309 /// double dash is not part of the raw suffix.
310 ///
311 /// All strings not matching the above format as considered to be just a raw
312 /// string without any options.
313 ///
314 /// \see Args
315 class OptionsWithRaw {
316 public:
317   /// Parse the given string as a list of optional arguments with a raw suffix.
318   ///
319   /// See the class description for a description of the input format.
320   ///
321   /// \param[in] argument_string
322   ///     The string that should be parsed.
323   explicit OptionsWithRaw(llvm::StringRef argument_string);
324 
325   /// Returns true if there are any arguments before the raw suffix.
326   bool HasArgs() const { return m_has_args; }
327 
328   /// Returns the list of arguments.
329   ///
330   /// You can only call this method if HasArgs returns true.
331   Args &GetArgs() {
332     assert(m_has_args);
333     return m_args;
334   }
335 
336   /// Returns the list of arguments.
337   ///
338   /// You can only call this method if HasArgs returns true.
339   const Args &GetArgs() const {
340     assert(m_has_args);
341     return m_args;
342   }
343 
344   /// Returns the part of the input string that was used for parsing the
345   /// argument list. This string also includes the double dash that is used
346   /// for separating the argument list from the suffix.
347   ///
348   /// You can only call this method if HasArgs returns true.
349   llvm::StringRef GetArgStringWithDelimiter() const {
350     assert(m_has_args);
351     return m_arg_string_with_delimiter;
352   }
353 
354   /// Returns the part of the input string that was used for parsing the
355   /// argument list.
356   ///
357   /// You can only call this method if HasArgs returns true.
358   llvm::StringRef GetArgString() const {
359     assert(m_has_args);
360     return m_arg_string;
361   }
362 
363   /// Returns the raw suffix part of the parsed string.
364   const std::string &GetRawPart() const { return m_suffix; }
365 
366 private:
367   void SetFromString(llvm::StringRef arg_string);
368 
369   /// Keeps track if we have parsed and stored any arguments.
370   bool m_has_args = false;
371   Args m_args;
372   llvm::StringRef m_arg_string;
373   llvm::StringRef m_arg_string_with_delimiter;
374 
375   // FIXME: This should be a StringRef, but some of the calling code expect a
376   // C string here so only a real std::string is possible.
377   std::string m_suffix;
378 };
379 
380 } // namespace lldb_private
381 
382 namespace llvm {
383 namespace yaml {
384 template <> struct MappingTraits<lldb_private::Args::ArgEntry> {
385   class NormalizedArgEntry {
386   public:
387     NormalizedArgEntry(IO &) {}
388     NormalizedArgEntry(IO &, lldb_private::Args::ArgEntry &entry)
389         : value(entry.ref()), quote(entry.quote) {}
390     lldb_private::Args::ArgEntry denormalize(IO &) {
391       return lldb_private::Args::ArgEntry(value, quote);
392     }
393     StringRef value;
394     uint8_t quote;
395   };
396   static void mapping(IO &io, lldb_private::Args::ArgEntry &v);
397 };
398 template <> struct MappingTraits<lldb_private::Args> {
399   static void mapping(IO &io, lldb_private::Args &v);
400 };
401 } // namespace yaml
402 } // namespace llvm
403 
404 LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::Args::ArgEntry)
405 
406 #endif // LLDB_UTILITY_ARGS_H
407