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();
69static llvm::StringRef
ltrimForArgs(llvm::StringRef str,
size_t &shift) {
70 static const char *k_space_separators =
" \t";
71 llvm::StringRef result = str.ltrim(k_space_separators);
72 shift = result.data() - str.data();
81static std::tuple<std::string, char, llvm::StringRef>
94 char first_quote_char =
'\0';
96 bool arg_complete =
false;
99 size_t regular = command.find_first_of(
" \t\r\"'`\\");
100 arg += command.substr(0, regular);
101 command = command.substr(regular);
106 char special = command.front();
107 command = command.drop_front();
110 if (command.empty()) {
117 if (strchr(
" \t\\'\"`", command.front()) ==
nullptr)
120 arg += command.front();
121 command = command.drop_front();
137 if (first_quote_char ==
'\0')
138 first_quote_char = special;
145 size_t quoted = command.find(special);
146 arg += command.substr(0, quoted);
147 command = command.substr(quoted);
151 if (!command.empty())
152 command = command.drop_front();
156 }
while (!arg_complete);
158 return std::make_tuple(arg, first_quote_char, command);
162 std::optional<uint16_t> column)
163 : quote(quote), column(column) {
164 size_t size = str.size();
167 ::memcpy(
data(), str.data() ? str.data() :
"",
size);
177 for (
const std::string &arg : list)
182 for (llvm::StringRef arg : args)
192 m_entries.emplace_back(entry.ref(), entry.quote, entry.column);
195 m_argv.push_back(
nullptr);
209 s.
Format(
"{0}[{1}]=\"{2}\"\n", label_name, i++, entry.ref());
211 s.
Format(
"{0}[{1}]=NULL\n", label_name, i);
218 for (
size_t i = 0; i <
m_entries.size(); ++i) {
235 for (
size_t i = 0; i <
m_entries.size(); ++i) {
261 while (!command.empty()) {
262 const char *prev = command.data();
264 m_entries.emplace_back(arg, quote, column);
268 column += command.data() - prev;
270 m_argv.push_back(
nullptr);
291 return (
m_argv.size() > 1) ?
const_cast<const char **
>(
m_argv.data())
309 assert(
m_argv.back() ==
nullptr);
312 m_entries.emplace_back(entry.ref(), entry.quote, entry.column);
315 m_argv.push_back(
nullptr);
322 assert(
m_argv.back() ==
nullptr);
324 for (
auto arg : llvm::ArrayRef(argv, argc)) {
325 m_entries.emplace_back(arg,
'\0', std::nullopt);
329 m_argv.push_back(
nullptr);
339 assert(
m_argv.back() ==
nullptr);
350 assert(
m_argv.back() ==
nullptr);
370 auto args = llvm::ArrayRef(argv, argc);
373 for (
size_t i = 0; i < args.size(); ++i) {
375 ((args[i][0] ==
'\'') || (args[i][0] ==
'"') || (args[i][0] ==
'`'))
391 m_argv.push_back(
nullptr);
395 llvm::StringRef unsafe_arg) {
396 struct ShellDescriptor {
397 llvm::StringRef m_basename;
398 llvm::StringRef m_escapables;
401 static ShellDescriptor g_Shells[] = {{
"bash",
" '\"<>()&;"},
402 {
"fish",
" '\"<>()&\\|;"},
403 {
"tcsh",
" '\"<>()&;"},
404 {
"zsh",
" '\"<>()&;\\|"},
405 {
"sh",
" '\"<>()&;"}};
408 llvm::StringRef escapables =
" '\"";
411 if (!basename.empty()) {
412 for (
const auto &Shell : g_Shells) {
413 if (Shell.m_basename == basename) {
414 escapables = Shell.m_escapables;
420 std::string safe_arg;
421 safe_arg.reserve(unsafe_arg.size());
423 for (
char c : unsafe_arg) {
424 if (escapables.contains(c))
425 safe_arg.push_back(
'\\');
426 safe_arg.push_back(c);
433 return llvm::StringSwitch<lldb::Encoding>(s)
438 .Default(fail_value);
444 uint32_t result = llvm::StringSwitch<uint32_t>(s)
466 for (
const char *p = src; *p !=
'\0'; ++p) {
467 size_t non_special_chars = ::strcspn(p,
"\\");
468 if (non_special_chars > 0) {
469 dst.append(p, non_special_chars);
470 p += non_special_chars;
513 char oct_str[5] = {
'\0',
'\0',
'\0',
'\0',
'\0'};
516 for (i = 0; (p[i] >=
'0' && p[i] <=
'7') && i < 4; ++i)
523 unsigned long octal_value = ::strtoul(oct_str,
nullptr, 8);
524 if (octal_value <= UINT8_MAX) {
525 dst.append(1,
static_cast<char>(octal_value));
532 if (isxdigit(p[1])) {
537 char hex_str[3] = {*p,
'\0',
'\0'};
538 if (isxdigit(p[1])) {
543 unsigned long hex_value = strtoul(hex_str,
nullptr, 16);
544 if (hex_value <= UINT8_MAX)
545 dst.append(1,
static_cast<char>(hex_value));
565 for (
const char *p = src; *p !=
'\0'; ++p) {
566 if (llvm::isPrint(*p))
604 snprintf(octal_str,
sizeof(octal_str),
"%o", *p);
605 dst.append(octal_str);
615 const char *chars_to_escape =
nullptr;
616 switch (quote_char) {
618 chars_to_escape =
" \t\\'\"`";
621 chars_to_escape =
"$\"`\\";
627 assert(
false &&
"Unhandled quote character");
632 res.reserve(arg.size());
634 if (::strchr(chars_to_escape, c))
646 const llvm::StringRef original_args = arg_string;
655 if (!arg_string.starts_with(
"-")) {
656 m_suffix = std::string(original_args);
660 bool found_suffix =
false;
661 while (!arg_string.empty()) {
663 std::size_t prev_prefix_length = original_args.size() - arg_string.size();
671 if (!entry.
IsQuoted() && arg ==
"--") {
679 std::size_t prefix_length = original_args.size() - arg_string.size();
683 llvm::StringRef prefix = original_args.take_front(prev_prefix_length);
700 m_suffix = std::string(original_args);
static std::tuple< std::string, char, llvm::StringRef > ParseSingleArgument(llvm::StringRef command)
static llvm::StringRef ltrimForArgs(llvm::StringRef str, size_t &shift)
static size_t ArgvToArgc(const char **argv)
static llvm::StringRef ParseDoubleQuotes(llvm::StringRef quoted, std::string &result)
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.