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