13#include "llvm/ADT/StringSwitch.h"
24 std::string &result) {
26 static const char *k_escapable_characters =
"\"\\";
29 size_t regular = quoted.find_first_of(k_escapable_characters);
30 result += quoted.substr(0, regular);
31 quoted = quoted.substr(regular);
34 if (quoted.empty() || quoted.front() ==
'"')
38 quoted = quoted.drop_front();
48 if (strchr(k_escapable_characters, quoted.front()) ==
nullptr)
51 result += quoted.front();
52 quoted = quoted.drop_front();
70 static const char *k_space_separators =
" \t";
71 return str.ltrim(k_space_separators);
79static std::tuple<std::string, char, llvm::StringRef>
92 char first_quote_char =
'\0';
94 bool arg_complete =
false;
97 size_t regular = command.find_first_of(
" \t\r\"'`\\");
98 arg += command.substr(0, regular);
99 command = command.substr(regular);
104 char special = command.front();
105 command = command.drop_front();
108 if (command.empty()) {
115 if (strchr(
" \t\\'\"`", command.front()) ==
nullptr)
118 arg += command.front();
119 command = command.drop_front();
135 if (first_quote_char ==
'\0')
136 first_quote_char = special;
143 size_t quoted = command.find(special);
144 arg += command.substr(0, quoted);
145 command = command.substr(quoted);
149 if (!command.empty())
150 command = command.drop_front();
154 }
while (!arg_complete);
156 return std::make_tuple(arg, first_quote_char, command);
160 size_t size = str.size();
163 ::memcpy(
data(), str.data() ? str.data() :
"",
size);
173 for (
const std::string &arg : list)
178 for (llvm::StringRef arg : args)
188 m_entries.emplace_back(entry.ref(), entry.quote);
191 m_argv.push_back(
nullptr);
205 s.
Format(
"{0}[{1}]=\"{2}\"\n", label_name, i++, entry.ref());
207 s.
Format(
"{0}[{1}]=NULL\n", label_name, i);
214 for (
size_t i = 0; i <
m_entries.size(); ++i) {
231 for (
size_t i = 0; i <
m_entries.size(); ++i) {
254 while (!command.empty()) {
260 m_argv.push_back(
nullptr);
281 return (
m_argv.size() > 1) ?
const_cast<const char **
>(
m_argv.data())
299 assert(
m_argv.back() ==
nullptr);
302 m_entries.emplace_back(entry.ref(), entry.quote);
305 m_argv.push_back(
nullptr);
312 assert(
m_argv.back() ==
nullptr);
314 for (
auto arg : llvm::ArrayRef(argv, argc)) {
319 m_argv.push_back(
nullptr);
329 assert(
m_argv.back() ==
nullptr);
340 assert(
m_argv.back() ==
nullptr);
360 auto args = llvm::ArrayRef(argv, argc);
363 for (
size_t i = 0; i < args.size(); ++i) {
365 ((args[i][0] ==
'\'') || (args[i][0] ==
'"') || (args[i][0] ==
'`'))
381 m_argv.push_back(
nullptr);
385 llvm::StringRef unsafe_arg) {
386 struct ShellDescriptor {
387 llvm::StringRef m_basename;
388 llvm::StringRef m_escapables;
391 static ShellDescriptor g_Shells[] = {{
"bash",
" '\"<>()&;"},
392 {
"fish",
" '\"<>()&\\|;"},
393 {
"tcsh",
" '\"<>()&;"},
394 {
"zsh",
" '\"<>()&;\\|"},
395 {
"sh",
" '\"<>()&;"}};
398 llvm::StringRef escapables =
" '\"";
401 if (!basename.empty()) {
402 for (
const auto &Shell : g_Shells) {
403 if (Shell.m_basename == basename) {
404 escapables = Shell.m_escapables;
410 std::string safe_arg;
411 safe_arg.reserve(unsafe_arg.size());
413 for (
char c : unsafe_arg) {
414 if (escapables.contains(c))
415 safe_arg.push_back(
'\\');
416 safe_arg.push_back(c);
423 return llvm::StringSwitch<lldb::Encoding>(s)
428 .Default(fail_value);
434 uint32_t result = llvm::StringSwitch<uint32_t>(s)
456 for (
const char *p = src; *p !=
'\0'; ++p) {
457 size_t non_special_chars = ::strcspn(p,
"\\");
458 if (non_special_chars > 0) {
459 dst.append(p, non_special_chars);
460 p += non_special_chars;
503 char oct_str[5] = {
'\0',
'\0',
'\0',
'\0',
'\0'};
506 for (i = 0; (p[i] >=
'0' && p[i] <=
'7') && i < 4; ++i)
513 unsigned long octal_value = ::strtoul(oct_str,
nullptr, 8);
514 if (octal_value <= UINT8_MAX) {
515 dst.append(1,
static_cast<char>(octal_value));
522 if (isxdigit(p[1])) {
527 char hex_str[3] = {*p,
'\0',
'\0'};
528 if (isxdigit(p[1])) {
533 unsigned long hex_value = strtoul(hex_str,
nullptr, 16);
534 if (hex_value <= UINT8_MAX)
535 dst.append(1,
static_cast<char>(hex_value));
555 for (
const char *p = src; *p !=
'\0'; ++p) {
556 if (llvm::isPrint(*p))
594 snprintf(octal_str,
sizeof(octal_str),
"%o", *p);
595 dst.append(octal_str);
605 const char *chars_to_escape =
nullptr;
606 switch (quote_char) {
608 chars_to_escape =
" \t\\'\"`";
611 chars_to_escape =
"$\"`\\";
617 assert(
false &&
"Unhandled quote character");
622 res.reserve(arg.size());
624 if (::strchr(chars_to_escape, c))
636 const llvm::StringRef original_args = arg_string;
644 if (!arg_string.starts_with(
"-")) {
645 m_suffix = std::string(original_args);
649 bool found_suffix =
false;
650 while (!arg_string.empty()) {
652 std::size_t prev_prefix_length = original_args.size() - arg_string.size();
660 if (!entry.
IsQuoted() && arg ==
"--") {
668 std::size_t prefix_length = original_args.size() - arg_string.size();
672 llvm::StringRef prefix = original_args.take_front(prev_prefix_length);
689 m_suffix = std::string(original_args);
static std::tuple< std::string, char, llvm::StringRef > ParseSingleArgument(llvm::StringRef command)
static size_t ArgvToArgc(const char **argv)
static llvm::StringRef ParseDoubleQuotes(llvm::StringRef quoted, std::string &result)
static llvm::StringRef ltrimForArgs(llvm::StringRef str)
A command line argument class.
char ** GetArgumentVector()
Gets the argument vector.
void Dump(Stream &s, const char *label_name="argv") const
Dump all entries to the stream s using label label_name.
static std::string EscapeLLDBCommandArgument(const std::string &arg, char quote_char)
void Unshift(llvm::StringRef arg_str, char quote_char='\0')
Inserts a class owned copy of arg_str at the beginning of the argument vector.
void Shift()
Shifts the first argument C string value of the array off the argument array.
void DeleteArgumentAtIndex(size_t idx)
Deletes the argument value at index if idx is a valid argument index.
static void ExpandEscapedCharacters(const char *src, std::string &dst)
ExpandEscapeSequences will change a string of possibly non-printable characters and expand them into ...
void SetArguments(size_t argc, const char **argv)
Sets the argument vector value, optionally copying all arguments into an internal buffer.
void AppendArguments(const Args &rhs)
static lldb::Encoding StringToEncoding(llvm::StringRef s, lldb::Encoding fail_value=lldb::eEncodingInvalid)
static uint32_t StringToGenericRegister(llvm::StringRef s)
Args(llvm::StringRef command=llvm::StringRef())
Construct with an option command string.
Args & operator=(const Args &rhs)
std::vector< ArgEntry > m_entries
size_t GetArgumentCount() const
Gets the number of arguments left in this command object.
void SetCommandString(llvm::StringRef command)
Sets the command string contained by this object.
static void EncodeEscapeSequences(const char *src, std::string &dst)
EncodeEscapeSequences will change the textual representation of common escape sequences like "\n" (tw...
void ReplaceArgumentAtIndex(size_t idx, llvm::StringRef arg_str, char quote_char='\0')
Replaces the argument value at index idx to arg_str if idx is a valid argument index.
void AppendArgument(llvm::StringRef arg_str, char quote_char='\0')
Appends a new argument to the end of the list argument list.
std::vector< char * > m_argv
The arguments as C strings with a trailing nullptr element.
static std::string GetShellSafeArgument(const FileSpec &shell, llvm::StringRef unsafe_arg)
const char * GetArgumentAtIndex(size_t idx) const
Gets the NULL terminated C string argument pointer for the argument at index idx.
bool GetCommandString(std::string &command) const
void InsertArgumentAtIndex(size_t idx, llvm::StringRef arg_str, char quote_char='\0')
Insert the argument value at index idx to arg_str.
const char ** GetConstArgumentVector() const
Gets the argument vector.
bool GetQuotedCommandString(std::string &command) const
void Clear()
Clear the arguments.
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
const ConstString & GetFilename() const
Filename string const get accessor.
bool m_has_args
Keeps track if we have parsed and stored any arguments.
void SetFromString(llvm::StringRef arg_string)
OptionsWithRaw(llvm::StringRef argument_string)
Parse the given string as a list of optional arguments with a raw suffix.
llvm::StringRef m_arg_string
llvm::StringRef m_arg_string_with_delimiter
A stream class that can stream formatted output to a file.
void Format(const char *format, Args &&... args)
size_t Indent(llvm::StringRef s="")
Indent the current line in the stream.
size_t EOL()
Output and End of Line character to the stream.
#define LLDB_REGNUM_GENERIC_RA
#define LLDB_REGNUM_GENERIC_ARG8
#define LLDB_REGNUM_GENERIC_ARG6
#define LLDB_REGNUM_GENERIC_SP
#define LLDB_REGNUM_GENERIC_ARG4
#define LLDB_REGNUM_GENERIC_ARG3
#define LLDB_REGNUM_GENERIC_ARG1
#define LLDB_REGNUM_GENERIC_ARG7
#define LLDB_REGNUM_GENERIC_FLAGS
#define LLDB_INVALID_REGNUM
#define LLDB_REGNUM_GENERIC_TP
#define LLDB_REGNUM_GENERIC_ARG2
#define LLDB_REGNUM_GENERIC_PC
#define LLDB_REGNUM_GENERIC_FP
#define LLDB_REGNUM_GENERIC_ARG5
A class that represents a running process on the host machine.
Encoding
Register encoding definitions.
@ eEncodingVector
vector registers
@ eEncodingUint
unsigned integer
@ eEncodingSint
signed integer
std::unique_ptr< char[]> ptr
bool IsQuoted() const
Returns true if this argument was quoted in any way.