1 //===-- Args.cpp ------------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
13 // Other libraries and framework includes
15 #include "lldb/DataFormatters/FormatManager.h"
16 #include "lldb/Host/OptionParser.h"
17 #include "lldb/Interpreter/Args.h"
18 #include "lldb/Interpreter/CommandInterpreter.h"
19 #include "lldb/Interpreter/CommandReturnObject.h"
20 #include "lldb/Interpreter/Options.h"
21 #include "lldb/Target/Target.h"
22 #include "lldb/Utility/Stream.h"
23 #include "lldb/Utility/StreamString.h"
25 #include "llvm/ADT/STLExtras.h"
26 #include "llvm/ADT/StringExtras.h"
27 #include "llvm/ADT/StringSwitch.h"
30 using namespace lldb_private;
33 // A helper function for argument parsing.
34 // Parses the initial part of the first argument using normal double quote
36 // backslash escapes the double quote and itself. The parsed string is appended
38 // argument. The function returns the unparsed portion of the string, starting
41 static llvm::StringRef ParseDoubleQuotes(llvm::StringRef quoted,
42 std::string &result) {
43 // Inside double quotes, '\' and '"' are special.
44 static const char *k_escapable_characters = "\"\\";
46 // Skip over over regular characters and append them.
47 size_t regular = quoted.find_first_of(k_escapable_characters);
48 result += quoted.substr(0, regular);
49 quoted = quoted.substr(regular);
51 // If we have reached the end of string or the closing quote, we're done.
52 if (quoted.empty() || quoted.front() == '"')
55 // We have found a backslash.
56 quoted = quoted.drop_front();
59 // A lone backslash at the end of string, let's just append it.
64 // If the character after the backslash is not a whitelisted escapable
66 // leave the character sequence untouched.
67 if (strchr(k_escapable_characters, quoted.front()) == nullptr)
70 result += quoted.front();
71 quoted = quoted.drop_front();
77 static size_t ArgvToArgc(const char **argv) {
86 // A helper function for SetCommandString. Parses a single argument from the
87 // command string, processing quotes and backslashes in a shell-like manner.
88 // The function returns a tuple consisting of the parsed argument, the quote
89 // char used, and the unparsed portion of the string starting at the first
90 // unqouted, unescaped whitespace character.
91 static std::tuple<std::string, char, llvm::StringRef>
92 ParseSingleArgument(llvm::StringRef command) {
93 // Argument can be split into multiple discontiguous pieces, for example:
95 // this would result in a single argument "Hello World" (without the quotes)
96 // since the quotes would be removed and there is not space between the
100 // Since we can have multiple quotes that form a single command
101 // in a command like: "Hello "world'!' (which will make a single
102 // argument "Hello world!") we remember the first quote character
103 // we encounter and use that for the quote character.
104 char first_quote_char = '\0';
106 bool arg_complete = false;
108 // Skip over over regular characters and append them.
109 size_t regular = command.find_first_of(" \t\"'`\\");
110 arg += command.substr(0, regular);
111 command = command.substr(regular);
116 char special = command.front();
117 command = command.drop_front();
120 if (command.empty()) {
125 // If the character after the backslash is not a whitelisted escapable
127 // leave the character sequence untouched.
128 if (strchr(" \t\\'\"`", command.front()) == nullptr)
131 arg += command.front();
132 command = command.drop_front();
138 // We are not inside any quotes, we just found a space after an
139 // argument. We are done.
146 // We found the start of a quote scope.
147 if (first_quote_char == '\0')
148 first_quote_char = special;
151 command = ParseDoubleQuotes(command, arg);
153 // For single quotes, we simply skip ahead to the matching quote
155 // (or the end of the string).
156 size_t quoted = command.find(special);
157 arg += command.substr(0, quoted);
158 command = command.substr(quoted);
161 // If we found a closing quote, skip it.
162 if (!command.empty())
163 command = command.drop_front();
167 } while (!arg_complete);
169 return std::make_tuple(arg, first_quote_char, command);
172 Args::ArgEntry::ArgEntry(llvm::StringRef str, char quote) : quote(quote) {
173 size_t size = str.size();
174 ptr.reset(new char[size + 1]);
176 ::memcpy(data(), str.data() ? str.data() : "", size);
178 ref = llvm::StringRef(c_str(), size);
181 //----------------------------------------------------------------------
183 //----------------------------------------------------------------------
184 Args::Args(llvm::StringRef command) { SetCommandString(command); }
186 Args::Args(const Args &rhs) { *this = rhs; }
188 Args &Args::operator=(const Args &rhs) {
193 for (auto &entry : rhs.m_entries) {
194 m_entries.emplace_back(entry.ref, entry.quote);
195 m_argv.push_back(m_entries.back().data());
197 m_argv.push_back(nullptr);
201 //----------------------------------------------------------------------
203 //----------------------------------------------------------------------
206 void Args::Dump(Stream &s, const char *label_name) const {
211 for (auto &entry : m_entries) {
213 s.Format("{0}[{1}]=\"{2}\"\n", label_name, i++, entry.ref);
215 s.Format("{0}[{1}]=NULL\n", label_name, i);
219 bool Args::GetCommandString(std::string &command) const {
222 for (size_t i = 0; i < m_entries.size(); ++i) {
225 command += m_entries[i].ref;
228 return !m_entries.empty();
231 bool Args::GetQuotedCommandString(std::string &command) const {
234 for (size_t i = 0; i < m_entries.size(); ++i) {
238 if (m_entries[i].quote) {
239 command += m_entries[i].quote;
240 command += m_entries[i].ref;
241 command += m_entries[i].quote;
243 command += m_entries[i].ref;
247 return !m_entries.empty();
250 void Args::SetCommandString(llvm::StringRef command) {
254 static const char *k_space_separators = " \t";
255 command = command.ltrim(k_space_separators);
258 while (!command.empty()) {
259 std::tie(arg, quote, command) = ParseSingleArgument(command);
260 m_entries.emplace_back(arg, quote);
261 m_argv.push_back(m_entries.back().data());
262 command = command.ltrim(k_space_separators);
264 m_argv.push_back(nullptr);
267 void Args::UpdateArgsAfterOptionParsing() {
268 assert(!m_argv.empty());
269 assert(m_argv.back() == nullptr);
271 // Now m_argv might be out of date with m_entries, so we need to fix that.
272 // This happens because getopt_long_only may permute the order of the
273 // arguments in argv, so we need to re-order the quotes and the refs array
275 for (size_t i = 0; i < m_argv.size() - 1; ++i) {
276 const char *argv = m_argv[i];
278 std::find_if(m_entries.begin() + i, m_entries.end(),
279 [argv](const ArgEntry &D) { return D.c_str() == argv; });
280 assert(pos != m_entries.end());
281 size_t distance = std::distance(m_entries.begin(), pos);
285 assert(distance > i);
287 std::swap(m_entries[i], m_entries[distance]);
288 assert(m_entries[i].ref.data() == m_argv[i]);
290 m_entries.resize(m_argv.size() - 1);
293 size_t Args::GetArgumentCount() const { return m_entries.size(); }
295 const char *Args::GetArgumentAtIndex(size_t idx) const {
296 if (idx < m_argv.size())
301 char Args::GetArgumentQuoteCharAtIndex(size_t idx) const {
302 if (idx < m_entries.size())
303 return m_entries[idx].quote;
307 char **Args::GetArgumentVector() {
308 assert(!m_argv.empty());
309 // TODO: functions like execve and posix_spawnp exhibit undefined behavior
310 // when argv or envp is null. So the code below is actually wrong. However,
311 // other code in LLDB depends on it being null. The code has been acting this
312 // way for some time, so it makes sense to leave it this way until someone
313 // has the time to come along and fix it.
314 return (m_argv.size() > 1) ? m_argv.data() : nullptr;
317 const char **Args::GetConstArgumentVector() const {
318 assert(!m_argv.empty());
319 return (m_argv.size() > 1) ? const_cast<const char **>(m_argv.data())
324 // Don't pop the last NULL terminator from the argv array
325 if (m_entries.empty())
327 m_argv.erase(m_argv.begin());
328 m_entries.erase(m_entries.begin());
331 void Args::Unshift(llvm::StringRef arg_str, char quote_char) {
332 InsertArgumentAtIndex(0, arg_str, quote_char);
335 void Args::AppendArguments(const Args &rhs) {
336 assert(m_argv.size() == m_entries.size() + 1);
337 assert(m_argv.back() == nullptr);
339 for (auto &entry : rhs.m_entries) {
340 m_entries.emplace_back(entry.ref, entry.quote);
341 m_argv.push_back(m_entries.back().data());
343 m_argv.push_back(nullptr);
346 void Args::AppendArguments(const char **argv) {
347 size_t argc = ArgvToArgc(argv);
349 assert(m_argv.size() == m_entries.size() + 1);
350 assert(m_argv.back() == nullptr);
352 for (auto arg : llvm::makeArrayRef(argv, argc)) {
353 m_entries.emplace_back(arg, '\0');
354 m_argv.push_back(m_entries.back().data());
357 m_argv.push_back(nullptr);
360 void Args::AppendArgument(llvm::StringRef arg_str, char quote_char) {
361 InsertArgumentAtIndex(GetArgumentCount(), arg_str, quote_char);
364 void Args::InsertArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
366 assert(m_argv.size() == m_entries.size() + 1);
367 assert(m_argv.back() == nullptr);
369 if (idx > m_entries.size())
371 m_entries.emplace(m_entries.begin() + idx, arg_str, quote_char);
372 m_argv.insert(m_argv.begin() + idx, m_entries[idx].data());
375 void Args::ReplaceArgumentAtIndex(size_t idx, llvm::StringRef arg_str,
377 assert(m_argv.size() == m_entries.size() + 1);
378 assert(m_argv.back() == nullptr);
380 if (idx >= m_entries.size())
383 if (arg_str.size() > m_entries[idx].ref.size()) {
384 m_entries[idx] = ArgEntry(arg_str, quote_char);
385 m_argv[idx] = m_entries[idx].data();
387 const char *src_data = arg_str.data() ? arg_str.data() : "";
388 ::memcpy(m_entries[idx].data(), src_data, arg_str.size());
389 m_entries[idx].ptr[arg_str.size()] = 0;
390 m_entries[idx].ref = m_entries[idx].ref.take_front(arg_str.size());
394 void Args::DeleteArgumentAtIndex(size_t idx) {
395 if (idx >= m_entries.size())
398 m_argv.erase(m_argv.begin() + idx);
399 m_entries.erase(m_entries.begin() + idx);
402 void Args::SetArguments(size_t argc, const char **argv) {
405 auto args = llvm::makeArrayRef(argv, argc);
406 m_entries.resize(argc);
407 m_argv.resize(argc + 1);
408 for (size_t i = 0; i < args.size(); ++i) {
410 ((args[i][0] == '\'') || (args[i][0] == '"') || (args[i][0] == '`'))
414 m_entries[i] = ArgEntry(args[i], quote);
415 m_argv[i] = m_entries[i].data();
419 void Args::SetArguments(const char **argv) {
420 SetArguments(ArgvToArgc(argv), argv);
423 Status Args::ParseOptions(Options &options, ExecutionContext *execution_context,
424 PlatformSP platform_sp, bool require_validation) {
427 Option *long_options = options.GetLongOptions();
428 if (long_options == nullptr) {
429 error.SetErrorStringWithFormat("invalid long options");
433 for (int i = 0; long_options[i].definition != nullptr; ++i) {
434 if (long_options[i].flag == nullptr) {
435 if (isprint8(long_options[i].val)) {
436 sstr << (char)long_options[i].val;
437 switch (long_options[i].definition->option_has_arg) {
439 case OptionParser::eNoArgument:
441 case OptionParser::eRequiredArgument:
444 case OptionParser::eOptionalArgument:
451 std::unique_lock<std::mutex> lock;
452 OptionParser::Prepare(lock);
455 int long_options_index = -1;
456 val = OptionParser::Parse(GetArgumentCount(), GetArgumentVector(),
457 sstr.GetString(), long_options,
458 &long_options_index);
462 // Did we get an error?
464 error.SetErrorStringWithFormat("unknown or ambiguous option");
467 // The option auto-set itself
471 ((Options *)&options)->OptionSeen(val);
473 // Lookup the long option index
474 if (long_options_index == -1) {
475 for (int i = 0; long_options[i].definition || long_options[i].flag ||
478 if (long_options[i].val == val) {
479 long_options_index = i;
484 // Call the callback with the option
485 if (long_options_index >= 0 &&
486 long_options[long_options_index].definition) {
487 const OptionDefinition *def = long_options[long_options_index].definition;
490 // User did not pass in an explicit platform. Try to grab
491 // from the execution context.
493 execution_context ? execution_context->GetTargetSP() : TargetSP();
494 platform_sp = target_sp ? target_sp->GetPlatform() : PlatformSP();
496 OptionValidator *validator = def->validator;
498 if (!platform_sp && require_validation) {
499 // Caller requires validation but we cannot validate as we
500 // don't have the mandatory platform against which to
502 error.SetErrorString("cannot validate options: "
503 "no platform available");
507 bool validation_failed = false;
509 // Ensure we have an execution context, empty or not.
510 ExecutionContext dummy_context;
511 ExecutionContext *exe_ctx_p =
512 execution_context ? execution_context : &dummy_context;
513 if (validator && !validator->IsValid(*platform_sp, *exe_ctx_p)) {
514 validation_failed = true;
515 error.SetErrorStringWithFormat("Option \"%s\" invalid. %s",
517 def->validator->LongConditionString());
521 // As long as validation didn't fail, we set the option value.
522 if (!validation_failed)
523 error = options.SetOptionValue(
525 (def->option_has_arg == OptionParser::eNoArgument)
527 : OptionParser::GetOptionArgument(),
530 error.SetErrorStringWithFormat("invalid option with value '%i'", val);
536 // Update our ARGV now that get options has consumed all the options
537 m_argv.erase(m_argv.begin(), m_argv.begin() + OptionParser::GetOptionIndex());
538 UpdateArgsAfterOptionParsing();
545 m_argv.push_back(nullptr);
548 lldb::addr_t Args::StringToAddress(const ExecutionContext *exe_ctx,
549 llvm::StringRef s, lldb::addr_t fail_value,
551 bool error_set = false;
554 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
559 llvm::StringRef sref = s;
561 lldb::addr_t addr = LLDB_INVALID_ADDRESS;
562 if (!s.getAsInteger(0, addr)) {
568 // Try base 16 with no prefix...
569 if (!s.getAsInteger(16, addr)) {
575 Target *target = nullptr;
576 if (!exe_ctx || !(target = exe_ctx->GetTargetPtr())) {
578 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
583 lldb::ValueObjectSP valobj_sp;
584 EvaluateExpressionOptions options;
585 options.SetCoerceToId(false);
586 options.SetUnwindOnError(true);
587 options.SetKeepInMemory(false);
588 options.SetTryAllThreads(true);
590 ExpressionResults expr_result =
591 target->EvaluateExpression(s, exe_ctx->GetFramePtr(), valobj_sp, options);
593 bool success = false;
594 if (expr_result == eExpressionCompleted) {
596 valobj_sp = valobj_sp->GetQualifiedRepresentationIfAvailable(
597 valobj_sp->GetDynamicValueType(), true);
598 // Get the address to watch.
600 addr = valobj_sp->GetValueAsUnsigned(fail_value, &success);
608 error_ptr->SetErrorStringWithFormat(
609 "address expression \"%s\" resulted in a value whose type "
610 "can't be converted to an address: %s",
611 s.str().c_str(), valobj_sp->GetTypeName().GetCString());
616 // Since the compiler can't handle things like "main + 12" we should
617 // try to do this for now. The compiler doesn't like adding offsets
618 // to function pointer types.
619 static RegularExpression g_symbol_plus_offset_regex(
620 "^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");
621 RegularExpression::Match regex_match(3);
622 if (g_symbol_plus_offset_regex.Execute(sref, ®ex_match)) {
627 if (regex_match.GetMatchAtIndex(s, 1, name)) {
628 if (regex_match.GetMatchAtIndex(s, 2, str)) {
631 if (regex_match.GetMatchAtIndex(s, 3, str)) {
632 if (!llvm::StringRef(str).getAsInteger(0, offset)) {
634 addr = StringToAddress(exe_ctx, name.c_str(),
635 LLDB_INVALID_ADDRESS, &error);
636 if (addr != LLDB_INVALID_ADDRESS) {
638 return addr + offset;
640 return addr - offset;
650 error_ptr->SetErrorStringWithFormat(
651 "address expression \"%s\" evaluation failed", s.str().c_str());
657 error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
663 const char *Args::StripSpaces(std::string &s, bool leading, bool trailing,
664 bool return_null_if_empty) {
665 static const char *k_white_space = " \t\v";
668 size_t pos = s.find_first_not_of(k_white_space);
669 if (pos == std::string::npos)
676 size_t rpos = s.find_last_not_of(k_white_space);
677 if (rpos != std::string::npos && rpos + 1 < s.size())
681 if (return_null_if_empty && s.empty())
686 bool Args::StringToBoolean(llvm::StringRef ref, bool fail_value,
691 if (ref.equals_lower("false") || ref.equals_lower("off") ||
692 ref.equals_lower("no") || ref.equals_lower("0")) {
694 } else if (ref.equals_lower("true") || ref.equals_lower("on") ||
695 ref.equals_lower("yes") || ref.equals_lower("1")) {
699 *success_ptr = false;
703 char Args::StringToChar(llvm::StringRef s, char fail_value, bool *success_ptr) {
705 *success_ptr = false;
714 bool Args::StringToVersion(llvm::StringRef string, uint32_t &major,
715 uint32_t &minor, uint32_t &update) {
723 llvm::StringRef major_str, minor_str, update_str;
725 std::tie(major_str, minor_str) = string.split('.');
726 std::tie(minor_str, update_str) = minor_str.split('.');
727 if (major_str.getAsInteger(10, major))
729 if (!minor_str.empty() && minor_str.getAsInteger(10, minor))
731 if (!update_str.empty() && update_str.getAsInteger(10, update))
737 const char *Args::GetShellSafeArgument(const FileSpec &shell,
738 const char *unsafe_arg,
739 std::string &safe_arg) {
740 struct ShellDescriptor {
741 ConstString m_basename;
742 const char *m_escapables;
745 static ShellDescriptor g_Shells[] = {{ConstString("bash"), " '\"<>()&"},
746 {ConstString("tcsh"), " '\"<>()&$"},
747 {ConstString("sh"), " '\"<>()&"}};
750 const char *escapables = " '\"";
752 if (auto basename = shell.GetFilename()) {
753 for (const auto &Shell : g_Shells) {
754 if (Shell.m_basename == basename) {
755 escapables = Shell.m_escapables;
761 safe_arg.assign(unsafe_arg);
763 while (prev_pos < safe_arg.size()) {
764 // Escape spaces and quotes
765 size_t pos = safe_arg.find_first_of(escapables, prev_pos);
766 if (pos != std::string::npos) {
767 safe_arg.insert(pos, 1, '\\');
772 return safe_arg.c_str();
775 int64_t Args::StringToOptionEnum(llvm::StringRef s,
776 OptionEnumValueElement *enum_values,
777 int32_t fail_value, Status &error) {
780 error.SetErrorString("invalid enumeration argument");
785 error.SetErrorString("empty enumeration string");
789 for (int i = 0; enum_values[i].string_value != nullptr; i++) {
790 llvm::StringRef this_enum(enum_values[i].string_value);
791 if (this_enum.startswith(s))
792 return enum_values[i].value;
796 strm.PutCString("invalid enumeration value, valid values are: ");
797 for (int i = 0; enum_values[i].string_value != nullptr; i++) {
798 strm.Printf("%s\"%s\"", i > 0 ? ", " : "", enum_values[i].string_value);
800 error.SetErrorString(strm.GetString());
805 Args::StringToScriptLanguage(llvm::StringRef s, lldb::ScriptLanguage fail_value,
810 if (s.equals_lower("python"))
811 return eScriptLanguagePython;
812 if (s.equals_lower("default"))
813 return eScriptLanguageDefault;
814 if (s.equals_lower("none"))
815 return eScriptLanguageNone;
818 *success_ptr = false;
822 Status Args::StringToFormat(const char *s, lldb::Format &format,
823 size_t *byte_size_ptr) {
824 format = eFormatInvalid;
830 char *format_char = nullptr;
831 unsigned long byte_size = ::strtoul(s, &format_char, 0);
832 if (byte_size != ULONG_MAX)
833 *byte_size_ptr = byte_size;
839 const bool partial_match_ok = true;
840 if (!FormatManager::GetFormatFromCString(s, partial_match_ok, format)) {
841 StreamString error_strm;
843 "Invalid format character or name '%s'. Valid values are:\n", s);
844 for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) {
845 char format_char = FormatManager::GetFormatAsFormatChar(f);
847 error_strm.Printf("'%c' or ", format_char);
849 error_strm.Printf("\"%s\"", FormatManager::GetFormatAsCString(f));
854 error_strm.PutCString(
855 "An optional byte size can precede the format character.\n");
856 error.SetErrorString(error_strm.GetString());
862 error.SetErrorStringWithFormat("%s option string", s ? "empty" : "invalid");
867 lldb::Encoding Args::StringToEncoding(llvm::StringRef s,
868 lldb::Encoding fail_value) {
869 return llvm::StringSwitch<lldb::Encoding>(s)
870 .Case("uint", eEncodingUint)
871 .Case("sint", eEncodingSint)
872 .Case("ieee754", eEncodingIEEE754)
873 .Case("vector", eEncodingVector)
874 .Default(fail_value);
877 uint32_t Args::StringToGenericRegister(llvm::StringRef s) {
879 return LLDB_INVALID_REGNUM;
880 uint32_t result = llvm::StringSwitch<uint32_t>(s)
881 .Case("pc", LLDB_REGNUM_GENERIC_PC)
882 .Case("sp", LLDB_REGNUM_GENERIC_SP)
883 .Case("fp", LLDB_REGNUM_GENERIC_FP)
884 .Cases("ra", "lr", LLDB_REGNUM_GENERIC_RA)
885 .Case("flags", LLDB_REGNUM_GENERIC_FLAGS)
886 .Case("arg1", LLDB_REGNUM_GENERIC_ARG1)
887 .Case("arg2", LLDB_REGNUM_GENERIC_ARG2)
888 .Case("arg3", LLDB_REGNUM_GENERIC_ARG3)
889 .Case("arg4", LLDB_REGNUM_GENERIC_ARG4)
890 .Case("arg5", LLDB_REGNUM_GENERIC_ARG5)
891 .Case("arg6", LLDB_REGNUM_GENERIC_ARG6)
892 .Case("arg7", LLDB_REGNUM_GENERIC_ARG7)
893 .Case("arg8", LLDB_REGNUM_GENERIC_ARG8)
894 .Default(LLDB_INVALID_REGNUM);
898 void Args::AddOrReplaceEnvironmentVariable(llvm::StringRef env_var_name,
899 llvm::StringRef new_value) {
900 if (env_var_name.empty())
903 // Build the new entry.
904 std::string var_string(env_var_name);
905 if (!new_value.empty()) {
907 var_string += new_value;
911 if (ContainsEnvironmentVariable(env_var_name, &index)) {
912 ReplaceArgumentAtIndex(index, var_string);
916 // We didn't find it. Append it instead.
917 AppendArgument(var_string);
920 bool Args::ContainsEnvironmentVariable(llvm::StringRef env_var_name,
921 size_t *argument_index) const {
923 if (env_var_name.empty())
926 // Check each arg to see if it matches the env var name.
927 for (auto arg : llvm::enumerate(m_entries)) {
928 llvm::StringRef name, value;
929 std::tie(name, value) = arg.value().ref.split('=');
930 if (name != env_var_name)
934 *argument_index = arg.index();
938 // We didn't find a match.
942 size_t Args::FindArgumentIndexForOption(Option *long_options,
943 int long_options_index) const {
944 char short_buffer[3];
945 char long_buffer[255];
946 ::snprintf(short_buffer, sizeof(short_buffer), "-%c",
947 long_options[long_options_index].val);
948 ::snprintf(long_buffer, sizeof(long_buffer), "--%s",
949 long_options[long_options_index].definition->long_option);
951 for (auto entry : llvm::enumerate(m_entries)) {
952 if (entry.value().ref.startswith(short_buffer) ||
953 entry.value().ref.startswith(long_buffer))
954 return entry.index();
960 bool Args::IsPositionalArgument(const char *arg) {
964 bool is_positional = true;
965 const char *cptr = arg;
967 if (cptr[0] == '%') {
969 while (isdigit(cptr[0]))
972 is_positional = false;
974 is_positional = false;
976 return is_positional;
979 std::string Args::ParseAliasOptions(Options &options,
980 CommandReturnObject &result,
981 OptionArgVector *option_arg_vector,
982 llvm::StringRef raw_input_string) {
983 std::string result_string(raw_input_string);
986 Option *long_options = options.GetLongOptions();
988 if (long_options == nullptr) {
989 result.AppendError("invalid long options");
990 result.SetStatus(eReturnStatusFailed);
991 return result_string;
994 for (i = 0; long_options[i].definition != nullptr; ++i) {
995 if (long_options[i].flag == nullptr) {
996 sstr << (char)long_options[i].val;
997 switch (long_options[i].definition->option_has_arg) {
999 case OptionParser::eNoArgument:
1001 case OptionParser::eRequiredArgument:
1004 case OptionParser::eOptionalArgument:
1011 std::unique_lock<std::mutex> lock;
1012 OptionParser::Prepare(lock);
1013 result.SetStatus(eReturnStatusSuccessFinishNoResult);
1016 int long_options_index = -1;
1017 val = OptionParser::Parse(GetArgumentCount(), GetArgumentVector(),
1018 sstr.GetString(), long_options,
1019 &long_options_index);
1025 result.AppendError("unknown or ambiguous option");
1026 result.SetStatus(eReturnStatusFailed);
1033 options.OptionSeen(val);
1035 // Look up the long option index
1036 if (long_options_index == -1) {
1037 for (int j = 0; long_options[j].definition || long_options[j].flag ||
1038 long_options[j].val;
1040 if (long_options[j].val == val) {
1041 long_options_index = j;
1047 // See if the option takes an argument, and see if one was supplied.
1048 if (long_options_index == -1) {
1049 result.AppendErrorWithFormat("Invalid option with value '%c'.\n", val);
1050 result.SetStatus(eReturnStatusFailed);
1051 return result_string;
1054 StreamString option_str;
1055 option_str.Printf("-%c", val);
1056 const OptionDefinition *def = long_options[long_options_index].definition;
1058 (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1060 const char *option_arg = nullptr;
1062 case OptionParser::eRequiredArgument:
1063 if (OptionParser::GetOptionArgument() == nullptr) {
1064 result.AppendErrorWithFormat(
1065 "Option '%s' is missing argument specifier.\n",
1066 option_str.GetData());
1067 result.SetStatus(eReturnStatusFailed);
1068 return result_string;
1071 case OptionParser::eOptionalArgument:
1072 option_arg = OptionParser::GetOptionArgument();
1074 case OptionParser::eNoArgument:
1077 result.AppendErrorWithFormat("error with options table; invalid value "
1078 "in has_arg field for option '%c'.\n",
1080 result.SetStatus(eReturnStatusFailed);
1081 return result_string;
1084 option_arg = "<no-argument>";
1085 option_arg_vector->emplace_back(option_str.GetString(), has_arg,
1088 // Find option in the argument list; also see if it was supposed to take
1089 // an argument and if one was supplied. Remove option (and argument, if
1090 // given) from the argument list. Also remove them from the
1091 // raw_input_string, if one was passed in.
1092 size_t idx = FindArgumentIndexForOption(long_options, long_options_index);
1093 if (idx == size_t(-1))
1096 if (!result_string.empty()) {
1097 auto tmp_arg = m_entries[idx].ref;
1098 size_t pos = result_string.find(tmp_arg);
1099 if (pos != std::string::npos)
1100 result_string.erase(pos, tmp_arg.size());
1102 ReplaceArgumentAtIndex(idx, llvm::StringRef());
1103 if ((long_options[long_options_index].definition->option_has_arg !=
1104 OptionParser::eNoArgument) &&
1105 (OptionParser::GetOptionArgument() != nullptr) &&
1106 (idx + 1 < GetArgumentCount()) &&
1107 (m_entries[idx + 1].ref == OptionParser::GetOptionArgument())) {
1108 if (result_string.size() > 0) {
1109 auto tmp_arg = m_entries[idx + 1].ref;
1110 size_t pos = result_string.find(tmp_arg);
1111 if (pos != std::string::npos)
1112 result_string.erase(pos, tmp_arg.size());
1114 ReplaceArgumentAtIndex(idx + 1, llvm::StringRef());
1117 return result_string;
1120 void Args::ParseArgsForCompletion(Options &options,
1121 OptionElementVector &option_element_vector,
1122 uint32_t cursor_index) {
1124 Option *long_options = options.GetLongOptions();
1125 option_element_vector.clear();
1127 if (long_options == nullptr) {
1131 // Leading : tells getopt to return a : for a missing option argument AND
1132 // to suppress error messages.
1135 for (int i = 0; long_options[i].definition != nullptr; ++i) {
1136 if (long_options[i].flag == nullptr) {
1137 sstr << (char)long_options[i].val;
1138 switch (long_options[i].definition->option_has_arg) {
1140 case OptionParser::eNoArgument:
1142 case OptionParser::eRequiredArgument:
1145 case OptionParser::eOptionalArgument:
1152 std::unique_lock<std::mutex> lock;
1153 OptionParser::Prepare(lock);
1154 OptionParser::EnableError(false);
1157 auto opt_defs = options.GetDefinitions();
1159 // Fooey... OptionParser::Parse permutes the GetArgumentVector to move the
1160 // options to the front. So we have to build another Arg and pass that to
1161 // OptionParser::Parse so it doesn't change the one we have.
1163 std::vector<char *> dummy_vec = m_argv;
1165 bool failed_once = false;
1166 uint32_t dash_dash_pos = -1;
1169 bool missing_argument = false;
1170 int long_options_index = -1;
1172 val = OptionParser::Parse(dummy_vec.size() - 1, &dummy_vec[0],
1173 sstr.GetString(), long_options,
1174 &long_options_index);
1177 // When we're completing a "--" which is the last option on line,
1183 // If this is a bare "--" we mark it as such so we can complete it
1184 // successfully later.
1185 // Handling the "--" is a little tricky, since that may mean end of
1186 // options or arguments, or the
1187 // user might want to complete options by long name. I make this work by
1188 // checking whether the
1189 // cursor is in the "--" argument, and if so I assume we're completing the
1190 // long option, otherwise
1191 // I let it pass to OptionParser::Parse which will terminate the option
1193 // Note, in either case we continue parsing the line so we can figure out
1194 // what other options
1195 // were passed. This will be useful when we come to restricting
1196 // completions based on what other
1197 // options we've seen on the line.
1199 if (static_cast<size_t>(OptionParser::GetOptionIndex()) <
1200 dummy_vec.size() - 1 &&
1201 (strcmp(dummy_vec[OptionParser::GetOptionIndex() - 1], "--") == 0)) {
1202 dash_dash_pos = OptionParser::GetOptionIndex() - 1;
1203 if (static_cast<size_t>(OptionParser::GetOptionIndex() - 1) ==
1205 option_element_vector.push_back(
1206 OptionArgElement(OptionArgElement::eBareDoubleDash,
1207 OptionParser::GetOptionIndex() - 1,
1208 OptionArgElement::eBareDoubleDash));
1214 } else if (val == '?') {
1215 option_element_vector.push_back(
1216 OptionArgElement(OptionArgElement::eUnrecognizedArg,
1217 OptionParser::GetOptionIndex() - 1,
1218 OptionArgElement::eUnrecognizedArg));
1220 } else if (val == 0) {
1222 } else if (val == ':') {
1223 // This is a missing argument.
1224 val = OptionParser::GetOptionErrorCause();
1225 missing_argument = true;
1228 ((Options *)&options)->OptionSeen(val);
1230 // Look up the long option index
1231 if (long_options_index == -1) {
1232 for (int j = 0; long_options[j].definition || long_options[j].flag ||
1233 long_options[j].val;
1235 if (long_options[j].val == val) {
1236 long_options_index = j;
1242 // See if the option takes an argument, and see if one was supplied.
1243 if (long_options_index >= 0) {
1244 int opt_defs_index = -1;
1245 for (size_t i = 0; i < opt_defs.size(); i++) {
1246 if (opt_defs[i].short_option != val)
1252 const OptionDefinition *def = long_options[long_options_index].definition;
1254 (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
1256 case OptionParser::eNoArgument:
1257 option_element_vector.push_back(OptionArgElement(
1258 opt_defs_index, OptionParser::GetOptionIndex() - 1, 0));
1260 case OptionParser::eRequiredArgument:
1261 if (OptionParser::GetOptionArgument() != nullptr) {
1263 if (missing_argument)
1266 arg_index = OptionParser::GetOptionIndex() - 1;
1268 option_element_vector.push_back(OptionArgElement(
1269 opt_defs_index, OptionParser::GetOptionIndex() - 2, arg_index));
1271 option_element_vector.push_back(OptionArgElement(
1272 opt_defs_index, OptionParser::GetOptionIndex() - 1, -1));
1275 case OptionParser::eOptionalArgument:
1276 if (OptionParser::GetOptionArgument() != nullptr) {
1277 option_element_vector.push_back(OptionArgElement(
1278 opt_defs_index, OptionParser::GetOptionIndex() - 2,
1279 OptionParser::GetOptionIndex() - 1));
1281 option_element_vector.push_back(OptionArgElement(
1282 opt_defs_index, OptionParser::GetOptionIndex() - 2,
1283 OptionParser::GetOptionIndex() - 1));
1287 // The options table is messed up. Here we'll just continue
1288 option_element_vector.push_back(
1289 OptionArgElement(OptionArgElement::eUnrecognizedArg,
1290 OptionParser::GetOptionIndex() - 1,
1291 OptionArgElement::eUnrecognizedArg));
1295 option_element_vector.push_back(
1296 OptionArgElement(OptionArgElement::eUnrecognizedArg,
1297 OptionParser::GetOptionIndex() - 1,
1298 OptionArgElement::eUnrecognizedArg));
1302 // Finally we have to handle the case where the cursor index points at a
1303 // single "-". We want to mark that in
1304 // the option_element_vector, but only if it is not after the "--". But it
1305 // turns out that OptionParser::Parse just ignores
1306 // an isolated "-". So we have to look it up by hand here. We only care if
1307 // it is AT the cursor position.
1308 // Note, a single quoted dash is not the same as a single dash...
1310 const ArgEntry &cursor = m_entries[cursor_index];
1311 if ((static_cast<int32_t>(dash_dash_pos) == -1 ||
1312 cursor_index < dash_dash_pos) &&
1313 cursor.quote == '\0' && cursor.ref == "-") {
1314 option_element_vector.push_back(
1315 OptionArgElement(OptionArgElement::eBareDash, cursor_index,
1316 OptionArgElement::eBareDash));
1320 void Args::EncodeEscapeSequences(const char *src, std::string &dst) {
1323 for (const char *p = src; *p != '\0'; ++p) {
1324 size_t non_special_chars = ::strcspn(p, "\\");
1325 if (non_special_chars > 0) {
1326 dst.append(p, non_special_chars);
1327 p += non_special_chars;
1333 ++p; // skip the slash
1336 dst.append(1, '\a');
1339 dst.append(1, '\b');
1342 dst.append(1, '\f');
1345 dst.append(1, '\n');
1348 dst.append(1, '\r');
1351 dst.append(1, '\t');
1354 dst.append(1, '\v');
1357 dst.append(1, '\\');
1360 dst.append(1, '\'');
1366 // 1 to 3 octal chars
1368 // Make a string that can hold onto the initial zero char,
1369 // up to 3 octal digits, and a terminating NULL.
1370 char oct_str[5] = {'\0', '\0', '\0', '\0', '\0'};
1373 for (i = 0; (p[i] >= '0' && p[i] <= '7') && i < 4; ++i)
1376 // We don't want to consume the last octal character since
1377 // the main for loop will do this for us, so we advance p by
1378 // one less than i (even if i is zero)
1380 unsigned long octal_value = ::strtoul(oct_str, nullptr, 8);
1381 if (octal_value <= UINT8_MAX) {
1382 dst.append(1, (char)octal_value);
1388 // hex number in the format
1389 if (isxdigit(p[1])) {
1390 ++p; // Skip the 'x'
1392 // Make a string that can hold onto two hex chars plus a
1394 char hex_str[3] = {*p, '\0', '\0'};
1395 if (isxdigit(p[1])) {
1396 ++p; // Skip the first of the two hex chars
1400 unsigned long hex_value = strtoul(hex_str, nullptr, 16);
1401 if (hex_value <= UINT8_MAX)
1402 dst.append(1, (char)hex_value);
1409 // Just desensitize any other character by just printing what
1410 // came after the '\'
1419 void Args::ExpandEscapedCharacters(const char *src, std::string &dst) {
1422 for (const char *p = src; *p != '\0'; ++p) {
1458 // Just encode as octal
1461 snprintf(octal_str, sizeof(octal_str), "%o", *p);
1462 dst.append(octal_str);
1470 std::string Args::EscapeLLDBCommandArgument(const std::string &arg,
1472 const char *chars_to_escape = nullptr;
1473 switch (quote_char) {
1475 chars_to_escape = " \t\\'\"`";
1478 chars_to_escape = "";
1481 chars_to_escape = "$\"`\\";
1484 assert(false && "Unhandled quote character");
1488 res.reserve(arg.size());
1489 for (char c : arg) {
1490 if (::strchr(chars_to_escape, c))
1491 res.push_back('\\');